diff options
Diffstat (limited to 'internal/config/config.go')
| -rw-r--r-- | internal/config/config.go | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/internal/config/config.go b/internal/config/config.go index 609bde5..abb7444 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -8,14 +8,12 @@ import ( "strconv" "strings" "time" - "gopkg.in/yaml.v3" ) const ( ModeResolver = "resolver" ModeMirror = "mirror" - VerifyFull = "full" VerifyLazy = "lazy" VerifyStateOnly = "state-only" @@ -77,19 +75,25 @@ func Default() Config { func Load(path string) (Config, error) { cfg := Default() + if path != "" { b, err := os.ReadFile(path) + if err != nil { return Config{}, fmt.Errorf("read config: %w", err) } + if err := yaml.Unmarshal(b, &cfg); err != nil { return Config{}, fmt.Errorf("parse config: %w", err) } } + applyEnv(&cfg) + if err := cfg.Validate(); err != nil { return Config{}, err } + return cfg, nil } @@ -154,64 +158,84 @@ func (c Config) Validate() error { if c.Mode != ModeResolver && c.Mode != ModeMirror { return fmt.Errorf("invalid mode %q", c.Mode) } + switch c.VerifyPolicy { case VerifyFull, VerifyLazy, VerifyStateOnly: default: return fmt.Errorf("invalid verify policy %q", c.VerifyPolicy) } + if c.DataDir == "" { return errors.New("data_dir is required") } + if c.PLCSource == "" { return errors.New("plc_source is required") } + if c.ZstdLevel < 1 || c.ZstdLevel > 22 { return fmt.Errorf("zstd_level must be between 1 and 22, got %d", c.ZstdLevel) } + if c.BlockSizeMB < 4 || c.BlockSizeMB > 16 { return fmt.Errorf("block_size_mb must be between 4 and 16, got %d", c.BlockSizeMB) } + if c.CheckpointInterval == 0 { return errors.New("checkpoint_interval must be > 0") } + if c.CommitBatchSize <= 0 || c.CommitBatchSize > 4096 { return fmt.Errorf("commit_batch_size must be between 1 and 4096, got %d", c.CommitBatchSize) } + if c.VerifyWorkers <= 0 || c.VerifyWorkers > 1024 { return fmt.Errorf("verify_workers must be between 1 and 1024, got %d", c.VerifyWorkers) } + if c.ListenAddr == "" { return errors.New("listen_addr is required") } + if c.PollInterval <= 0 { return errors.New("poll_interval must be > 0") } + if c.RequestTimeout <= 0 { return errors.New("request_timeout must be > 0") } + if c.RateLimit.ResolveRPS <= 0 { return errors.New("rate_limit.resolve_rps must be > 0") } + if c.RateLimit.ResolveBurst <= 0 { return errors.New("rate_limit.resolve_burst must be > 0") } + if c.RateLimit.ProofRPS <= 0 { return errors.New("rate_limit.proof_rps must be > 0") } + if c.RateLimit.ProofBurst <= 0 { return errors.New("rate_limit.proof_burst must be > 0") } + if c.HTTPRetryMaxAttempts < 1 || c.HTTPRetryMaxAttempts > 32 { return fmt.Errorf("http_retry_max_attempts must be between 1 and 32, got %d", c.HTTPRetryMaxAttempts) } + if c.HTTPRetryBaseDelay <= 0 { return errors.New("http_retry_base_delay must be > 0") } + if c.HTTPRetryMaxDelay <= 0 { return errors.New("http_retry_max_delay must be > 0") } + if c.HTTPRetryBaseDelay > c.HTTPRetryMaxDelay { return errors.New("http_retry_base_delay must be <= http_retry_max_delay") } + return nil } |