slack5-1770603014/services/preferences-api/internal/adapter/postgres/preferences.go
rdev-worker e5fc44d10e
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
build: /implement-feature user-preferences
2026-02-09 02:37:38 +00:00

75 lines
2.1 KiB
Go

// Package postgres provides PostgreSQL implementations of repository interfaces.
package postgres
import (
"context"
"database/sql"
"encoding/json"
"errors"
"time"
"git.threesix.ai/jordan/slack5-1770603014/pkg/database"
"git.threesix.ai/jordan/slack5-1770603014/services/preferences-api/internal/domain"
"git.threesix.ai/jordan/slack5-1770603014/services/preferences-api/internal/port"
)
// Compile-time verification that PreferencesRepository implements port.PreferencesRepository.
var _ port.PreferencesRepository = (*PreferencesRepository)(nil)
// PreferencesRepository is a PostgreSQL implementation of port.PreferencesRepository.
type PreferencesRepository struct {
pool *database.Pool
}
// NewPreferencesRepository creates a new PostgreSQL preferences repository.
func NewPreferencesRepository(pool *database.Pool) *PreferencesRepository {
return &PreferencesRepository{pool: pool}
}
// Get returns preferences for a user by ID.
// Returns nil, nil if no preferences exist for the user.
func (r *PreferencesRepository) Get(ctx context.Context, userID domain.UserID) (*domain.UserPreferences, error) {
var prefsJSON []byte
var updatedAt time.Time
err := r.pool.DB.QueryRowContext(ctx,
`SELECT preferences, updated_at FROM user_preferences WHERE user_id = $1`,
string(userID),
).Scan(&prefsJSON, &updatedAt)
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
if err != nil {
return nil, err
}
var prefs domain.Preferences
if err := json.Unmarshal(prefsJSON, &prefs); err != nil {
return nil, err
}
return &domain.UserPreferences{
UserID: userID,
Preferences: prefs,
UpdatedAt: updatedAt,
}, nil
}
// Upsert creates or updates preferences for a user.
func (r *PreferencesRepository) Upsert(ctx context.Context, prefs *domain.UserPreferences) error {
prefsJSON, err := json.Marshal(prefs.Preferences)
if err != nil {
return err
}
_, err = r.pool.DB.ExecContext(ctx,
`INSERT INTO user_preferences (user_id, preferences, created_at, updated_at)
VALUES ($1, $2, $3, $3)
ON CONFLICT (user_id)
DO UPDATE SET preferences = $2, updated_at = $3`,
string(prefs.UserID), prefsJSON, prefs.UpdatedAt,
)
return err
}