visitor_sessions.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package repository
  2. import (
  3. "context"
  4. "fmt"
  5. "time"
  6. "github.com/jackc/pgx/v5"
  7. "github.com/jackc/pgx/v5/pgxpool"
  8. "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/models"
  9. )
  10. type VisitorSessionRepo struct {
  11. pool *pgxpool.Pool
  12. }
  13. func NewVisitorSessionRepo(pool *pgxpool.Pool) *VisitorSessionRepo {
  14. return &VisitorSessionRepo{pool: pool}
  15. }
  16. func (r *VisitorSessionRepo) Create(ctx context.Context, vs *models.VisitorSession) error {
  17. err := r.pool.QueryRow(ctx,
  18. `INSERT INTO visitor_sessions (user_id, coordinates, last_active_at)
  19. VALUES ($1, ST_SetSRID(ST_MakePoint($2, $3), 4326), $4)
  20. RETURNING id, created_at`,
  21. vs.UserID, vs.Lng, vs.Lat, vs.LastActiveAt,
  22. ).Scan(&vs.ID, &vs.CreatedAt)
  23. if err != nil {
  24. return fmt.Errorf("create visitor session: %w", err)
  25. }
  26. return nil
  27. }
  28. func (r *VisitorSessionRepo) GetByID(ctx context.Context, id string) (*models.VisitorSession, error) {
  29. row := r.pool.QueryRow(ctx,
  30. `SELECT id, user_id, ST_Y(coordinates::geometry) AS lat, ST_X(coordinates::geometry) AS lng,
  31. last_active_at, created_at
  32. FROM visitor_sessions WHERE id = $1`, id)
  33. return scanVisitorSession(row)
  34. }
  35. func (r *VisitorSessionRepo) UpdateLastActive(ctx context.Context, id string) error {
  36. _, err := r.pool.Exec(ctx,
  37. `UPDATE visitor_sessions SET last_active_at=$1 WHERE id=$2`,
  38. time.Now(), id)
  39. return err
  40. }
  41. func (r *VisitorSessionRepo) CountActive(ctx context.Context, since time.Duration) (int, error) {
  42. var count int
  43. err := r.pool.QueryRow(ctx,
  44. `SELECT COUNT(*) FROM visitor_sessions WHERE last_active_at > $1`,
  45. time.Now().Add(-since)).Scan(&count)
  46. if err != nil {
  47. return 0, fmt.Errorf("count active visitors: %w", err)
  48. }
  49. return count, nil
  50. }
  51. func scanVisitorSession(row interface{ Scan(dest ...any) error}) (*models.VisitorSession, error) {
  52. var vs models.VisitorSession
  53. err := row.Scan(&vs.ID, &vs.UserID, &vs.Lat, &vs.Lng, &vs.LastActiveAt, &vs.CreatedAt)
  54. if err != nil {
  55. if err == pgx.ErrNoRows {
  56. return nil, nil
  57. }
  58. return nil, err
  59. }
  60. return &vs, nil
  61. }