// Package store defines database functions package store import ( _ "embed" "log/slog" "strings" "time" "quantex.com.ar/multidb" "quantex.com/qfixdpl/src/app" "quantex.com/qfixdpl/src/client/store/external" "quantex.com/qfixdpl/src/common/tracerr" ) //go:embed db.sql var schemaSQL string const dbPingSeconds = 30 type Store struct { db *multidb.MultiDB ext *external.Manager } type Config struct { MultiDB multidb.Config External external.Config } // New NewStore creates Store object func New(config Config) (*Store, error) { database, err := multidb.New("postgres", config.MultiDB) if err != nil { return nil, tracerr.Errorf("error trying to create multidb: %w", err) } database.Start() if err = database.Ping(); err != nil { return nil, tracerr.Errorf("error ping to database: %w", err) } ext := external.NewManager(nil, config.External) s := &Store{ db: database, ext: ext, } go s.db.PeriodicDBPing(time.Second * dbPingSeconds) if err := s.ensureTables(); err != nil { return nil, tracerr.Errorf("error ensuring tables: %w", err) } return s, nil } func (p *Store) ensureTables() error { statements := strings.Split(schemaSQL, ";") for _, stmt := range statements { stmt = strings.TrimSpace(stmt) if stmt == "" { continue } if _, err := p.db.Exec(stmt); err != nil { return tracerr.Errorf("error executing schema statement: %w", err) } } slog.Info("database tables ensured") return nil } func (p *Store) CloseDB() { p.db.Close() slog.Info("closing database connection.") } func (p *Store) UserByEmail(email string) (out *app.User, err error) { var user app.User if err := p.ext.UserByEmail(email, &user); err != nil { return nil, tracerr.Errorf("error fetching user by email from external service: %w", err) } return &user, nil } func (p *Store) ValidateSession(sessionToken string) (bool, error) { ok, err := p.ext.ValidateSession(sessionToken) if err != nil { return false, tracerr.Errorf("error validating session: %w", err) } return ok, nil }