|
- package context
-
- import (
- "context"
- "fmt"
- "strings"
-
- "github.com/opentrx/seata-golang/v2/pkg/apis"
- "github.com/opentrx/seata-golang/v2/pkg/util/log"
- )
-
- const (
- KeyXID = "TX_XID"
- KeyXIDInterceptorType = "tx-xid-interceptor-type"
- KeyGlobalLockFlag = "TX_LOCK"
- )
-
- // RootContext store the global transaction context
- type RootContext struct {
- context.Context
-
- // like thread local map
- localMap map[string]interface{}
- }
-
- // NewRootContext return a pointer to RootContext
- func NewRootContext(ctx context.Context) *RootContext {
- rootCtx := &RootContext{
- Context: ctx,
- localMap: make(map[string]interface{}),
- }
-
- xID := ctx.Value(KeyXID)
- if xID != nil {
- xid := xID.(string)
- rootCtx.Bind(xid)
- }
- return rootCtx
- }
-
- // Set store key value to RootContext
- func (c *RootContext) Set(key string, value interface{}) {
- if c.localMap == nil {
- c.localMap = make(map[string]interface{})
- }
- c.localMap[key] = value
- }
-
- // Get get a value by given key from RootContext
- func (c *RootContext) Get(key string) (value interface{}, exists bool) {
- value, exists = c.localMap[key]
- return
- }
-
- // GetXID from RootContext get xid
- func (c *RootContext) GetXID() string {
- xID := c.localMap[KeyXID]
- xid, ok := xID.(string)
- if ok && xid != "" {
- return xid
- }
-
- xIDType := c.localMap[KeyXIDInterceptorType]
- xidType, success := xIDType.(string)
-
- if success && xidType != "" && strings.Contains(xidType, "_") {
- return strings.Split(xidType, "_")[0]
- }
-
- return ""
- }
-
- // GetXIDInterceptorType from RootContext get xid interceptor type
- func (c *RootContext) GetXIDInterceptorType() string {
- xIDType := c.localMap[KeyXIDInterceptorType]
- xidType, _ := xIDType.(string)
- return xidType
- }
-
- // Bind bind xid with RootContext
- func (c *RootContext) Bind(xid string) {
- log.Debugf("bind %s", xid)
- c.Set(KeyXID, xid)
- }
-
- // BindInterceptorType bind interceptor type with RootContext
- func (c *RootContext) BindInterceptorType(xidType string) {
- if xidType != "" {
- xidTypes := strings.Split(xidType, "_")
-
- if len(xidTypes) == 2 {
- c.BindInterceptorTypeWithBranchType(xidTypes[0],
- apis.BranchSession_BranchType(apis.BranchSession_BranchType_value[xidTypes[1]]))
- }
- }
- }
-
- // BindInterceptorTypeWithBranchType bind interceptor type and branch type with RootContext
- func (c *RootContext) BindInterceptorTypeWithBranchType(xid string, branchType apis.BranchSession_BranchType) {
- xidType := fmt.Sprintf("%s_%s", xid, branchType.String())
- log.Debugf("bind interceptor type xid=%s branchType=%s", xid, branchType.String())
- c.Set(KeyXIDInterceptorType, xidType)
- }
-
- // BindGlobalLockFlag bind global lock flag with RootContext
- func (c *RootContext) BindGlobalLockFlag() {
- log.Debug("local transaction global lock support enabled")
- c.Set(KeyGlobalLockFlag, KeyGlobalLockFlag)
- }
-
- // Unbind unbind xid with RootContext
- func (c *RootContext) Unbind() string {
- xID := c.localMap[KeyXID]
- xid, ok := xID.(string)
- if ok && xid != "" {
- log.Debugf("unbind %s", xid)
- delete(c.localMap, KeyXID)
- return xid
- }
- return ""
-
- }
-
- // UnbindInterceptorType unbind interceptor type with RootContext
- func (c *RootContext) UnbindInterceptorType() string {
- xidType := c.localMap[KeyXIDInterceptorType]
- xt, ok := xidType.(string)
- if ok && xt != "" {
- log.Debugf("unbind inteceptor type %s", xidType)
- delete(c.localMap, KeyXIDInterceptorType)
- return xt
- }
- return ""
- }
-
- // UnbindGlobalLockFlag unbind global lock flag with RootContext
- func (c *RootContext) UnbindGlobalLockFlag() {
- log.Debug("unbind global lock flag")
- delete(c.localMap, KeyGlobalLockFlag)
- }
-
- // InGlobalTransaction determine whether the context is in global transaction
- func (c *RootContext) InGlobalTransaction() bool {
- return c.localMap[KeyXID] != nil
- }
-
- // RequireGlobalLock return global lock flag
- func (c *RootContext) RequireGlobalLock() bool {
- _, exists := c.localMap[KeyGlobalLockFlag]
- return exists
- }
|