From 4ed6f95ebe1fad59d07e3804b03dc65a6b552009 Mon Sep 17 00:00:00 2001 From: Andrei Mihu Date: Sat, 19 Jun 2021 16:12:56 +0100 Subject: [PATCH] Cancel runtime context when graceful shutdown completes. --- CHANGELOG.md | 1 + main.go | 8 +++++++- server/runtime.go | 4 ++-- server/runtime_go.go | 4 ++-- server/runtime_test.go | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa20603b6..da65fe838 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr - Add new langTag, members and open filters to the group listing API. - Upgrade pgx to v4 for improved SQL performance. - Change RegisterLeaderboardReset runtime function signature. +- Cancel runtime context when graceful shutdown completes. ### Fixed - Ensure all members are correctly listed in party info when there are multiple concurrent successful joins. diff --git a/main.go b/main.go index 69ede7a9b..6d05ebf79 100644 --- a/main.go +++ b/main.go @@ -119,6 +119,9 @@ func main() { db, dbVersion := dbConnect(startupLogger, config) startupLogger.Info("Database information", zap.String("version", dbVersion)) + // Global server context. + ctx, ctxCancelFn := context.WithCancel(context.Background()) + // Check migration status and fail fast if the schema has diverged. migrate.StartupCheck(startupLogger, db) @@ -140,7 +143,7 @@ func main() { tracker.SetMatchJoinListener(matchRegistry.Join) tracker.SetMatchLeaveListener(matchRegistry.Leave) streamManager := server.NewLocalStreamManager(config, sessionRegistry, tracker) - runtime, runtimeInfo, err := server.NewRuntime(logger, startupLogger, db, jsonpbMarshaler, jsonpbUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, metrics, streamManager, router) + runtime, runtimeInfo, err := server.NewRuntime(ctx, logger, startupLogger, db, jsonpbMarshaler, jsonpbUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, metrics, streamManager, router) if err != nil { startupLogger.Fatal("Failed initializing runtime modules", zap.Error(err)) } @@ -208,6 +211,9 @@ func main() { timer.Stop() } + // Signal cancellation to the global runtime context. + ctxCancelFn() + // Gracefully stop remaining server components. apiServer.Stop() consoleServer.Stop() diff --git a/server/runtime.go b/server/runtime.go index e8f513430..e73969b7e 100644 --- a/server/runtime.go +++ b/server/runtime.go @@ -564,7 +564,7 @@ func CheckRuntime(logger *zap.Logger, config Config) error { return nil } -func NewRuntime(logger, startupLogger *zap.Logger, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, protojsonUnmarshaler *protojson.UnmarshalOptions, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, leaderboardRankCache LeaderboardRankCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, matchRegistry MatchRegistry, tracker Tracker, metrics *Metrics, streamManager StreamManager, router MessageRouter) (*Runtime, *RuntimeInfo, error) { +func NewRuntime(ctx context.Context, logger, startupLogger *zap.Logger, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, protojsonUnmarshaler *protojson.UnmarshalOptions, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, leaderboardRankCache LeaderboardRankCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, matchRegistry MatchRegistry, tracker Tracker, metrics *Metrics, streamManager StreamManager, router MessageRouter) (*Runtime, *RuntimeInfo, error) { runtimeConfig := config.GetRuntime() startupLogger.Info("Initialising runtime", zap.String("path", runtimeConfig.Path)) @@ -579,7 +579,7 @@ func NewRuntime(logger, startupLogger *zap.Logger, db *sql.DB, protojsonMarshale matchProvider := NewMatchProvider() - goModules, goRPCFunctions, goBeforeRtFunctions, goAfterRtFunctions, goBeforeReqFunctions, goAfterReqFunctions, goMatchmakerMatchedFunction, goTournamentEndFunction, goTournamentResetFunction, goLeaderboardResetFunction, allEventFunctions, goMatchNamesListFn, err := NewRuntimeProviderGo(logger, startupLogger, db, protojsonMarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, streamManager, router, runtimeConfig.Path, paths, eventQueue, matchProvider) + goModules, goRPCFunctions, goBeforeRtFunctions, goAfterRtFunctions, goBeforeReqFunctions, goAfterReqFunctions, goMatchmakerMatchedFunction, goTournamentEndFunction, goTournamentResetFunction, goLeaderboardResetFunction, allEventFunctions, goMatchNamesListFn, err := NewRuntimeProviderGo(ctx, logger, startupLogger, db, protojsonMarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, streamManager, router, runtimeConfig.Path, paths, eventQueue, matchProvider) if err != nil { startupLogger.Error("Error initialising Go runtime provider", zap.Error(err)) return nil, nil, err diff --git a/server/runtime_go.go b/server/runtime_go.go index 21980df85..e71fabb76 100644 --- a/server/runtime_go.go +++ b/server/runtime_go.go @@ -2327,7 +2327,7 @@ func (ri *RuntimeGoInitializer) RegisterMatch(name string, fn func(ctx context.C return nil } -func NewRuntimeProviderGo(logger, startupLogger *zap.Logger, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, leaderboardRankCache LeaderboardRankCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, matchRegistry MatchRegistry, tracker Tracker, streamManager StreamManager, router MessageRouter, rootPath string, paths []string, eventQueue *RuntimeEventQueue, matchProvider *MatchProvider) ([]string, map[string]RuntimeRpcFunction, map[string]RuntimeBeforeRtFunction, map[string]RuntimeAfterRtFunction, *RuntimeBeforeReqFunctions, *RuntimeAfterReqFunctions, RuntimeMatchmakerMatchedFunction, RuntimeTournamentEndFunction, RuntimeTournamentResetFunction, RuntimeLeaderboardResetFunction, *RuntimeEventFunctions, func() []string, error) { +func NewRuntimeProviderGo(ctx context.Context, logger, startupLogger *zap.Logger, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, leaderboardRankCache LeaderboardRankCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, matchRegistry MatchRegistry, tracker Tracker, streamManager StreamManager, router MessageRouter, rootPath string, paths []string, eventQueue *RuntimeEventQueue, matchProvider *MatchProvider) ([]string, map[string]RuntimeRpcFunction, map[string]RuntimeBeforeRtFunction, map[string]RuntimeAfterRtFunction, *RuntimeBeforeReqFunctions, *RuntimeAfterReqFunctions, RuntimeMatchmakerMatchedFunction, RuntimeTournamentEndFunction, RuntimeTournamentResetFunction, RuntimeLeaderboardResetFunction, *RuntimeEventFunctions, func() []string, error) { runtimeLogger := NewRuntimeGoLogger(logger) node := config.GetName() env := config.GetRuntime().Environment @@ -2391,7 +2391,7 @@ func NewRuntimeProviderGo(logger, startupLogger *zap.Logger, db *sql.DB, protojs } // The baseline context that will be passed to all InitModule calls. - ctx := NewRuntimeGoContext(context.Background(), node, env, RuntimeExecutionModeRunOnce, nil, 0, "", "", nil, "", "", "") + ctx = NewRuntimeGoContext(ctx, node, env, RuntimeExecutionModeRunOnce, nil, 0, "", "", nil, "", "", "") startupLogger.Info("Initialising Go runtime provider", zap.String("path", rootPath)) diff --git a/server/runtime_test.go b/server/runtime_test.go index 940a4c403..195659493 100644 --- a/server/runtime_test.go +++ b/server/runtime_test.go @@ -76,7 +76,7 @@ func runtimeWithModules(t *testing.T, modules map[string]string) (*Runtime, *Run cfg := NewConfig(logger) cfg.Runtime.Path = dir - return NewRuntime(logger, logger, NewDB(t), protojsonMarshaler, protojsonUnmarshaler, cfg, nil, nil, nil, nil, nil, nil, nil, nil, metrics, nil, &DummyMessageRouter{}) + return NewRuntime(context.Background(), logger, logger, NewDB(t), protojsonMarshaler, protojsonUnmarshaler, cfg, nil, nil, nil, nil, nil, nil, nil, nil, metrics, nil, &DummyMessageRouter{}) } func TestRuntimeSampleScript(t *testing.T) { -- GitLab