feat(multiplayer): add degraded admission mode

This commit is contained in:
Josh Creek
2026-09-01 19:14:28 +01:00
parent d04523accd
commit 6366b5e1f6
6 changed files with 196 additions and 1 deletions
+18
View File
@@ -29,6 +29,7 @@ func main() {
redisPrefix := flag.String("redis-prefix", envOrDefault("COSMIC_CLASH_REDIS_PREFIX", "cosmic-clash"), "Redis key prefix")
redisTTL := flag.Duration("redis-ttl", 60*time.Second, "TTL for transient candidate projection entries")
workloadSecret := flag.String("workload-secret", os.Getenv("COSMIC_CLASH_WORKLOAD_SECRET"), "HMAC secret for control-plane-issued workload tokens (see workload/signed_token.go); server registration/result submission return 503 until this is set")
degraded := flag.Bool("degraded", false, "start with new login, queue, and proposal mutations rejected; SIGUSR1 enables and SIGUSR2 disables this mode")
flag.Parse()
if *role != "api" {
fatalf("unsupported role %q (only api is implemented)", *role)
@@ -63,11 +64,28 @@ func main() {
fmt.Fprintln(os.Stderr, "control-plane: warning: --workload-secret / COSMIC_CLASH_WORKLOAD_SECRET is unset; server registration and result submission will return 503")
}
service := newAPIService(db, *workloadSecret, candidateIndex)
admission := api.NewAdmissionGate(*degraded)
service.Admission = admission
server := &http.Server{Addr: *listen, Handler: service.Handler(), ReadHeaderTimeout: 5 * time.Second}
serveErr := make(chan error, 1)
go func() { serveErr <- server.ListenAndServe() }()
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
operatorSignals := make(chan os.Signal, 2)
signal.Notify(operatorSignals, syscall.SIGUSR1, syscall.SIGUSR2)
defer signal.Stop(operatorSignals)
go func() {
for sig := range operatorSignals {
switch sig {
case syscall.SIGUSR1:
admission.SetDegraded(true)
fmt.Fprintln(os.Stderr, "control-plane: degraded admission enabled")
case syscall.SIGUSR2:
admission.SetDegraded(false)
fmt.Fprintln(os.Stderr, "control-plane: degraded admission disabled")
}
}
}()
go api.RunProposalOutboxDispatcher(ctx, db, service)
go api.RunResultOutboxDispatcher(ctx, db, service)
go api.RunStateOutboxDispatcher(ctx, db, service)