From b5fc6b6c93ee51eb714383d08b2460f6f82c2b7f Mon Sep 17 00:00:00 2001 From: Henrique Rodrigues Date: Tue, 14 Aug 2018 13:50:14 -0300 Subject: [PATCH 1/2] ordered modules --- app.go | 6 ++-- module.go | 83 +++++++++++++++++++++++++++++++++++++++----------- module_test.go | 46 ++++++++++++++++++++++------ 3 files changed, 105 insertions(+), 30 deletions(-) diff --git a/app.go b/app.go index 37d45e20..ae390fcb 100644 --- a/app.go +++ b/app.go @@ -338,9 +338,9 @@ func Start() { app.serviceDiscovery.AddListener(app.rpcClient.(*cluster.GRPCClient)) } - RegisterModule(app.serviceDiscovery, "serviceDiscovery") - RegisterModule(app.rpcServer, "rpcServer") - RegisterModule(app.rpcClient, "rpcClient") + RegisterModuleBefore(app.serviceDiscovery, "serviceDiscovery") + RegisterModuleBefore(app.rpcServer, "rpcServer") + RegisterModuleBefore(app.rpcClient, "rpcClient") app.router.SetServiceDiscovery(app.serviceDiscovery) diff --git a/module.go b/module.go index 7a3e92a4..630ed18e 100644 --- a/module.go +++ b/module.go @@ -27,46 +27,95 @@ import ( "github.com/topfreegames/pitaya/logger" ) -var modules = make(map[string]interfaces.Module) +var ( + modulesMap = make(map[string]interfaces.Module) + modulesArr = []moduleWrapper{} +) + +type moduleWrapper struct { + module interfaces.Module + name string +} -// RegisterModule registers a module +// RegisterModule registers a module, by default it register after registered modules func RegisterModule(module interfaces.Module, name string) error { - if _, ok := modules[name]; ok { - return fmt.Errorf("module with name %s already exists", name) + return RegisterModuleAfter(module, name) +} + +// RegisterModuleAfter registers a module after all registered modules +func RegisterModuleAfter(module interfaces.Module, name string) error { + if err := alreadyRegistered(name); err != nil { + return err + } + + modulesMap[name] = module + modulesArr = append(modulesArr, moduleWrapper{ + module: module, + name: name, + }) + + return nil +} + +// RegisterModuleBefore registers a module before all registered modules +func RegisterModuleBefore(module interfaces.Module, name string) error { + if err := alreadyRegistered(name); err != nil { + return err } - modules[name] = module + + modulesMap[name] = module + modulesArr = append([]moduleWrapper{ + { + module: module, + name: name, + }, + }, modulesArr...) + return nil } // GetModule gets a module with a name func GetModule(name string) (interfaces.Module, error) { - if m, ok := modules[name]; ok { + if m, ok := modulesMap[name]; ok { return m, nil } return nil, fmt.Errorf("module with name %s not found", name) } -// StartModules starts all modules +func alreadyRegistered(name string) error { + if _, ok := modulesMap[name]; ok { + return fmt.Errorf("module with name %s already exists", name) + } + + return nil +} + +// startModules starts all modules in order func startModules() { logger.Log.Debug("initializing all modules") - for name, mod := range modules { - logger.Log.Debugf("initializing module: %s", name) - if err := mod.Init(); err != nil { - logger.Log.Fatalf("error starting module %s, error: %s", name, err.Error()) + for _, modWrapper := range modulesArr { + logger.Log.Debugf("initializing module: %s", modWrapper.name) + if err := modWrapper.module.Init(); err != nil { + logger.Log.Fatalf("error starting module %s, error: %s", modWrapper.name, err.Error()) } } - for name, mod := range modules { - mod.AfterInit() - logger.Log.Infof("module: %s successfully loaded", name) + for _, modWrapper := range modulesArr { + modWrapper.module.AfterInit() + logger.Log.Infof("module: %s successfully loaded", modWrapper.name) } } +// shutdownModules starts all modules in reverse order func shutdownModules() { - for _, mod := range modules { - mod.BeforeShutdown() + for i := len(modulesArr) - 1; i >= 0; i-- { + modulesArr[i].module.BeforeShutdown() } - for name, mod := range modules { + + for i := len(modulesArr) - 1; i >= 0; i-- { + name := modulesArr[i].name + mod := modulesArr[i].module + logger.Log.Debugf("stopping module: %s", name) if err := mod.Shutdown(); err != nil { logger.Log.Warnf("error stopping module: %s", name) diff --git a/module_test.go b/module_test.go index 9698b6c7..3b1e0d64 100644 --- a/module_test.go +++ b/module_test.go @@ -32,29 +32,39 @@ import ( type MyMod struct { component.Base running bool + name string +} + +var modulesOrder []string + +func resetModules() { + modulesMap = make(map[string]interfaces.Module) + modulesArr = []moduleWrapper{} + modulesOrder = []string{} } func (m *MyMod) Init() error { m.running = true + modulesOrder = append(modulesOrder, m.name) return nil } func (m *MyMod) Shutdown() error { m.running = false + modulesOrder = append(modulesOrder, m.name) return nil } -func resetModules() { - modules = make(map[string]interfaces.Module) -} - func TestRegisterModule(t *testing.T) { resetModules() b := &MyMod{} err := RegisterModule(b, "mod") assert.NoError(t, err) - assert.Equal(t, 1, len(modules)) - assert.Equal(t, b, modules["mod"]) + assert.Equal(t, 1, len(modulesMap)) + assert.Equal(t, b, modulesMap["mod"]) + assert.Equal(t, 1, len(modulesArr)) + assert.Equal(t, "mod", modulesArr[0].name) + assert.Equal(t, b, modulesArr[0].module) err = RegisterModule(b, "mod") assert.Error(t, err) } @@ -76,9 +86,17 @@ func TestStartupModules(t *testing.T) { resetModules() Configure(true, "testtype", Standalone, map[string]string{}, viper.New()) - RegisterModule(&MyMod{}, "bla") + RegisterModule(&MyMod{name: "mod1"}, "mod1") + RegisterModuleBefore(&MyMod{name: "mod2"}, "mod2") + RegisterModuleBefore(&MyMod{name: "mod3"}, "mod3") + RegisterModuleAfter(&MyMod{name: "mod4"}, "mod4") + startModules() - assert.Equal(t, true, modules["bla"].(*MyMod).running) + assert.Equal(t, true, modulesMap["mod1"].(*MyMod).running) + assert.Equal(t, true, modulesMap["mod2"].(*MyMod).running) + assert.Equal(t, true, modulesMap["mod3"].(*MyMod).running) + assert.Equal(t, true, modulesMap["mod4"].(*MyMod).running) + assert.Equal(t, []string{"mod3", "mod2", "mod1", "mod4"}, modulesOrder) } func TestShutdownModules(t *testing.T) { @@ -86,9 +104,17 @@ func TestShutdownModules(t *testing.T) { initApp() Configure(true, "testtype", Standalone, map[string]string{}, viper.New()) - RegisterModule(&MyMod{}, "bla") + RegisterModule(&MyMod{name: "mod1"}, "mod1") + RegisterModuleBefore(&MyMod{name: "mod2"}, "mod2") + RegisterModuleBefore(&MyMod{name: "mod3"}, "mod3") + RegisterModuleAfter(&MyMod{name: "mod4"}, "mod4") startModules() + modulesOrder = []string{} shutdownModules() - assert.Equal(t, false, modules["bla"].(*MyMod).running) + assert.Equal(t, false, modulesMap["mod1"].(*MyMod).running) + assert.Equal(t, false, modulesMap["mod2"].(*MyMod).running) + assert.Equal(t, false, modulesMap["mod3"].(*MyMod).running) + assert.Equal(t, false, modulesMap["mod4"].(*MyMod).running) + assert.Equal(t, []string{"mod4", "mod1", "mod2", "mod3"}, modulesOrder) } From a6600efb14975335e72f20c2ec52c8ddef814f6d Mon Sep 17 00:00:00 2001 From: Henrique Rodrigues Date: Tue, 14 Aug 2018 14:29:04 -0300 Subject: [PATCH 2/2] check error on app.go --- app.go | 15 ++++++++++++--- module_test.go | 25 +++++++++++++++++-------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/app.go b/app.go index ae390fcb..d414c183 100644 --- a/app.go +++ b/app.go @@ -338,9 +338,18 @@ func Start() { app.serviceDiscovery.AddListener(app.rpcClient.(*cluster.GRPCClient)) } - RegisterModuleBefore(app.serviceDiscovery, "serviceDiscovery") - RegisterModuleBefore(app.rpcServer, "rpcServer") - RegisterModuleBefore(app.rpcClient, "rpcClient") + err := RegisterModuleBefore(app.serviceDiscovery, "serviceDiscovery") + if err != nil { + logger.Log.Fatal("failed to register service discovery module: %s", err.Error()) + } + err = RegisterModuleBefore(app.rpcServer, "rpcServer") + if err != nil { + logger.Log.Fatal("failed to register rpc server module: %s", err.Error()) + } + err = RegisterModuleBefore(app.rpcClient, "rpcClient") + if err != nil { + logger.Log.Fatal("failed to register rpc client module: %s", err.Error()) + } app.router.SetServiceDiscovery(app.serviceDiscovery) diff --git a/module_test.go b/module_test.go index 3b1e0d64..8741779d 100644 --- a/module_test.go +++ b/module_test.go @@ -86,10 +86,14 @@ func TestStartupModules(t *testing.T) { resetModules() Configure(true, "testtype", Standalone, map[string]string{}, viper.New()) - RegisterModule(&MyMod{name: "mod1"}, "mod1") - RegisterModuleBefore(&MyMod{name: "mod2"}, "mod2") - RegisterModuleBefore(&MyMod{name: "mod3"}, "mod3") - RegisterModuleAfter(&MyMod{name: "mod4"}, "mod4") + err := RegisterModule(&MyMod{name: "mod1"}, "mod1") + assert.NoError(t, err) + err = RegisterModuleBefore(&MyMod{name: "mod2"}, "mod2") + assert.NoError(t, err) + err = RegisterModuleBefore(&MyMod{name: "mod3"}, "mod3") + assert.NoError(t, err) + err = RegisterModuleAfter(&MyMod{name: "mod4"}, "mod4") + assert.NoError(t, err) startModules() assert.Equal(t, true, modulesMap["mod1"].(*MyMod).running) @@ -104,10 +108,15 @@ func TestShutdownModules(t *testing.T) { initApp() Configure(true, "testtype", Standalone, map[string]string{}, viper.New()) - RegisterModule(&MyMod{name: "mod1"}, "mod1") - RegisterModuleBefore(&MyMod{name: "mod2"}, "mod2") - RegisterModuleBefore(&MyMod{name: "mod3"}, "mod3") - RegisterModuleAfter(&MyMod{name: "mod4"}, "mod4") + err := RegisterModule(&MyMod{name: "mod1"}, "mod1") + assert.NoError(t, err) + err = RegisterModuleBefore(&MyMod{name: "mod2"}, "mod2") + assert.NoError(t, err) + err = RegisterModuleBefore(&MyMod{name: "mod3"}, "mod3") + assert.NoError(t, err) + err = RegisterModuleAfter(&MyMod{name: "mod4"}, "mod4") + assert.NoError(t, err) + startModules() modulesOrder = []string{}