This repository has been archived by the owner on Aug 16, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdispatcher.go
189 lines (155 loc) · 3.69 KB
/
dispatcher.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package fairy
import (
"fmt"
"math"
"reflect"
)
var gDispatcher = NewDispatcher()
func GetDispatcher() *Dispatcher {
return gDispatcher
}
func NewDispatcher() *Dispatcher {
dispatcher := &Dispatcher{}
dispatcher.nameMap = make(map[string]*Handler)
return dispatcher
}
// RegisterHandler 注册消息回调
func RegisterHandler(key interface{}, cb HandlerCB) *Handler {
return GetDispatcher().Register(key, cb, QueueMainID)
}
// InvokeHandler 调用Handler
func InvokeHandler(conn IConn, packet IPacket, handler *Handler) {
hctx := HandlerCtx{}
hctx.Init(conn, packet, handler, GetDispatcher().Middlewares())
hctx.Next()
}
// HandlerCtx 支持中间件,在Dispatcher中注册
type HandlerCtx struct {
IConn
packet IPacket
args []interface{} // 附加参数
handler *Handler // 回调
chain []HandlerCB // 中间件
index int // 索引
}
func (ctx *HandlerCtx) Init(conn IConn, packet IPacket, handler *Handler, chain []HandlerCB) {
ctx.IConn = conn
ctx.packet = packet
ctx.handler = handler
ctx.chain = chain
ctx.index = -1
}
func (ctx *HandlerCtx) Packet() IPacket {
return ctx.packet
}
func (ctx *HandlerCtx) MsgID() uint {
return ctx.packet.GetId()
}
func (ctx *HandlerCtx) MsgName() string {
return ctx.packet.GetName()
}
func (ctx *HandlerCtx) Message() interface{} {
return ctx.packet.GetMessage()
}
func (ctx *HandlerCtx) Len() int {
return len(ctx.args)
}
func (ctx *HandlerCtx) Add(v interface{}) {
ctx.args = append(ctx.args, v)
}
func (ctx *HandlerCtx) Get(index int) interface{} {
return ctx.args[index]
}
func (ctx *HandlerCtx) Next() {
ctx.index++
if ctx.index < len(ctx.chain) {
cb := ctx.chain[ctx.index]
cb(ctx)
} else if ctx.index == len(ctx.chain) {
ctx.handler.Func(ctx)
// finish
ctx.index++
}
}
// HandlerCB 消息回调
type HandlerCB func(ctx *HandlerCtx)
// Handler 消息处理
type Handler struct {
Func HandlerCB
QueueId uint
Data interface{}
}
// Dispatcher 消息回调管理,id不能超过uint16
// 支持添加中间件
type Dispatcher struct {
nameMap map[string]*Handler
idArray []*Handler
middlewares []HandlerCB
}
func (d *Dispatcher) Use(cb HandlerCB) {
d.middlewares = append(d.middlewares, cb)
}
func (d *Dispatcher) Middlewares() []HandlerCB {
return d.middlewares
}
// Register 注册消息回调,可以指定队列
func (d *Dispatcher) Register(key interface{}, cb HandlerCB, queueId uint) *Handler {
id := uint(0)
name := ""
switch key.(type) {
case int:
id = uint(key.(int))
case uint:
id = key.(uint)
case string:
name = key.(string)
default:
// must be struct!!!
// example:Register(&LoginReq{}, handler) or Register(LoginReq{}, handler)
rtype := reflect.TypeOf(key)
if rtype.Kind() == reflect.Ptr {
rtype = rtype.Elem()
}
if rtype.Kind() == reflect.Struct {
name = rtype.Name()
} else {
panic(fmt.Sprintf("register handler fail,bad key type!key=%+v", key))
}
}
handler := &Handler{Func: cb, QueueId: queueId}
if id > 0 {
// 通过id注册
if id > math.MaxUint16 {
panic("handler id overflow")
}
if int(id) >= len(d.idArray) {
targets := make([]*Handler, id+1)
copy(targets, d.idArray)
d.idArray = targets
}
d.idArray[id] = handler
} else if name != "" {
// 通过名字注册
d.nameMap[name] = handler
}
return handler
}
func (d *Dispatcher) GetHandler(id uint, name string) *Handler {
if id > 0 {
// 通过id查找
if int(id) < len(d.idArray) {
return d.idArray[id]
}
return nil
}
return d.nameMap[name]
}
func (d *Dispatcher) GetHandlerById(id uint) *Handler {
if int(id) < len(d.idArray) {
return d.idArray[id]
}
return nil
}
func (d *Dispatcher) GetHandlerByName(name string) *Handler {
return d.nameMap[name]
}