github.com/cloudwego/kitex@v0.9.0/pkg/rpcinfo/ctx.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 "context" 21 22 "github.com/cloudwego/kitex/internal" 23 ) 24 25 type ctxRPCInfoKeyType struct{} 26 27 var ctxRPCInfoKey ctxRPCInfoKeyType 28 29 // NewCtxWithRPCInfo creates a new context with the RPCInfo given. 30 func NewCtxWithRPCInfo(ctx context.Context, ri RPCInfo) context.Context { 31 if ri != nil { 32 return context.WithValue(ctx, ctxRPCInfoKey, ri) 33 } 34 return ctx 35 } 36 37 // GetRPCInfo gets RPCInfo from ctx. 38 // Returns nil if not found. 39 func GetRPCInfo(ctx context.Context) RPCInfo { 40 if ri, ok := ctx.Value(ctxRPCInfoKey).(RPCInfo); ok { 41 return ri 42 } 43 return nil 44 } 45 46 // PutRPCInfo recycles the RPCInfo. This function is for internal use only. 47 func PutRPCInfo(ri RPCInfo) { 48 if v, ok := ri.(internal.Reusable); ok { 49 v.Recycle() 50 } 51 } 52 53 // FreezeRPCInfo returns a new context containing an RPCInfo that is safe 54 // to be used asynchronically. 55 // Note that the RPCStats of the freezed RPCInfo will be nil and 56 // the FreezeRPCInfo itself should not be used asynchronically. 57 // 58 // Example: 59 // 60 // func (p *MyServiceImpl) MyMethod(ctx context.Context, req *MyRequest) (resp *MyResponse, err error) { 61 // ri := rpcinfo.GetRPCInfo(ctx) 62 // go func(ctx context.Context) { 63 // ... 64 // ri := rpcinfo.GetRPCInfo(ctx) // not concurrent-safe 65 // ... 66 // }(ctx2) 67 // 68 // ctx2 := rpcinfo.FreezeRPCInfo(ctx) // this creates a read-only copy of `ri` and attaches it to the new context 69 // go func(ctx context.Context) { 70 // ... 71 // ri := rpcinfo.GetRPCInfo(ctx) // OK 72 // ... 73 // }(ctx2) 74 // } 75 func FreezeRPCInfo(ctx context.Context) context.Context { 76 ri := GetRPCInfo(ctx) 77 if ri == nil { 78 return ctx 79 } 80 return NewCtxWithRPCInfo(ctx, freeze(ri)) 81 }