package pushnotify import ( "context" "errors" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) type repository interface { upsert(ctx context.Context, t *PushToken) error deleteForHuman(ctx context.Context, humanID, token string) error deleteByToken(ctx context.Context, token string) error listForHumans(ctx context.Context, humanIDs []string) ([]*PushToken, error) } type repositoryImpl struct { pool *pgxpool.Pool } func newRepository(pool *pgxpool.Pool) repository { return &repositoryImpl{pool: pool} } func (r *repositoryImpl) upsert(ctx context.Context, t *PushToken) error { _, err := r.pool.Exec(ctx, `INSERT INTO push_tokens (token, human_id, platform, app_version) VALUES ($1, $2, $3, NULLIF($4, '')) ON CONFLICT (token) DO UPDATE SET human_id = EXCLUDED.human_id, platform = EXCLUDED.platform, app_version = EXCLUDED.app_version, last_seen_at = NOW()`, t.Token, t.HumanID, string(t.Platform), t.AppVersion, ) return err } func (r *repositoryImpl) deleteForHuman(ctx context.Context, humanID, token string) error { result, err := r.pool.Exec(ctx, `DELETE FROM push_tokens WHERE human_id = $1 AND token = $2`, humanID, token, ) if err != nil { return err } if result.RowsAffected() == 0 { return ErrNotFound } return nil } func (r *repositoryImpl) deleteByToken(ctx context.Context, token string) error { _, err := r.pool.Exec(ctx, `DELETE FROM push_tokens WHERE token = $1`, token, ) return err } func (r *repositoryImpl) listForHumans(ctx context.Context, humanIDs []string) ([]*PushToken, error) { if len(humanIDs) == 0 { return nil, nil } rows, err := r.pool.Query(ctx, `SELECT token, human_id, platform, app_version, created_at, last_seen_at FROM push_tokens WHERE human_id = ANY($1)`, humanIDs, ) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, nil } return nil, err } defer rows.Close() var tokens []*PushToken for rows.Next() { var t PushToken var appVersion *string var platform string if err := rows.Scan(&t.Token, &t.HumanID, &platform, &appVersion, &t.CreatedAt, &t.LastSeenAt); err != nil { return nil, err } t.Platform = Platform(platform) if appVersion != nil { t.AppVersion = *appVersion } tokens = append(tokens, &t) } return tokens, rows.Err() }