You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

root_context.go 3.9 kB

4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package context
  2. import (
  3. "context"
  4. "fmt"
  5. "strings"
  6. "github.com/opentrx/seata-golang/v2/pkg/apis"
  7. "github.com/opentrx/seata-golang/v2/pkg/util/log"
  8. )
  9. const (
  10. KeyXID = "TX_XID"
  11. KeyXIDInterceptorType = "tx-xid-interceptor-type"
  12. KeyGlobalLockFlag = "TX_LOCK"
  13. )
  14. // RootContext store the global transaction context
  15. type RootContext struct {
  16. context.Context
  17. // like thread local map
  18. localMap map[string]interface{}
  19. }
  20. // NewRootContext return a pointer to RootContext
  21. func NewRootContext(ctx context.Context) *RootContext {
  22. rootCtx := &RootContext{
  23. Context: ctx,
  24. localMap: make(map[string]interface{}),
  25. }
  26. xID := ctx.Value(KeyXID)
  27. if xID != nil {
  28. xid := xID.(string)
  29. rootCtx.Bind(xid)
  30. }
  31. return rootCtx
  32. }
  33. // Set store key value to RootContext
  34. func (c *RootContext) Set(key string, value interface{}) {
  35. if c.localMap == nil {
  36. c.localMap = make(map[string]interface{})
  37. }
  38. c.localMap[key] = value
  39. }
  40. // Get get a value by given key from RootContext
  41. func (c *RootContext) Get(key string) (value interface{}, exists bool) {
  42. value, exists = c.localMap[key]
  43. return
  44. }
  45. // GetXID from RootContext get xid
  46. func (c *RootContext) GetXID() string {
  47. xID := c.localMap[KeyXID]
  48. xid, ok := xID.(string)
  49. if ok && xid != "" {
  50. return xid
  51. }
  52. xIDType := c.localMap[KeyXIDInterceptorType]
  53. xidType, success := xIDType.(string)
  54. if success && xidType != "" && strings.Contains(xidType, "_") {
  55. return strings.Split(xidType, "_")[0]
  56. }
  57. return ""
  58. }
  59. // GetXIDInterceptorType from RootContext get xid interceptor type
  60. func (c *RootContext) GetXIDInterceptorType() string {
  61. xIDType := c.localMap[KeyXIDInterceptorType]
  62. xidType, _ := xIDType.(string)
  63. return xidType
  64. }
  65. // Bind bind xid with RootContext
  66. func (c *RootContext) Bind(xid string) {
  67. log.Debugf("bind %s", xid)
  68. c.Set(KeyXID, xid)
  69. }
  70. // BindInterceptorType bind interceptor type with RootContext
  71. func (c *RootContext) BindInterceptorType(xidType string) {
  72. if xidType != "" {
  73. xidTypes := strings.Split(xidType, "_")
  74. if len(xidTypes) == 2 {
  75. c.BindInterceptorTypeWithBranchType(xidTypes[0],
  76. apis.BranchSession_BranchType(apis.BranchSession_BranchType_value[xidTypes[1]]))
  77. }
  78. }
  79. }
  80. // BindInterceptorTypeWithBranchType bind interceptor type and branch type with RootContext
  81. func (c *RootContext) BindInterceptorTypeWithBranchType(xid string, branchType apis.BranchSession_BranchType) {
  82. xidType := fmt.Sprintf("%s_%s", xid, branchType.String())
  83. log.Debugf("bind interceptor type xid=%s branchType=%s", xid, branchType.String())
  84. c.Set(KeyXIDInterceptorType, xidType)
  85. }
  86. // BindGlobalLockFlag bind global lock flag with RootContext
  87. func (c *RootContext) BindGlobalLockFlag() {
  88. log.Debug("local transaction global lock support enabled")
  89. c.Set(KeyGlobalLockFlag, KeyGlobalLockFlag)
  90. }
  91. // Unbind unbind xid with RootContext
  92. func (c *RootContext) Unbind() string {
  93. xID := c.localMap[KeyXID]
  94. xid, ok := xID.(string)
  95. if ok && xid != "" {
  96. log.Debugf("unbind %s", xid)
  97. delete(c.localMap, KeyXID)
  98. return xid
  99. }
  100. return ""
  101. }
  102. // UnbindInterceptorType unbind interceptor type with RootContext
  103. func (c *RootContext) UnbindInterceptorType() string {
  104. xidType := c.localMap[KeyXIDInterceptorType]
  105. xt, ok := xidType.(string)
  106. if ok && xt != "" {
  107. log.Debugf("unbind inteceptor type %s", xidType)
  108. delete(c.localMap, KeyXIDInterceptorType)
  109. return xt
  110. }
  111. return ""
  112. }
  113. // UnbindGlobalLockFlag unbind global lock flag with RootContext
  114. func (c *RootContext) UnbindGlobalLockFlag() {
  115. log.Debug("unbind global lock flag")
  116. delete(c.localMap, KeyGlobalLockFlag)
  117. }
  118. // InGlobalTransaction determine whether the context is in global transaction
  119. func (c *RootContext) InGlobalTransaction() bool {
  120. return c.localMap[KeyXID] != nil
  121. }
  122. // RequireGlobalLock return global lock flag
  123. func (c *RootContext) RequireGlobalLock() bool {
  124. _, exists := c.localMap[KeyGlobalLockFlag]
  125. return exists
  126. }