github.com/15mga/kiwi@v0.0.2-0.20240324021231-b95d5c3ac751/core/snd_request.go (about) 1 package core 2 3 import ( 4 "github.com/15mga/kiwi/worker" 5 "github.com/panjf2000/ants/v2" 6 "reflect" 7 "sync" 8 "sync/atomic" 9 "time" 10 11 "github.com/15mga/kiwi" 12 "github.com/15mga/kiwi/util" 13 ) 14 15 type SRequest struct { 16 sndPkt 17 isBytes bool 18 timer *time.Timer 19 okBytes util.FnInt64MBytes 20 okMsg util.FnInt64MMsg 21 fail util.FnInt64MUint16 22 disposed int32 23 } 24 25 func (r *SRequest) SetBytesHandler(fail util.FnInt64MUint16, ok util.FnInt64MBytes) { 26 r.isBytes = true 27 r.okBytes = ok 28 r.fail = fail 29 } 30 31 func (r *SRequest) SetHandler(fail util.FnInt64MUint16, ok util.FnInt64MMsg) { 32 r.isBytes = false 33 r.okMsg = ok 34 r.fail = fail 35 } 36 37 func (r *SRequest) OkBytes(head util.M, bytes []byte) { 38 if r.isDisposed() { 39 return 40 } 41 defer r.Dispose() 42 43 if r.isBytes { 44 if r.okBytes == nil { 45 return 46 } 47 r.okBytes(r.tid, head, bytes) 48 } else { 49 if r.okMsg == nil { 50 return 51 } 52 code, err := kiwi.Codec().ReqToResCode(r.svc, r.code) 53 if err != nil { 54 kiwi.TE(r.tid, err) 55 r.fail(r.tid, head, err.Code()) 56 return 57 } 58 var msg util.IMsg 59 if r.json { 60 msg, err = kiwi.Codec().JsonUnmarshal2(r.svc, code, bytes) 61 } else { 62 msg, err = kiwi.Codec().PbUnmarshal2(r.svc, code, bytes) 63 } 64 if err != nil { 65 kiwi.TE(r.tid, err) 66 r.fail(r.tid, head, err.Code()) 67 return 68 } 69 r.okMsg(r.tid, head, msg) 70 } 71 } 72 73 func (r *SRequest) Ok(head util.M, msg util.IMsg) { 74 if r.isDisposed() { 75 return 76 } 77 defer r.Dispose() 78 79 if r.isBytes { 80 bytes, err := kiwi.Codec().PbMarshal(msg) 81 if err != nil { 82 kiwi.TE(r.tid, err) 83 r.fail(r.tid, head, err.Code()) 84 return 85 } 86 r.okBytes(r.tid, head, bytes) 87 } else { 88 r.okMsg(r.tid, head, msg) 89 } 90 } 91 92 func (r *SRequest) Fail(head util.M, code uint16) { 93 if r.isDisposed() { 94 return 95 } 96 defer r.Dispose() 97 r.fail(r.tid, head, code) 98 } 99 100 func (r *SRequest) timeout() { 101 kiwi.TE2(r.tid, util.EcTimeout, r.head) 102 } 103 104 func (r *SRequest) isDisposed() bool { 105 return atomic.LoadInt32(&r.disposed) == 1 106 } 107 108 func (r *SRequest) Dispose() { 109 if atomic.CompareAndSwapInt32(&r.disposed, 0, 1) { 110 r.sndPkt.Dispose() 111 r.timer.Stop() 112 _ReqPool.Put(r) 113 } 114 } 115 116 var ( 117 ResponseTimeoutDur = time.Duration(5000) * time.Millisecond 118 _ReqPool = sync.Pool{ 119 New: func() any { 120 return &SRequest{} 121 }, 122 } 123 ) 124 125 func newBytesRequest(pid int64, svc kiwi.TSvc, code kiwi.TCode, head util.M, json bool, payload []byte) *SRequest { 126 if head == nil { 127 head = util.M{} 128 } 129 GenHead(head) 130 131 req := _ReqPool.Get().(*SRequest) 132 req.pid = pid 133 req.svc, req.code = svc, code 134 req.json = json 135 req.head = head 136 req.payload = payload 137 req.InitHead() 138 req.timer = time.AfterFunc(ResponseTimeoutDur, req.timeout) 139 req.tid = kiwi.TC(pid, head, IsExcludeLog(svc, code)) 140 atomic.StoreInt32(&req.disposed, 0) 141 return req 142 } 143 144 func newRequest(pid int64, head util.M, json bool, msg util.IMsg) *SRequest { 145 var ( 146 payload []byte 147 err *util.Err 148 ) 149 if json { 150 payload, err = kiwi.Codec().JsonMarshal(msg) 151 } else { 152 payload, err = kiwi.Codec().PbMarshal(msg) 153 } 154 if err != nil { 155 kiwi.Fatal(err) 156 return nil 157 } 158 svc, code := kiwi.Codec().MsgToSvcCode(msg) 159 req := newBytesRequest(pid, svc, code, head, json, payload) 160 req.msg = msg 161 return req 162 } 163 164 func Req[ResT util.IMsg](pid int64, head util.M, msg util.IMsg) (ResT, util.M, uint16) { 165 req := newRequest(pid, head, false, msg) 166 okCh := make(chan util.IMsg, 1) 167 failCh := make(chan uint16, 1) 168 var rm util.M 169 req.SetHandler(func(_ int64, m util.M, code uint16) { 170 rm = m 171 failCh <- code 172 }, func(_ int64, m util.M, a util.IMsg) { 173 rm = m 174 okCh <- a 175 }) 176 kiwi.Router().AddRequest(req) 177 kiwi.Node().Request(req) 178 select { 179 case res := <-okCh: 180 r, ok := res.(ResT) 181 if !ok { 182 return util.Default[ResT](), nil, util.EcWrongType 183 } 184 return r, rm, 0 185 case code := <-failCh: 186 return util.Default[ResT](), rm, code 187 } 188 } 189 190 func Req2(pid int64, head util.M, msg util.IMsg) (util.IMsg, util.M, uint16) { 191 req := newRequest(pid, head, false, msg) 192 okCh := make(chan util.IMsg) 193 failCh := make(chan uint16, 1) 194 var rm util.M 195 req.SetHandler(func(_ int64, m util.M, code uint16) { 196 rm = m 197 failCh <- code 198 }, func(_ int64, m util.M, a util.IMsg) { 199 rm = m 200 okCh <- a 201 }) 202 kiwi.Router().AddRequest(req) 203 kiwi.Node().Request(req) 204 select { 205 case res := <-okCh: 206 return res, rm, 0 207 case code := <-failCh: 208 return nil, rm, code 209 } 210 } 211 212 func ReqBytes(pid int64, svc kiwi.TSvc, code kiwi.TCode, head util.M, json bool, payload []byte) ([]byte, util.M, uint16) { 213 req := newBytesRequest(pid, svc, code, head, json, payload) 214 okCh := make(chan []byte) 215 failCh := make(chan uint16, 1) 216 var rm util.M 217 req.SetBytesHandler(func(_ int64, m util.M, code uint16) { 218 rm = m 219 failCh <- code 220 }, func(_ int64, m util.M, payload []byte) { 221 rm = m 222 okCh <- payload 223 }) 224 kiwi.Router().AddRequest(req) 225 kiwi.Node().Request(req) 226 select { 227 case res := <-okCh: 228 return res, rm, 0 229 case code := <-failCh: 230 return nil, rm, code 231 } 232 } 233 234 func ReqNode[ResT any](nodeId, pid int64, head util.M, msg util.IMsg) (ResT, util.M, uint16) { 235 req := newRequest(pid, head, false, msg) 236 okCh := make(chan util.IMsg, 1) 237 failCh := make(chan uint16, 1) 238 var rm util.M 239 req.SetHandler(func(_ int64, m util.M, code uint16) { 240 rm = m 241 failCh <- code 242 }, func(_ int64, m util.M, a util.IMsg) { 243 rm = m 244 okCh <- a 245 }) 246 kiwi.Router().AddRequest(req) 247 kiwi.Node().RequestNode(nodeId, req) 248 select { 249 case res := <-okCh: 250 r, ok := res.(ResT) 251 if !ok { 252 return util.Default[ResT](), nil, util.EcWrongType 253 } 254 return r, rm, 0 255 case code := <-failCh: 256 return util.Default[ResT](), nil, code 257 } 258 } 259 260 func ReqNodeBytes(nodeId, pid int64, svc kiwi.TSvc, code kiwi.TCode, head util.M, json bool, payload []byte) ([]byte, util.M, uint16) { 261 req := newBytesRequest(pid, svc, code, head, json, payload) 262 okCh := make(chan []byte, 1) 263 failCh := make(chan uint16, 1) 264 var rm util.M 265 req.SetBytesHandler(func(_ int64, m util.M, code uint16) { 266 rm = m 267 failCh <- code 268 }, func(_ int64, m util.M, payload []byte) { 269 rm = m 270 okCh <- payload 271 }) 272 kiwi.Router().AddRequest(req) 273 kiwi.Node().RequestNode(nodeId, req) 274 select { 275 case res := <-okCh: 276 return res, rm, 0 277 case code := <-failCh: 278 return nil, nil, code 279 } 280 } 281 282 func AsyncReq(pid int64, head util.M, msg util.IMsg, onFail util.FnInt64MUint16, onOk util.FnInt64MMsg) { 283 req := newRequest(pid, head, false, msg) 284 req.SetHandler(onFail, onOk) 285 kiwi.Router().AddRequest(req) 286 kiwi.Node().Request(req) 287 } 288 289 func AsyncReqBytes(pid int64, svc kiwi.TSvc, code kiwi.TCode, head util.M, json bool, payload []byte, 290 onFail util.FnInt64MUint16, onOk util.FnInt64MBytes) { 291 req := newBytesRequest(pid, svc, code, head, json, payload) 292 req.SetBytesHandler(onFail, onOk) 293 kiwi.Router().AddRequest(req) 294 kiwi.Node().Request(req) 295 } 296 297 func AsyncReqNode(pid, nodeId int64, head util.M, msg util.IMsg, onFail util.FnInt64MUint16, onOk util.FnInt64MMsg) { 298 req := newRequest(pid, head, false, msg) 299 req.SetHandler(onFail, onOk) 300 kiwi.Router().AddRequest(req) 301 kiwi.Node().RequestNode(nodeId, req) 302 } 303 304 func AsyncReqNodeBytes(pid, nodeId int64, svc kiwi.TSvc, code kiwi.TCode, head util.M, json bool, payload []byte, 305 onFail util.FnInt64MUint16, onOk util.FnInt64MBytes) { 306 req := newBytesRequest(pid, svc, code, head, json, payload) 307 req.SetBytesHandler(onFail, onOk) 308 kiwi.Router().AddRequest(req) 309 kiwi.Node().RequestNode(nodeId, req) 310 } 311 312 func AsyncSubReq[ResT util.IMsg](pkt kiwi.IRcvRequest, head util.M, req util.IMsg, resFail util.FnInt64MUint16, resOk func(int64, util.M, ResT)) { 313 switch pkt.Worker() { 314 case kiwi.EWorkerGo: 315 AsyncReq(pkt.Tid(), head, req, func(tid int64, head util.M, code uint16) { 316 if resFail == nil { 317 return 318 } 319 e := ants.Submit(func() { 320 resFail(tid, head, code) 321 }) 322 if e != nil { 323 kiwi.TE3(pkt.Tid(), util.EcServiceErr, e) 324 } 325 }, func(tid int64, head util.M, msg util.IMsg) { 326 res, ok := msg.(ResT) 327 if ok { 328 e := ants.Submit(func() { 329 resOk(tid, head, res) 330 }) 331 if e != nil { 332 kiwi.TE3(pkt.Tid(), util.EcServiceErr, e) 333 } 334 } else { 335 kiwi.TE2(pkt.Tid(), util.EcWrongType, util.M{ 336 "expected": reflect.TypeOf(util.Default[ResT]()), 337 "actual": reflect.TypeOf(msg), 338 }) 339 } 340 }) 341 case kiwi.EWorkerActive: 342 AsyncReq(pkt.Tid(), head, req, func(tid int64, head util.M, code uint16) { 343 if resFail == nil { 344 return 345 } 346 worker.Active().Push(pkt.WorkerKey(), func(params []any) { 347 resFail(util.SplitSlc3[int64, util.M, uint16](params)) 348 }, tid, head, code) 349 }, func(tid int64, head util.M, msg util.IMsg) { 350 res, ok := msg.(ResT) 351 if ok { 352 worker.Active().Push(pkt.WorkerKey(), func(params []any) { 353 resOk(util.SplitSlc3[int64, util.M, ResT](params)) 354 }, tid, head, res) 355 } else { 356 kiwi.TE2(pkt.Tid(), util.EcWrongType, util.M{ 357 "expected": reflect.TypeOf(util.Default[ResT]()), 358 "actual": reflect.TypeOf(msg), 359 }) 360 } 361 }) 362 case kiwi.EWorkerShare: 363 AsyncReq(pkt.Tid(), head, req, func(tid int64, head util.M, code uint16) { 364 if resFail == nil { 365 return 366 } 367 worker.Share().Push(pkt.WorkerKey(), func(params []any) { 368 resFail(util.SplitSlc3[int64, util.M, uint16](params)) 369 }, tid, head, code) 370 }, func(tid int64, head util.M, msg util.IMsg) { 371 res, ok := msg.(ResT) 372 if ok { 373 worker.Share().Push(pkt.WorkerKey(), func(params []any) { 374 resOk(util.SplitSlc3[int64, util.M, ResT](params)) 375 }, tid, head, res) 376 } else { 377 kiwi.TE2(pkt.Tid(), util.EcWrongType, util.M{ 378 "expected": reflect.TypeOf(util.Default[ResT]()), 379 "actual": reflect.TypeOf(msg), 380 }) 381 } 382 }) 383 case kiwi.EWorkerGlobal: 384 AsyncReq(pkt.Tid(), head, req, func(tid int64, head util.M, code uint16) { 385 if resFail == nil { 386 return 387 } 388 worker.Global().Push(func(params []any) { 389 resFail(util.SplitSlc3[int64, util.M, uint16](params)) 390 }, tid, head, code) 391 }, func(tid int64, head util.M, msg util.IMsg) { 392 res, ok := msg.(ResT) 393 if ok { 394 worker.Global().Push(func(params []any) { 395 resOk(util.SplitSlc3[int64, util.M, ResT](params)) 396 }, tid, head, res) 397 } else { 398 kiwi.TE2(pkt.Tid(), util.EcWrongType, util.M{ 399 "expected": reflect.TypeOf(util.Default[ResT]()), 400 "actual": reflect.TypeOf(msg), 401 }) 402 } 403 }) 404 case kiwi.EWorkerSelf: 405 AsyncReq(pkt.Tid(), head, req, func(tid int64, head util.M, code uint16) { 406 if resFail == nil { 407 return 408 } 409 resFail(tid, head, code) 410 }, func(tid int64, head util.M, msg util.IMsg) { 411 res, ok := msg.(ResT) 412 if ok { 413 resOk(tid, head, res) 414 } else { 415 kiwi.TE2(pkt.Tid(), util.EcWrongType, util.M{ 416 "expected": reflect.TypeOf(util.Default[ResT]()), 417 "actual": reflect.TypeOf(msg), 418 }) 419 } 420 }) 421 } 422 }