package sqlstore import ( "context" "database/sql" "errors" "fmt" "time" ) // SettingsQueries are the four statements the settings store needs. Each // driver writes them in its own placeholder style and upsert syntax. type SettingsQueries struct { // Get binds (key) and selects setting_value. Get string // GetAll selects (setting_key, setting_value). GetAll string // Upsert binds (key, value, updated_at) and overwrites on conflict. Upsert string // Delete binds (key). Delete string } // Settings is the server_settings key/value store. It is the persistence // behind the runtime federation and registration switches; the in-memory // cache lives one layer up, in the settings service. type Settings struct { db *sql.DB q SettingsQueries } // NewSettings builds a settings store. func NewSettings(db *sql.DB, q SettingsQueries) *Settings { return &Settings{db: db, q: q} } // Get returns the stored value for key; the boolean reports presence. func (s *Settings) Get(ctx context.Context, key string) (string, bool, error) { var value string err := s.db.QueryRowContext(ctx, s.q.Get, key).Scan(&value) switch { case errors.Is(err, sql.ErrNoRows): return "", false, nil case err != nil: return "", false, fmt.Errorf("get setting %q: %w", key, err) } return value, true, nil } // GetAll returns every stored setting. func (s *Settings) GetAll(ctx context.Context) (map[string]string, error) { rows, err := s.db.QueryContext(ctx, s.q.GetAll) if err != nil { return nil, fmt.Errorf("list settings: %w", err) } defer rows.Close() out := map[string]string{} for rows.Next() { var k, v string if err := rows.Scan(&k, &v); err != nil { return nil, fmt.Errorf("scan setting: %w", err) } out[k] = v } if err := rows.Err(); err != nil { return nil, fmt.Errorf("list settings: %w", err) } return out, nil } // Set writes key, overwriting any previous value. func (s *Settings) Set(ctx context.Context, key, value string) error { if _, err := s.db.ExecContext(ctx, s.q.Upsert, key, value, time.Now().UTC()); err != nil { return fmt.Errorf("set setting %q: %w", key, err) } return nil } // Delete removes key. Removing an absent key is not an error. func (s *Settings) Delete(ctx context.Context, key string) error { if _, err := s.db.ExecContext(ctx, s.q.Delete, key); err != nil { return fmt.Errorf("delete setting %q: %w", key, err) } return nil }