diff --git a/server/server.go b/server/server.go index b70094c..9b84fcf 100644 --- a/server/server.go +++ b/server/server.go @@ -97,18 +97,19 @@ type Server struct { cancel context.CancelFunc // 停止上下文 online *concurrent.BalanceMap[string, *Conn] // 在线连接 systemDispatcher *dispatcher // 系统消息分发器 - network Network // 网络类型 - addr string // 侦听地址 systemSignal chan os.Signal // 系统信号 closeChannel chan struct{} // 关闭信号 multipleRuntimeErrorChan chan error // 多服务器模式下的运行时错误 - dispatcherLock sync.RWMutex // 消息分发器锁 - isShutdown atomic.Bool // 是否已关闭 - messageCounter atomic.Int64 // 消息计数器 - isRunning bool // 是否正在运行 dispatchers map[string]*dispatcher // 消息分发器集合 dispatcherMember map[string]map[string]*Conn // 消息分发器包含的连接 currDispatcher map[string]*dispatcher // 当前连接所处消息分发器 + dispatcherLock sync.RWMutex // 消息分发器锁 + isShutdown atomic.Bool // 是否已关闭 + messageCounter atomic.Int64 // 消息计数器 + addr string // 侦听地址 + network Network // 网络类型 + isRunning bool // 是否正在运行 + services []func() // 服务 } // Run 使用特定地址运行服务器 @@ -130,6 +131,7 @@ func (slf *Server) Run(addr string) error { if slf.event == nil { return ErrConstructed } + onServicesInit(slf) slf.event.check() slf.addr = addr slf.startMessageStatistics() diff --git a/server/service.go b/server/service.go new file mode 100644 index 0000000..003d650 --- /dev/null +++ b/server/service.go @@ -0,0 +1,37 @@ +package server + +import ( + "github.com/kercylan98/minotaur/utils/log" + "reflect" +) + +// Service 兼容传统 service 设计模式的接口 +type Service interface { + // OnInit 初始化服务,该方法将会在 Server 初始化时执行 + // - 通常来说,该阶段发生任何错误都应该 panic 以阻止 Server 启动 + OnInit(srv *Server) +} + +// BindService 绑定服务到特定 Server,被绑定的服务将会在 Server 初始化时执行 Service.OnInit 方法 +func BindService(srv *Server, services ...Service) { + for _, service := range services { + srv.services = append(srv.services, func() { + name := reflect.TypeOf(service).String() + defer func(name string) { + if err := recover(); err != nil { + log.Error("Server", log.String("service", name), log.String("status", "initialization"), log.Any("err", err)) + panic(err) + } + }(name) + service.OnInit(srv) + log.Info("Server", log.String("service", name), log.String("status", "initialized")) + }) + } +} + +// onServicesInit 服务初始化 +func onServicesInit(srv *Server) { + for _, service := range srv.services { + service() + } +} diff --git a/server/service_test.go b/server/service_test.go new file mode 100644 index 0000000..a3bae8e --- /dev/null +++ b/server/service_test.go @@ -0,0 +1,30 @@ +package server_test + +import ( + "github.com/kercylan98/minotaur/server" + "testing" + "time" +) + +type TestService struct { +} + +func (ts *TestService) OnInit(srv *server.Server) { + srv.RegStartFinishEvent(func(srv *server.Server) { + println("Server started") + }) + + srv.RegStopEvent(func(srv *server.Server) { + println("Server stopped") + }) +} + +func TestBindService(t *testing.T) { + srv := server.New(server.NetworkNone, server.WithLimitLife(time.Second)) + + server.BindService(srv, new(TestService)) + + if err := srv.RunNone(); err != nil { + panic(err) + } +}