package repository import ( "context" "fmt" "time" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/models" ) type VisitorSessionRepo struct { pool *pgxpool.Pool } func NewVisitorSessionRepo(pool *pgxpool.Pool) *VisitorSessionRepo { return &VisitorSessionRepo{pool: pool} } func (r *VisitorSessionRepo) Create(ctx context.Context, vs *models.VisitorSession) error { err := r.pool.QueryRow(ctx, `INSERT INTO visitor_sessions (user_id, coordinates, last_active_at) VALUES ($1, ST_SetSRID(ST_MakePoint($2, $3), 4326), $4) RETURNING id, created_at`, vs.UserID, vs.Lng, vs.Lat, vs.LastActiveAt, ).Scan(&vs.ID, &vs.CreatedAt) if err != nil { return fmt.Errorf("create visitor session: %w", err) } return nil } func (r *VisitorSessionRepo) GetByID(ctx context.Context, id string) (*models.VisitorSession, error) { row := r.pool.QueryRow(ctx, `SELECT id, user_id, ST_Y(coordinates::geometry) AS lat, ST_X(coordinates::geometry) AS lng, last_active_at, created_at FROM visitor_sessions WHERE id = $1`, id) return scanVisitorSession(row) } func (r *VisitorSessionRepo) UpdateLastActive(ctx context.Context, id string) error { _, err := r.pool.Exec(ctx, `UPDATE visitor_sessions SET last_active_at=$1 WHERE id=$2`, time.Now(), id) return err } func (r *VisitorSessionRepo) CountActive(ctx context.Context, since time.Duration) (int, error) { var count int err := r.pool.QueryRow(ctx, `SELECT COUNT(*) FROM visitor_sessions WHERE last_active_at > $1`, time.Now().Add(-since)).Scan(&count) if err != nil { return 0, fmt.Errorf("count active visitors: %w", err) } return count, nil } func scanVisitorSession(row interface{ Scan(dest ...any) error}) (*models.VisitorSession, error) { var vs models.VisitorSession err := row.Scan(&vs.ID, &vs.UserID, &vs.Lat, &vs.Lng, &vs.LastActiveAt, &vs.CreatedAt) if err != nil { if err == pgx.ErrNoRows { return nil, nil } return nil, err } return &vs, nil }