diff --git a/server/errors.go b/server/errors.go index 1607391..922aea5 100644 --- a/server/errors.go +++ b/server/errors.go @@ -9,6 +9,7 @@ var ( ErrWebsocketMessageTypePacketAttrs = errors.New("MessageTypePacket must contain *Conn and []byte and int(MessageType)") ErrMessageTypeErrorAttrs = errors.New("MessageTypePacket must contain error and MessageErrorAction") ErrMessageTypeCrossErrorAttrs = errors.New("MessageTypeCross must contain int64(server id) and []byte") + ErrMessageTypeTickerErrorAttrs = errors.New("MessageTypeTicker must contain func()") ErrNetworkOnlySupportHttp = errors.New("the current network mode is not compatible with HttpRouter, only NetworkHttp is supported") ErrNetworkOnlySupportGRPC = errors.New("the current network mode is not compatible with RegGrpcServer, only NetworkGRPC is supported") ErrNetworkIncompatibleHttp = errors.New("the current network mode is not compatible with NetworkHttp") @@ -19,4 +20,5 @@ var ( ErrPleaseUseOrdinaryPacketHandle = errors.New("non Websocket mode, please use the RegConnectionReceivePacketEvent function to register") ErrOnlySupportSocket = errors.New("only supports Socket programming") ErrNoSupportCross = errors.New("the server does not support GetID or PushCrossMessage, please use the WithCross option to create the server") + ErrNoSupportTicker = errors.New("the server does not support Ticker, please use the WithTicker option to create the server") ) diff --git a/server/message.go b/server/message.go index 265536a..e296cb4 100644 --- a/server/message.go +++ b/server/message.go @@ -15,6 +15,10 @@ const ( // - int64(serverId) // - []byte MessageTypeCross + + // MessageTypeTicker 定时器消息类型 + // - func() + MessageTypeTicker ) var messageNames = map[MessageType]string{ @@ -111,3 +115,14 @@ func (slf MessageType) deconstructCross(attrs ...any) (serverId int64, packet [] } return } + +func (slf MessageType) deconstructTicker(attrs ...any) (caller func()) { + if len(attrs) != 1 { + panic(ErrMessageTypeTickerErrorAttrs) + } + var ok bool + if caller, ok = attrs[0].(func()); !ok { + panic(ErrMessageTypeTickerErrorAttrs) + } + return +} diff --git a/server/options.go b/server/options.go index dba24b2..1c7ba00 100644 --- a/server/options.go +++ b/server/options.go @@ -3,6 +3,7 @@ package server import ( "github.com/kercylan98/minotaur/utils/hash" "github.com/kercylan98/minotaur/utils/log" + "github.com/kercylan98/minotaur/utils/timer" "go.uber.org/zap" "google.golang.org/grpc" "reflect" @@ -22,7 +23,21 @@ const ( ) type Option func(srv *Server) -type CrossRegisterHandle func(server *Server) error + +// WithTicker 通过定时器创建服务器,为服务器添加定时器功能 +// - autonomy:定时器是否独立运行(独立运行的情况下不会作为服务器消息运行,会导致并发问题) +// - 多核与分流情况下需要考虑是否有必要 autonomy +func WithTicker(size int, autonomy bool) Option { + return func(srv *Server) { + if !autonomy { + srv.ticker = timer.GetTicker(size) + } else { + srv.ticker = timer.GetTicker(size, timer.WithCaller(func(name string, caller func()) { + srv.PushMessage(MessageTypeTicker, caller) + })) + } + } +} // WithCross 通过跨服的方式创建服务器 func WithCross(serverId int64, cross Cross) Option { diff --git a/server/server.go b/server/server.go index 94c5767..289d415 100644 --- a/server/server.go +++ b/server/server.go @@ -8,6 +8,7 @@ import ( "github.com/kercylan98/minotaur/utils/hash" "github.com/kercylan98/minotaur/utils/log" "github.com/kercylan98/minotaur/utils/synchronization" + "github.com/kercylan98/minotaur/utils/timer" "github.com/panjf2000/gnet" "github.com/pkg/errors" "github.com/xtaci/kcp-go/v5" @@ -77,6 +78,7 @@ type Server struct { diversionMessageChannels []chan *message // 分流消息管道 diversionConsistency *hash.Consistency // 哈希一致性分流器 websocketWriteMessageType int // websocket写入的消息类型 + ticker *timer.Ticker // 定时器 } // Run 使用特定地址运行服务器 @@ -332,6 +334,14 @@ func (slf *Server) GetID() int64 { return slf.id } +// Ticker 获取服务器定时器 +func (slf *Server) Ticker() *timer.Ticker { + if slf.ticker == nil { + panic(ErrNoSupportTicker) + } + return slf.ticker +} + // Shutdown 停止运行服务器 func (slf *Server) Shutdown(err error) { slf.isShutdown.Store(true) @@ -442,6 +452,9 @@ func (slf *Server) dispatchMessage(msg *message) { case MessageTypeCross: serverId, packet := msg.t.deconstructCross(msg.attrs...) slf.OnReceiveCrossPacketEvent(serverId, packet) + case MessageTypeTicker: + caller := msg.t.deconstructTicker(msg.attrs...) + caller() default: log.Warn("Server", zap.String("not support message type", msg.t.String())) }