slack5-1770606136/services/preferences-api/internal/adapter/postgres/preference.go
rdev-worker a0ff64af5e
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
build: /implement-feature user-preferences
2026-02-09 03:30:01 +00:00

81 lines
2.1 KiB
Go

package postgres
import (
"context"
"database/sql"
"encoding/json"
"errors"
"time"
"github.com/jmoiron/sqlx"
"git.threesix.ai/jordan/slack5-1770606136/services/preferences-api/internal/domain"
"git.threesix.ai/jordan/slack5-1770606136/services/preferences-api/internal/port"
)
// PreferenceRepository implements port.PreferenceRepository using PostgreSQL.
type PreferenceRepository struct {
db *sqlx.DB
}
// Compile-time interface verification.
var _ port.PreferenceRepository = (*PreferenceRepository)(nil)
// NewPreferenceRepository creates a new PostgreSQL preference repository.
func NewPreferenceRepository(db *sqlx.DB) *PreferenceRepository {
return &PreferenceRepository{db: db}
}
// preferenceRow represents a database row from the preferences table.
type preferenceRow struct {
UserID string `db:"user_id"`
Preferences []byte `db:"preferences"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
// Get returns preferences for a user.
// Returns nil, nil when no row exists.
func (r *PreferenceRepository) Get(ctx context.Context, userID string) (*domain.UserPreferences, error) {
var row preferenceRow
err := r.db.GetContext(ctx, &row,
`SELECT user_id, preferences, created_at, updated_at FROM preferences WHERE user_id = $1`,
userID,
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return nil, err
}
prefs := make(map[string]any)
if err := json.Unmarshal(row.Preferences, &prefs); err != nil {
return nil, err
}
return &domain.UserPreferences{
UserID: row.UserID,
Preferences: prefs,
CreatedAt: row.CreatedAt,
UpdatedAt: row.UpdatedAt,
}, nil
}
// Upsert creates or updates preferences for a user.
func (r *PreferenceRepository) Upsert(ctx context.Context, prefs *domain.UserPreferences) error {
prefsJSON, err := json.Marshal(prefs.Preferences)
if err != nil {
return err
}
_, err = r.db.ExecContext(ctx,
`INSERT INTO preferences (user_id, preferences, updated_at)
VALUES ($1, $2, NOW())
ON CONFLICT (user_id) DO UPDATE
SET preferences = $2, updated_at = NOW()`,
prefs.UserID, prefsJSON,
)
return err
}