github.com/cloudwego/kitex@v0.9.0/pkg/generic/generic_service.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 generic 18 19 import ( 20 "context" 21 "fmt" 22 23 "github.com/apache/thrift/lib/go/thrift" 24 25 gproto "github.com/cloudwego/kitex/pkg/generic/proto" 26 gthrift "github.com/cloudwego/kitex/pkg/generic/thrift" 27 codecThrift "github.com/cloudwego/kitex/pkg/remote/codec/thrift" 28 "github.com/cloudwego/kitex/pkg/serviceinfo" 29 ) 30 31 // Service generic service interface 32 type Service interface { 33 // GenericCall handle the generic call 34 GenericCall(ctx context.Context, method string, request interface{}) (response interface{}, err error) 35 } 36 37 // ServiceInfo create a generic ServiceInfo 38 func ServiceInfo(pcType serviceinfo.PayloadCodec) *serviceinfo.ServiceInfo { 39 return newServiceInfo(pcType) 40 } 41 42 func newServiceInfo(pcType serviceinfo.PayloadCodec) *serviceinfo.ServiceInfo { 43 serviceName := serviceinfo.GenericService 44 handlerType := (*Service)(nil) 45 methods := map[string]serviceinfo.MethodInfo{ 46 serviceinfo.GenericMethod: serviceinfo.NewMethodInfo(callHandler, newGenericServiceCallArgs, newGenericServiceCallResult, false), 47 } 48 svcInfo := &serviceinfo.ServiceInfo{ 49 ServiceName: serviceName, 50 HandlerType: handlerType, 51 Methods: methods, 52 PayloadCodec: pcType, 53 Extra: make(map[string]interface{}), 54 } 55 svcInfo.Extra["generic"] = true 56 return svcInfo 57 } 58 59 func callHandler(ctx context.Context, handler, arg, result interface{}) error { 60 realArg := arg.(*Args) 61 realResult := result.(*Result) 62 success, err := handler.(Service).GenericCall(ctx, realArg.Method, realArg.Request) 63 if err != nil { 64 return err 65 } 66 realResult.Success = success 67 return nil 68 } 69 70 func newGenericServiceCallArgs() interface{} { 71 return &Args{} 72 } 73 74 func newGenericServiceCallResult() interface{} { 75 return &Result{} 76 } 77 78 // WithCodec set codec instance for Args or Result 79 type WithCodec interface { 80 SetCodec(codec interface{}) 81 } 82 83 // Args generic request 84 type Args struct { 85 Request interface{} 86 Method string 87 base *gthrift.Base 88 inner interface{} 89 } 90 91 var ( 92 _ codecThrift.MessageReaderWithMethodWithContext = (*Args)(nil) 93 _ codecThrift.MessageWriterWithContext = (*Args)(nil) 94 _ WithCodec = (*Args)(nil) 95 ) 96 97 // SetCodec ... 98 func (g *Args) SetCodec(inner interface{}) { 99 g.inner = inner 100 } 101 102 func (g *Args) GetOrSetBase() interface{} { 103 if g.base == nil { 104 g.base = gthrift.NewBase() 105 } 106 return g.base 107 } 108 109 // Write ... 110 func (g *Args) Write(ctx context.Context, out thrift.TProtocol) error { 111 if w, ok := g.inner.(gthrift.MessageWriter); ok { 112 return w.Write(ctx, out, g.Request, g.base) 113 } 114 return fmt.Errorf("unexpected Args writer type: %T", g.inner) 115 } 116 117 func (g *Args) WritePb(ctx context.Context) (interface{}, error) { 118 if w, ok := g.inner.(gproto.MessageWriter); ok { 119 return w.Write(ctx, g.Request) 120 } 121 return nil, fmt.Errorf("unexpected Args writer type: %T", g.inner) 122 } 123 124 // Read ... 125 func (g *Args) Read(ctx context.Context, method string, in thrift.TProtocol) error { 126 if w, ok := g.inner.(gthrift.MessageReader); ok { 127 g.Method = method 128 var err error 129 g.Request, err = w.Read(ctx, method, in) 130 return err 131 } 132 return fmt.Errorf("unexpected Args reader type: %T", g.inner) 133 } 134 135 func (g *Args) ReadPb(ctx context.Context, method string, in []byte) error { 136 if w, ok := g.inner.(gproto.MessageReader); ok { 137 g.Method = method 138 var err error 139 g.Request, err = w.Read(ctx, method, in) 140 return err 141 } 142 return fmt.Errorf("unexpected Args reader type: %T", g.inner) 143 } 144 145 // GetFirstArgument implements util.KitexArgs. 146 func (g *Args) GetFirstArgument() interface{} { 147 return g.Request 148 } 149 150 // Result generic response 151 type Result struct { 152 Success interface{} 153 inner interface{} 154 } 155 156 var ( 157 _ codecThrift.MessageReaderWithMethodWithContext = (*Result)(nil) 158 _ codecThrift.MessageWriterWithContext = (*Result)(nil) 159 _ WithCodec = (*Result)(nil) 160 ) 161 162 // SetCodec ... 163 func (r *Result) SetCodec(inner interface{}) { 164 r.inner = inner 165 } 166 167 // Write ... 168 func (r *Result) Write(ctx context.Context, out thrift.TProtocol) error { 169 if w, ok := r.inner.(gthrift.MessageWriter); ok { 170 return w.Write(ctx, out, r.Success, nil) 171 } 172 return fmt.Errorf("unexpected Result writer type: %T", r.inner) 173 } 174 175 func (r *Result) WritePb(ctx context.Context) (interface{}, error) { 176 if w, ok := r.inner.(gproto.MessageWriter); ok { 177 return w.Write(ctx, r.Success) 178 } 179 return nil, fmt.Errorf("unexpected Result writer type: %T", r.inner) 180 } 181 182 // Read ... 183 func (r *Result) Read(ctx context.Context, method string, in thrift.TProtocol) error { 184 if w, ok := r.inner.(gthrift.MessageReader); ok { 185 var err error 186 r.Success, err = w.Read(ctx, method, in) 187 return err 188 } 189 return fmt.Errorf("unexpected Result reader type: %T", r.inner) 190 } 191 192 func (r *Result) ReadPb(ctx context.Context, method string, in []byte) error { 193 if w, ok := r.inner.(gproto.MessageReader); ok { 194 var err error 195 r.Success, err = w.Read(ctx, method, in) 196 return err 197 } 198 return fmt.Errorf("unexpected Result reader type: %T", r.inner) 199 } 200 201 // GetSuccess implements util.KitexResult. 202 func (r *Result) GetSuccess() interface{} { 203 if !r.IsSetSuccess() { 204 return nil 205 } 206 return r.Success 207 } 208 209 // SetSuccess implements util.KitexResult. 210 func (r *Result) SetSuccess(x interface{}) { 211 r.Success = x 212 } 213 214 // IsSetSuccess ... 215 func (r *Result) IsSetSuccess() bool { 216 return r.Success != nil 217 } 218 219 // GetResult ... 220 func (r *Result) GetResult() interface{} { 221 return r.Success 222 }