Очередь job получила lease и fencing, телеметрия и прогресс deploy сохраняются, ревизия пишет manifest входов. Обновление префиксов не переписывает неизменённый снимок, большие наборы идут через COPY, а устаревшая ревизия не попадает в deploy. Бандл ноды кэшируется, prune и постановка job больше не держат горячий путь. Co-authored-by: Cursor <[email protected]>
82 lines
2.4 KiB
Go
82 lines
2.4 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"evobgp/internal/config"
|
|
"evobgp/internal/httpapi"
|
|
"evobgp/internal/scheduler"
|
|
)
|
|
|
|
func main() {
|
|
cfg := config.Load()
|
|
name := cfg.ServiceName
|
|
if name == "" {
|
|
name = "evobgp-scheduler"
|
|
}
|
|
log.Printf("%s starting (reference profile worker)", name)
|
|
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
|
defer stop()
|
|
|
|
bctx, bcancel := context.WithTimeout(context.Background(), 90*time.Second)
|
|
defer bcancel()
|
|
opts := httpapi.Options{
|
|
DatabaseURL: strings.TrimSpace(os.Getenv("EVOBGP_DATABASE_URL")),
|
|
SeedDemo: os.Getenv("EVOBGP_SEED_DEMO") != "0",
|
|
}
|
|
st, reg, pool, err := httpapi.BootstrapWorkers(bctx, opts)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if pool != nil {
|
|
defer pool.Close()
|
|
}
|
|
|
|
apiBase := strings.TrimSpace(os.Getenv("EVOBGP_CONTROL_PLANE_URL"))
|
|
apiTok := strings.TrimSpace(os.Getenv("EVOBGP_SCHEDULER_BEARER"))
|
|
mode := strings.ToLower(strings.TrimSpace(os.Getenv("EVOBGP_SCHEDULER_MODE")))
|
|
if mode == "" {
|
|
switch {
|
|
case apiBase != "" || apiTok != "":
|
|
mode = "http"
|
|
case pool != nil:
|
|
mode = "db"
|
|
default:
|
|
mode = "local"
|
|
}
|
|
}
|
|
deps := &scheduler.Deps{Store: st, HTTP: &http.Client{Timeout: 45 * time.Second}}
|
|
switch mode {
|
|
case "db":
|
|
if pool == nil {
|
|
log.Fatal("evobgp-scheduler: db mode requires EVOBGP_DATABASE_URL")
|
|
}
|
|
deps.Jobs = reg
|
|
log.Print("evobgp-scheduler: trusted DB enqueue mode; API workers consume the shared durable queue")
|
|
case "http":
|
|
tenant := strings.TrimSpace(os.Getenv("EVOBGP_SCHEDULER_TENANT_ID"))
|
|
if apiBase == "" || apiTok == "" || tenant == "" {
|
|
log.Fatal("evobgp-scheduler: http mode requires EVOBGP_CONTROL_PLANE_URL, EVOBGP_SCHEDULER_BEARER and EVOBGP_SCHEDULER_TENANT_ID")
|
|
}
|
|
deps.APIBase, deps.APIToken, deps.APITenantID = apiBase, apiTok, tenant
|
|
log.Print("evobgp-scheduler: single-tenant HTTP enqueue mode")
|
|
case "local":
|
|
if os.Getenv("EVOBGP_SCHEDULER_STANDALONE") == "1" || pool != nil {
|
|
log.Fatal("evobgp-scheduler: local mode is for in-process development only; use db for a shared PostgreSQL queue")
|
|
}
|
|
deps.Jobs = reg
|
|
defer func() { reg.RequestCancelAll(); _ = reg.Drain(context.Background()) }()
|
|
log.Print("evobgp-scheduler: local development mode")
|
|
default:
|
|
log.Fatal("evobgp-scheduler: EVOBGP_SCHEDULER_MODE must be db, http or local")
|
|
}
|
|
scheduler.Run(ctx, deps)
|
|
}
|