feat(store): add PostgreSQL foundation [T-009]
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
const (
|
||||
defaultHTTPAddress = "127.0.0.1:8080"
|
||||
defaultDatabaseDriver = "sqlite"
|
||||
defaultDatabaseDSN = "file:data/sense.db"
|
||||
defaultMediaMTXURL = "http://127.0.0.1:9997"
|
||||
defaultReconcilePeriod = 5 * time.Second
|
||||
@@ -23,6 +24,7 @@ const (
|
||||
type Config struct {
|
||||
HTTPAddress string
|
||||
AllowNonLoopback bool
|
||||
DatabaseDriver string
|
||||
DatabaseDSN string
|
||||
MediaMTXURL string
|
||||
ReconcileInterval time.Duration
|
||||
@@ -58,6 +60,7 @@ func Load() (Config, error) {
|
||||
cfg := Config{
|
||||
HTTPAddress: stringEnv("SENSE_HTTP_ADDR", defaultHTTPAddress),
|
||||
AllowNonLoopback: allow,
|
||||
DatabaseDriver: stringEnv("SENSE_DB_DRIVER", defaultDatabaseDriver),
|
||||
DatabaseDSN: stringEnv("SENSE_DB_DSN", defaultDatabaseDSN),
|
||||
MediaMTXURL: stringEnv("SENSE_MEDIAMTX_URL", defaultMediaMTXURL),
|
||||
ReconcileInterval: reconcilePeriod,
|
||||
@@ -86,6 +89,16 @@ func (c Config) Validate() error {
|
||||
if c.DatabaseDSN == "" {
|
||||
return fmt.Errorf("SENSE_DB_DSN must not be empty")
|
||||
}
|
||||
databaseDriver := strings.ToLower(strings.TrimSpace(c.DatabaseDriver))
|
||||
if databaseDriver == "" {
|
||||
databaseDriver = defaultDatabaseDriver
|
||||
}
|
||||
if databaseDriver != "sqlite" && databaseDriver != "postgres" {
|
||||
return fmt.Errorf("SENSE_DB_DRIVER must be sqlite or postgres")
|
||||
}
|
||||
if databaseDriver == "postgres" && strings.HasPrefix(c.DatabaseDSN, "file:") {
|
||||
return fmt.Errorf("postgres SENSE_DB_DRIVER requires an explicit PostgreSQL SENSE_DB_DSN")
|
||||
}
|
||||
mediaURL, err := url.Parse(c.MediaMTXURL)
|
||||
if err != nil || mediaURL.Scheme == "" || mediaURL.Host == "" {
|
||||
return fmt.Errorf("invalid SENSE_MEDIAMTX_URL")
|
||||
|
||||
@@ -70,3 +70,26 @@ func TestLoadRTSPStripQueryOptIn(t *testing.T) {
|
||||
t.Fatal("explicit RTSP query stripping was not loaded")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDatabaseDriver(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg := Config{
|
||||
HTTPAddress: "127.0.0.1:8080",
|
||||
DatabaseDriver: "postgres",
|
||||
DatabaseDSN: "file:test.db",
|
||||
MediaMTXURL: "http://127.0.0.1:9997",
|
||||
ReconcileInterval: 1,
|
||||
ProbeInterval: 1,
|
||||
}
|
||||
if err := cfg.Validate(); err == nil {
|
||||
t.Fatal("postgres driver must reject the SQLite default DSN")
|
||||
}
|
||||
cfg.DatabaseDSN = "postgres://sense-runtime@127.0.0.1/yovision?sslmode=disable"
|
||||
if err := cfg.Validate(); err != nil {
|
||||
t.Fatalf("valid PostgreSQL selection failed: %v", err)
|
||||
}
|
||||
cfg.DatabaseDriver = "mysql"
|
||||
if err := cfg.Validate(); err == nil {
|
||||
t.Fatal("unknown database driver must be rejected")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user