Files
orbit/internal/config/config.go

89 lines
2.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package config
import (
"errors"
"fmt"
"net"
"os"
"strconv"
"time"
)
type Config struct {
HTTPAddr string
MySQLDSN string
MaxOpen int
MaxIdle int
MetricsAddr string
WorkflowTickInterval time.Duration // WorkflowTickInterval Weave 持久化推进扫描间隔,范围100ms–1m。
ScheduleTickInterval time.Duration // ScheduleTickInterval 计划扫描间隔,范围100ms–1m。
RecoveryTickInterval time.Duration // RecoveryTickInterval 执行租约恢复扫描间隔,范围100ms–1m。
RuntimeBatchLimit int // RuntimeBatchLimit 每个后台批次的候选上限,范围1–100。
}
func Load() (Config, error) { return FromEnv(os.Getenv) }
func FromEnv(get func(string) string) (Config, error) {
c := Config{
HTTPAddr: get("ORBIT_HTTP_ADDR"),
MySQLDSN: get("ORBIT_MYSQL_DSN"),
MaxOpen: 20,
MaxIdle: 5,
MetricsAddr: get("ORBIT_METRICS_ADDR"),
WorkflowTickInterval: time.Second,
ScheduleTickInterval: time.Second,
RecoveryTickInterval: 2 * time.Second,
RuntimeBatchLimit: 100,
}
if c.HTTPAddr == "" {
c.HTTPAddr = "127.0.0.1:8080"
}
if _, _, err := net.SplitHostPort(c.HTTPAddr); err != nil {
return Config{}, errors.New("invalid ORBIT_HTTP_ADDR")
}
if c.MySQLDSN == "" {
return Config{}, errors.New("ORBIT_MYSQL_DSN is required")
}
for _, field := range []struct {
name string
dst *int
}{{"ORBIT_DB_MAX_OPEN", &c.MaxOpen}, {"ORBIT_DB_MAX_IDLE", &c.MaxIdle}} {
if raw := get(field.name); raw != "" {
n, err := strconv.Atoi(raw)
if err != nil || n < 0 {
return Config{}, fmt.Errorf("%s must be a nonnegative integer", field.name)
}
*field.dst = n
}
}
if c.MaxOpen <= 0 || c.MaxIdle > c.MaxOpen {
return Config{}, errors.New("database pool requires 0 <= max_idle <= max_open and max_open > 0")
}
for _, field := range []struct {
name string
dst *time.Duration
}{{"ORBIT_WORKFLOW_TICK_INTERVAL", &c.WorkflowTickInterval}, {"ORBIT_SCHEDULE_TICK_INTERVAL", &c.ScheduleTickInterval}, {"ORBIT_RECOVERY_TICK_INTERVAL", &c.RecoveryTickInterval}} {
if raw := get(field.name); raw != "" {
d, err := time.ParseDuration(raw)
if err != nil || d < 100*time.Millisecond || d > time.Minute {
return Config{}, fmt.Errorf("%s must be a duration from 100ms to 1m", field.name)
}
*field.dst = d
}
}
if raw := get("ORBIT_RUNTIME_BATCH_LIMIT"); raw != "" {
n, err := strconv.Atoi(raw)
if err != nil || n < 1 || n > 100 {
return Config{}, errors.New("ORBIT_RUNTIME_BATCH_LIMIT must be an integer from 1 to 100")
}
c.RuntimeBatchLimit = n
}
if c.MetricsAddr != "" {
_, port, err := net.SplitHostPort(c.MetricsAddr)
n, parseErr := strconv.Atoi(port)
if err != nil || parseErr != nil || n < 0 || n > 65535 {
return Config{}, errors.New("invalid ORBIT_METRICS_ADDR")
}
}
return c, nil
}