github.com/cloudwego/kitex@v0.9.0/pkg/rpcinfo/invocation.go (about) 1 /* 2 * Copyright 2021 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package rpcinfo 18 19 import ( 20 "sync" 21 "sync/atomic" 22 23 "github.com/cloudwego/kitex/pkg/kerrors" 24 ) 25 26 var ( 27 _ Invocation = (*invocation)(nil) 28 _ InvocationSetter = (*invocation)(nil) 29 invocationPool sync.Pool 30 globalSeqID int32 = 0 31 ) 32 33 func init() { 34 invocationPool.New = newInvocation 35 } 36 37 // InvocationSetter is used to set information about an RPC. 38 type InvocationSetter interface { 39 SetPackageName(name string) 40 SetServiceName(name string) 41 SetMethodName(name string) 42 SetSeqID(seqID int32) 43 SetBizStatusErr(err kerrors.BizStatusErrorIface) 44 SetExtra(key string, value interface{}) 45 Reset() 46 } 47 type invocation struct { 48 packageName string 49 serviceName string 50 methodName string 51 seqID int32 52 bizErr kerrors.BizStatusErrorIface 53 extra map[string]interface{} 54 } 55 56 // NewInvocation creates a new Invocation with the given service, method and optional package. 57 func NewInvocation(service, method string, pkgOpt ...string) *invocation { 58 ivk := invocationPool.Get().(*invocation) 59 ivk.seqID = genSeqID() 60 ivk.serviceName = service 61 ivk.methodName = method 62 if len(pkgOpt) > 0 { 63 ivk.packageName = pkgOpt[0] 64 } 65 return ivk 66 } 67 68 // NewServerInvocation to get Invocation for new request in server side 69 func NewServerInvocation() Invocation { 70 ivk := invocationPool.Get().(*invocation) 71 return ivk 72 } 73 74 func genSeqID() int32 { 75 id := atomic.AddInt32(&globalSeqID, 1) 76 if id == 0 { 77 // seqID is non-0 to avoid potential default value judgments leading to error handling 78 id = atomic.AddInt32(&globalSeqID, 1) 79 } 80 return id 81 } 82 83 func newInvocation() interface{} { 84 return &invocation{} 85 } 86 87 // SeqID implements the Invocation interface. 88 func (i *invocation) SeqID() int32 { 89 return i.seqID 90 } 91 92 // SetSeqID implements the InvocationSetter interface. 93 func (i *invocation) SetSeqID(seqID int32) { 94 i.seqID = seqID 95 } 96 97 func (i *invocation) PackageName() string { 98 return i.packageName 99 } 100 101 func (i *invocation) SetPackageName(name string) { 102 i.packageName = name 103 } 104 105 func (i *invocation) ServiceName() string { 106 return i.serviceName 107 } 108 109 // SetServiceName implements the InvocationSetter interface. 110 func (i *invocation) SetServiceName(name string) { 111 i.serviceName = name 112 } 113 114 // MethodName implements the Invocation interface. 115 func (i *invocation) MethodName() string { 116 return i.methodName 117 } 118 119 // SetMethodName implements the InvocationSetter interface. 120 func (i *invocation) SetMethodName(name string) { 121 i.methodName = name 122 } 123 124 // BizStatusErr implements the Invocation interface. 125 func (i *invocation) BizStatusErr() kerrors.BizStatusErrorIface { 126 return i.bizErr 127 } 128 129 // SetBizStatusErr implements the InvocationSetter interface. 130 func (i *invocation) SetBizStatusErr(err kerrors.BizStatusErrorIface) { 131 i.bizErr = err 132 } 133 134 func (i *invocation) SetExtra(key string, value interface{}) { 135 if i.extra == nil { 136 i.extra = map[string]interface{}{} 137 } 138 i.extra[key] = value 139 } 140 141 func (i *invocation) Extra(key string) interface{} { 142 if i.extra == nil { 143 return nil 144 } 145 return i.extra[key] 146 } 147 148 // Reset implements the InvocationSetter interface. 149 func (i *invocation) Reset() { 150 i.zero() 151 } 152 153 // Recycle reuses the invocation. 154 func (i *invocation) Recycle() { 155 i.zero() 156 invocationPool.Put(i) 157 } 158 159 func (i *invocation) zero() { 160 i.seqID = 0 161 i.packageName = "" 162 i.serviceName = "" 163 i.methodName = "" 164 i.bizErr = nil 165 for key := range i.extra { 166 delete(i.extra, key) 167 } 168 }