refactor(scheduler): add base context for graceful shutdown

- Create application-level context with cancel function
- Pass base context to scheduler via WithBaseContext option
- Move scheduler.Stop() to explicit shutdown sequence after context cancellation
- Upgrade foundation dependency to v0.7.0 for new scheduler options
This commit is contained in:
zenfun
2026-01-01 01:44:49 +08:00
parent 31914b9ab5
commit bae3d9bd5b
3 changed files with 12 additions and 5 deletions

View File

@@ -85,6 +85,8 @@ func main() {
} }
logger, _ := logging.New(logging.Options{Service: "ez-api"}) logger, _ := logging.New(logging.Options{Service: "ez-api"})
appCtx, appCancel := context.WithCancel(context.Background())
defer appCancel()
if len(os.Args) > 1 && os.Args[1] == "import" { if len(os.Args) > 1 && os.Args[1] == "import" {
code := runImport(logger, os.Args[2:]) code := runImport(logger, os.Args[2:])
os.Exit(code) os.Exit(code)
@@ -201,7 +203,11 @@ func main() {
alertDetector := cron.NewAlertDetector(db, logDB, rdb, service.NewStatsService(rdb), alertDetectorConfig, logger) alertDetector := cron.NewAlertDetector(db, logDB, rdb, service.NewStatsService(rdb), alertDetectorConfig, logger)
// Setup scheduler (jobs are added incrementally, Start() called after all services initialized) // Setup scheduler (jobs are added incrementally, Start() called after all services initialized)
sched := scheduler.New(scheduler.WithLogger(logger), scheduler.WithSkipIfRunning()) sched := scheduler.New(
scheduler.WithLogger(logger),
scheduler.WithSkipIfRunning(),
scheduler.WithBaseContext(appCtx),
)
sched.Every("quota-reset", time.Duration(cfg.Quota.ResetIntervalSeconds)*time.Second, quotaResetter.RunOnce) sched.Every("quota-reset", time.Duration(cfg.Quota.ResetIntervalSeconds)*time.Second, quotaResetter.RunOnce)
sched.Every("log-cleanup", time.Hour, logCleaner.RunOnce) sched.Every("log-cleanup", time.Hour, logCleaner.RunOnce)
sched.Every("token-refresh", time.Duration(cfg.TokenRefresh.IntervalSeconds)*time.Second, tokenRefresher.RunOnce) sched.Every("token-refresh", time.Duration(cfg.TokenRefresh.IntervalSeconds)*time.Second, tokenRefresher.RunOnce)
@@ -209,7 +215,6 @@ func main() {
if outboxService != nil && outboxService.Enabled() { if outboxService != nil && outboxService.Enabled() {
sched.Every("sync-outbox", outboxService.Interval(), outboxService.RunOnce) sched.Every("sync-outbox", outboxService.Interval(), outboxService.RunOnce)
} }
defer sched.Stop()
adminService, err := service.NewAdminService() adminService, err := service.NewAdminService()
if err != nil { if err != nil {
@@ -430,6 +435,8 @@ func main() {
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit <-quit
logger.Info("shutting down server...") logger.Info("shutting down server...")
appCancel()
sched.Stop()
// Shutdown with timeout // Shutdown with timeout
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)

2
go.mod
View File

@@ -4,7 +4,7 @@ go 1.24.5
require ( require (
github.com/alicebob/miniredis/v2 v2.35.0 github.com/alicebob/miniredis/v2 v2.35.0
github.com/ez-api/foundation v0.6.0 github.com/ez-api/foundation v0.7.0
github.com/gin-gonic/gin v1.11.0 github.com/gin-gonic/gin v1.11.0
github.com/pelletier/go-toml/v2 v2.2.4 github.com/pelletier/go-toml/v2 v2.2.4
github.com/redis/go-redis/v9 v9.17.2 github.com/redis/go-redis/v9 v9.17.2

4
go.sum
View File

@@ -20,8 +20,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/ez-api/foundation v0.6.0 h1:rRC3D6KreTuRGSUppPCvEIgqu697NLSHuk+SDuc4lGk= github.com/ez-api/foundation v0.7.0 h1:1jYQsqcVd8dxb+8I8ENlNg2zGVeR78yGeF/dlJTf/kY=
github.com/ez-api/foundation v0.6.0/go.mod h1:Ds1imonA0hbjh1vY5YPwjdAG1XhkckDSe/pR5aY2mJQ= github.com/ez-api/foundation v0.7.0/go.mod h1:rJvvHahdWlNHQSVEyifnxLK2uleH4VNdC87HVgC8Lwo=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=