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  }