Files
iu 50dff63ece feat: rename service to galo, add halo branding and release build
- rename Go module, binary, systemd unit, PG_DATABASE default, frontend package and docs from shared-album to galo
- add theme-aware halo emblem and favicon (new ui-branding capability)
- add make build-release (versioned, stripped, static binary) and run the binary from the repo root
2026-10-11 11:36:56 +03:00

64 lines
1.5 KiB
Go

package settings
import (
"context"
"database/sql"
"errors"
"fmt"
"time"
"galo/internal/sqliteutil"
)
// SQLiteStore is the SQLite implementation of Repository.
type SQLiteStore struct {
db *sql.DB
}
func NewSQLiteStore(db *sql.DB) *SQLiteStore { return &SQLiteStore{db: db} }
func (s *SQLiteStore) Get(ctx context.Context, key string) (string, bool, error) {
var v string
err := s.db.QueryRowContext(ctx, `SELECT value FROM app_settings WHERE key = $1`, key).Scan(&v)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return "", false, nil
}
return "", false, err
}
return v, true, nil
}
func (s *SQLiteStore) Set(ctx context.Context, key, value string) error {
_, err := s.db.ExecContext(ctx,
`INSERT INTO app_settings (key, value) VALUES ($1, $2)
ON CONFLICT (key) DO UPDATE SET value = excluded.value, updated_at = $3`,
key, value, sqliteutil.FormatTime(time.Now()))
return err
}
func (s *SQLiteStore) Ensure(ctx context.Context, key string, generate func() (string, error)) (string, error) {
if v, ok, err := s.Get(ctx, key); err != nil {
return "", err
} else if ok {
return v, nil
}
v, err := generate()
if err != nil {
return "", err
}
if _, err := s.db.ExecContext(ctx,
`INSERT INTO app_settings (key, value) VALUES ($1, $2) ON CONFLICT (key) DO NOTHING`,
key, v); err != nil {
return "", err
}
got, ok, err := s.Get(ctx, key)
if err != nil {
return "", err
}
if !ok {
return "", fmt.Errorf("settings: %q missing after insert", key)
}
return got, nil
}