package postgres import ( "context" "fmt" "sort" ) const LoadRuntimeSettingsSQL = ` SELECT setting_key, setting_value FROM platform_runtime_settings WHERE setting_key = ANY($1::text[]) ORDER BY setting_key ` const UpsertRuntimeSettingSQL = ` INSERT INTO platform_runtime_settings (setting_key, setting_value) VALUES ($1, $2) ON CONFLICT (setting_key) DO UPDATE SET setting_value = EXCLUDED.setting_value, revision = platform_runtime_settings.revision + 1, updated_at = now() ` // LoadRuntimeSettings returns only the requested runtime setting keys. The // caller owns the editable-key whitelist; the database adapter owns storage. func (db *Database) LoadRuntimeSettings(ctx context.Context, keys []string) (map[string]string, error) { if db.config.Backend != BackendPostgres || db.querier == nil { return nil, fmt.Errorf("PostgreSQL is unavailable when ZHINIAN_DATA_BACKEND=%s", db.config.Backend) } if len(keys) == 0 { return map[string]string{}, nil } rows, err := db.querier.Query(ctx, LoadRuntimeSettingsSQL, keys) if err != nil { return nil, fmt.Errorf("load runtime settings: %w", err) } defer rows.Close() values := make(map[string]string, len(keys)) for rows.Next() { var key, value string if err := rows.Scan(&key, &value); err != nil { return nil, fmt.Errorf("scan runtime setting: %w", err) } values[key] = value } if err := rows.Err(); err != nil { return nil, fmt.Errorf("read runtime settings: %w", err) } return values, nil } // SaveRuntimeSettings atomically upserts a partial set of settings. Sorting // makes lock acquisition deterministic when concurrent requests touch several // keys at once. func (db *Database) SaveRuntimeSettings(ctx context.Context, values map[string]string) error { if db.config.Backend != BackendPostgres || db.transactions == nil { return fmt.Errorf("PostgreSQL is unavailable when ZHINIAN_DATA_BACKEND=%s", db.config.Backend) } if len(values) == 0 { return nil } keys := make([]string, 0, len(values)) for key := range values { keys = append(keys, key) } sort.Strings(keys) tx, err := db.transactions.Begin(ctx) if err != nil { return fmt.Errorf("begin runtime settings update: %w", err) } finished := false defer func() { if !finished { _ = tx.Rollback(ctx) } }() for _, key := range keys { if err := tx.Exec(ctx, UpsertRuntimeSettingSQL, key, values[key]); err != nil { return fmt.Errorf("save runtime setting %s: %w", key, err) } } if err := tx.Commit(ctx); err != nil { return fmt.Errorf("commit runtime settings update: %w", err) } finished = true return nil }