Files
geo/server/internal/shared/config/reload.go
T
root 77d542c282
Frontend CI / Frontend (push) Successful in 3m38s
Backend CI / Backend (push) Successful in 14m43s
feat(server): make tenant login guard toggleable via config
Add auth.login_guard.enabled config (default on) so the tenant login
brute-force / rate-limit guard can be disabled per environment.
Surfaces an AUTH_LOGIN_GUARD_ENABLED env override and a startup warning
when disabled. Wired through Diff() so hot reload picks up changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 12:32:39 +08:00

128 lines
4.0 KiB
Go

package config
import "reflect"
type FieldChange struct {
Path string
Hot bool
}
func Diff(previous, current *Config) []FieldChange {
if previous == nil || current == nil {
return nil
}
changes := make([]FieldChange, 0)
addChange := func(path string, hot bool) {
changes = append(changes, FieldChange{Path: path, Hot: hot})
}
if !reflect.DeepEqual(previous.Server, current.Server) {
addChange("server", false)
}
if previous.Database != current.Database {
addChange("database", false)
}
if previous.MonitoringDatabase != current.MonitoringDatabase {
addChange("monitoring_database", false)
}
if previous.RabbitMQ != current.RabbitMQ {
addChange("rabbitmq", false)
}
if previous.Scheduler.HTTPHost != current.Scheduler.HTTPHost ||
previous.Scheduler.HTTPPort != current.Scheduler.HTTPPort {
addChange("scheduler.http", false)
}
if previous.Redis != current.Redis {
addChange("redis", false)
}
if previous.Cache != current.Cache {
addChange("cache", false)
}
if previous.Log != current.Log {
addChange("log", false)
}
if previous.Scheduler.InternalMetricsToken != current.Scheduler.InternalMetricsToken {
addChange("scheduler.internal_metrics_token", true)
}
if previous.Scheduler.DispatchInterval != current.Scheduler.DispatchInterval ||
previous.Scheduler.DispatchTimeout != current.Scheduler.DispatchTimeout ||
previous.Scheduler.DispatchBatchSize != current.Scheduler.DispatchBatchSize ||
previous.Scheduler.DispatchConcurrency != current.Scheduler.DispatchConcurrency ||
previous.Scheduler.GenerationQueueBackpressureLimit != current.Scheduler.GenerationQueueBackpressureLimit {
addChange("scheduler.dispatch", true)
}
if previous.MonitoringWorkers != current.MonitoringWorkers {
addChange("monitoring_workers", true)
}
if previous.MonitoringDispatch != current.MonitoringDispatch {
addChange("monitoring_dispatch", true)
}
if !reflect.DeepEqual(previous.Membership, current.Membership) {
addChange("membership", true)
}
if previous.BrandLibrary != current.BrandLibrary {
addChange("brand_library", true)
}
if previous.Qdrant != current.Qdrant {
addChange("qdrant", true)
}
if previous.ObjectStorage != current.ObjectStorage {
addChange("object_storage", true)
}
if previous.JWT != current.JWT {
addChange("jwt", true)
}
if previous.Auth != current.Auth {
addChange("auth", true)
}
if previous.LLM != current.LLM {
addChange("llm", true)
}
if previous.Retrieval != current.Retrieval {
addChange("retrieval", true)
}
if previous.BrowserFetch.QueueSize != current.BrowserFetch.QueueSize ||
previous.BrowserFetch.WorkerConcurrency != current.BrowserFetch.WorkerConcurrency {
addChange("browser_fetch.worker", false)
} else if !reflect.DeepEqual(previous.BrowserFetch, current.BrowserFetch) {
addChange("browser_fetch", true)
}
if previous.Generation.QueueSize != current.Generation.QueueSize ||
previous.Generation.WorkerConcurrency != current.Generation.WorkerConcurrency {
addChange("generation.worker", false)
}
if previous.Generation.StreamEnabled != current.Generation.StreamEnabled ||
previous.Generation.ArticleTimeout != current.Generation.ArticleTimeout ||
previous.Generation.TaskLeaseTTL != current.Generation.TaskLeaseTTL ||
previous.Generation.TaskRecoveryInterval != current.Generation.TaskRecoveryInterval ||
previous.Generation.TaskRecoveryTimeout != current.Generation.TaskRecoveryTimeout ||
previous.Generation.TaskRecoveryBatchSize != current.Generation.TaskRecoveryBatchSize ||
previous.Generation.TaskQueuedStaleAfter != current.Generation.TaskQueuedStaleAfter ||
previous.Generation.TaskMaxAttempts != current.Generation.TaskMaxAttempts {
addChange("generation", true)
}
return changes
}
func RestartRequired(changes []FieldChange) bool {
for _, change := range changes {
if !change.Hot {
return true
}
}
return false
}
func ChangePaths(changes []FieldChange, hot bool) []string {
paths := make([]string, 0, len(changes))
for _, change := range changes {
if change.Hot == hot {
paths = append(paths, change.Path)
}
}
return paths
}