1package sqlite
2
3import (
4 "context"
5 "database/sql"
6 "errors"
7 "time"
8
9 "github.com/bnema/dumber/internal/domain/entity"
10 "github.com/bnema/dumber/internal/domain/repository"
11 "github.com/bnema/dumber/internal/infrastructure/persistence/sqlite/sqlc"
12 "github.com/bnema/dumber/internal/logging"
13)
14
15type sessionRepo struct {
16 queries *sqlc.Queries
17}
18
19func NewSessionRepository(db *sql.DB) repository.SessionRepository {
20 return &sessionRepo{queries: sqlc.New(db)}
21}
22
23func (r *sessionRepo) Save(ctx context.Context, session *entity.Session) error {
24 log := logging.FromContext(ctx)
25 if err := session.Validate(); err != nil {
26 return err
27 }
28
29 log.Debug().Str("session", string(session.ID)).Str("type", string(session.Type)).Msg("saving session")
30
31 var endedAt sql.NullTime
32 if session.EndedAt != nil {
33 endedAt = sql.NullTime{Time: session.EndedAt.UTC(), Valid: true}
34 }
35
36 return r.queries.InsertSession(ctx, sqlc.InsertSessionParams{
37 ID: string(session.ID),
38 Type: string(session.Type),
39 StartedAt: session.StartedAt.UTC(),
40 EndedAt: endedAt,
41 })
42}
43
44func (r *sessionRepo) FindByID(ctx context.Context, id entity.SessionID) (*entity.Session, error) {
45 row, err := r.queries.GetSessionByID(ctx, string(id))
46 if err != nil {
47 if errors.Is(err, sql.ErrNoRows) {
48 return nil, nil
49 }
50 return nil, err
51 }
52 return sessionFromRow(row), nil
53}
54
55func (r *sessionRepo) GetActive(ctx context.Context) (*entity.Session, error) {
56 row, err := r.queries.GetActiveBrowserSession(ctx)
57 if err != nil {
58 if errors.Is(err, sql.ErrNoRows) {
59 return nil, nil
60 }
61 return nil, err
62 }
63 return sessionFromRow(row), nil
64}
65
66func (r *sessionRepo) GetRecent(ctx context.Context, limit int) ([]*entity.Session, error) {
67 if limit <= 0 {
68 limit = 20
69 }
70 rows, err := r.queries.GetRecentSessions(ctx, int64(limit))
71 if err != nil {
72 return nil, err
73 }
74
75 sessions := make([]*entity.Session, len(rows))
76 for i := range rows {
77 sessions[i] = sessionFromRow(rows[i])
78 }
79 return sessions, nil
80}
81
82func (r *sessionRepo) MarkEnded(ctx context.Context, id entity.SessionID, endedAt time.Time) error {
83 endedAt = endedAt.UTC()
84 return r.queries.MarkSessionEnded(ctx, sqlc.MarkSessionEndedParams{
85 EndedAt: sql.NullTime{Time: endedAt, Valid: true},
86 ID: string(id),
87 })
88}
89
90func sessionFromRow(row sqlc.Session) *entity.Session {
91 var endedAt *time.Time
92 if row.EndedAt.Valid {
93 t := row.EndedAt.Time.UTC()
94 endedAt = &t
95 }
96
97 return &entity.Session{
98 ID: entity.SessionID(row.ID),
99 Type: entity.SessionType(row.Type),
100 StartedAt: row.StartedAt.UTC(),
101 EndedAt: endedAt,
102 }
103}