feat: simplify SOP to immediate-effect configuration
This commit is contained in:
@@ -12,11 +12,12 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
App AppConfig `yaml:"app"`
|
||||
Server ServerConfig `yaml:"server"`
|
||||
Database DatabaseConfig `yaml:"database"`
|
||||
Auth AuthConfig `yaml:"auth"`
|
||||
Seed SeedConfig `yaml:"seed"`
|
||||
App AppConfig `yaml:"app"`
|
||||
Server ServerConfig `yaml:"server"`
|
||||
Database DatabaseConfig `yaml:"database"`
|
||||
Auth AuthConfig `yaml:"auth"`
|
||||
Seed SeedConfig `yaml:"seed"`
|
||||
MultiTable MultiTableConfig `yaml:"multitable"`
|
||||
}
|
||||
|
||||
type AppConfig struct {
|
||||
@@ -63,6 +64,32 @@ type SeedConfig struct {
|
||||
AdminDisplayName string `yaml:"admin_display_name" env:"APP_SEED_ADMIN_DISPLAY_NAME"`
|
||||
}
|
||||
|
||||
type MultiTableConfig struct {
|
||||
Enabled bool `yaml:"enabled" env:"APP_MULTITABLE_ENABLED" env-default:"false"`
|
||||
BaseURL string `yaml:"base_url" env:"APP_MULTITABLE_BASE_URL" env-default:"https://table.iwork-ai.com/open/v1"`
|
||||
APIKey string `yaml:"api_key" env:"APP_MULTITABLE_API_KEY"`
|
||||
SyncInterval time.Duration `yaml:"sync_interval" env:"APP_MULTITABLE_SYNC_INTERVAL" env-default:"5s"`
|
||||
RequestTimeout time.Duration `yaml:"request_timeout" env:"APP_MULTITABLE_REQUEST_TIMEOUT" env-default:"10s"`
|
||||
BatchSize int `yaml:"batch_size" env:"APP_MULTITABLE_BATCH_SIZE" env-default:"20"`
|
||||
MaxAttempts int `yaml:"max_attempts" env:"APP_MULTITABLE_MAX_ATTEMPTS" env-default:"12"`
|
||||
Tables MultiTableTables `yaml:"tables"`
|
||||
}
|
||||
|
||||
type MultiTableTables struct {
|
||||
Scenarios uint64 `yaml:"scenarios" env:"APP_MULTITABLE_TABLES_SCENARIOS"`
|
||||
ScenarioFields uint64 `yaml:"scenario_fields" env:"APP_MULTITABLE_TABLES_SCENARIO_FIELDS"`
|
||||
ScenarioRules uint64 `yaml:"scenario_rules" env:"APP_MULTITABLE_TABLES_SCENARIO_RULES"`
|
||||
SOPVersions uint64 `yaml:"sop_versions" env:"APP_MULTITABLE_TABLES_SOP_VERSIONS"`
|
||||
SOPNodes uint64 `yaml:"sop_nodes" env:"APP_MULTITABLE_TABLES_SOP_NODES"`
|
||||
SOPEdges uint64 `yaml:"sop_edges" env:"APP_MULTITABLE_TABLES_SOP_EDGES"`
|
||||
KnowledgeItems uint64 `yaml:"knowledge_items" env:"APP_MULTITABLE_TABLES_KNOWLEDGE_ITEMS"`
|
||||
KnowledgeRelations uint64 `yaml:"knowledge_relations" env:"APP_MULTITABLE_TABLES_KNOWLEDGE_RELATIONS"`
|
||||
// KnowledgeVersions is retained only for replaying historical projection events.
|
||||
KnowledgeVersions uint64 `yaml:"knowledge_versions" env:"APP_MULTITABLE_TABLES_KNOWLEDGE_VERSIONS"`
|
||||
Runs uint64 `yaml:"runs" env:"APP_MULTITABLE_TABLES_RUNS"`
|
||||
Feedback uint64 `yaml:"feedback" env:"APP_MULTITABLE_TABLES_FEEDBACK"`
|
||||
}
|
||||
|
||||
type LoadOptions struct {
|
||||
Environment string
|
||||
ConfigDir string
|
||||
@@ -138,5 +165,33 @@ func (c Config) Validate() error {
|
||||
if c.App.Env == "prod" && c.Database.Password == "" {
|
||||
return errors.New("database password is required in production")
|
||||
}
|
||||
if c.MultiTable.Enabled {
|
||||
if !strings.HasPrefix(c.MultiTable.BaseURL, "https://") {
|
||||
return errors.New("multitable.base_url must use https when multitable is enabled")
|
||||
}
|
||||
if strings.TrimSpace(c.MultiTable.APIKey) == "" {
|
||||
return errors.New("APP_MULTITABLE_API_KEY is required when multitable is enabled")
|
||||
}
|
||||
if c.MultiTable.SyncInterval <= 0 || c.MultiTable.RequestTimeout <= 0 || c.MultiTable.BatchSize < 1 || c.MultiTable.MaxAttempts < 1 {
|
||||
return errors.New("multitable retry and timeout settings must be positive")
|
||||
}
|
||||
ids := []uint64{
|
||||
c.MultiTable.Tables.Scenarios,
|
||||
c.MultiTable.Tables.ScenarioFields,
|
||||
c.MultiTable.Tables.ScenarioRules,
|
||||
c.MultiTable.Tables.SOPVersions,
|
||||
c.MultiTable.Tables.SOPNodes,
|
||||
c.MultiTable.Tables.SOPEdges,
|
||||
c.MultiTable.Tables.KnowledgeItems,
|
||||
c.MultiTable.Tables.KnowledgeRelations,
|
||||
c.MultiTable.Tables.Runs,
|
||||
c.MultiTable.Tables.Feedback,
|
||||
}
|
||||
for _, id := range ids {
|
||||
if id == 0 {
|
||||
return errors.New("all multitable table IDs are required when multitable is enabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -72,6 +72,34 @@ func TestLoadProductionRequiresEnvironmentSecrets(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadMultiTableEnvironmentConfiguration(t *testing.T) {
|
||||
dir := writeConfigs(t, "")
|
||||
t.Setenv("APP_MULTITABLE_ENABLED", "true")
|
||||
t.Setenv("APP_MULTITABLE_API_KEY", "test-key")
|
||||
for key, value := range map[string]string{
|
||||
"APP_MULTITABLE_TABLES_SCENARIOS": "46",
|
||||
"APP_MULTITABLE_TABLES_SCENARIO_FIELDS": "47",
|
||||
"APP_MULTITABLE_TABLES_SCENARIO_RULES": "54",
|
||||
"APP_MULTITABLE_TABLES_SOP_VERSIONS": "48",
|
||||
"APP_MULTITABLE_TABLES_SOP_NODES": "49",
|
||||
"APP_MULTITABLE_TABLES_SOP_EDGES": "50",
|
||||
"APP_MULTITABLE_TABLES_KNOWLEDGE_VERSIONS": "51",
|
||||
"APP_MULTITABLE_TABLES_KNOWLEDGE_ITEMS": "55",
|
||||
"APP_MULTITABLE_TABLES_KNOWLEDGE_RELATIONS": "56",
|
||||
"APP_MULTITABLE_TABLES_RUNS": "52",
|
||||
"APP_MULTITABLE_TABLES_FEEDBACK": "53",
|
||||
} {
|
||||
t.Setenv(key, value)
|
||||
}
|
||||
cfg, err := Load(LoadOptions{ConfigDir: dir})
|
||||
if err != nil {
|
||||
t.Fatalf("Load() error = %v", err)
|
||||
}
|
||||
if !cfg.MultiTable.Enabled || cfg.MultiTable.Tables.Scenarios != 46 || cfg.MultiTable.Tables.ScenarioRules != 54 || cfg.MultiTable.Tables.KnowledgeItems != 55 || cfg.MultiTable.Tables.KnowledgeRelations != 56 || cfg.MultiTable.Tables.Feedback != 53 {
|
||||
t.Fatalf("unexpected multitable configuration: %+v", cfg.MultiTable)
|
||||
}
|
||||
}
|
||||
|
||||
func writeConfigs(t *testing.T, profile string) string {
|
||||
t.Helper()
|
||||
dir := t.TempDir()
|
||||
|
||||
Reference in New Issue
Block a user