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.

global_transaction_manager.go 5.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package manager
  18. import (
  19. "context"
  20. "fmt"
  21. "sync"
  22. )
  23. import (
  24. "github.com/pkg/errors"
  25. )
  26. import (
  27. "github.com/seata/seata-go/pkg/common/log"
  28. "github.com/seata/seata-go/pkg/protocol/message"
  29. "github.com/seata/seata-go/pkg/protocol/seatactx"
  30. "github.com/seata/seata-go/pkg/protocol/transaction"
  31. "github.com/seata/seata-go/pkg/remoting/getty"
  32. "github.com/seata/seata-go/pkg/tm/api"
  33. )
  34. type GlobalTransaction struct {
  35. Xid string
  36. Status transaction.GlobalStatus
  37. Role transaction.GlobalTransactionRole
  38. }
  39. var (
  40. // singletone ResourceManagerFacade
  41. globalTransactionManager *GlobalTransactionManager
  42. onceGlobalTransactionManager = &sync.Once{}
  43. )
  44. func GetGlobalTransactionManager() *GlobalTransactionManager {
  45. if globalTransactionManager == nil {
  46. onceGlobalTransactionManager.Do(func() {
  47. globalTransactionManager = &GlobalTransactionManager{}
  48. })
  49. }
  50. return globalTransactionManager
  51. }
  52. type GlobalTransactionManager struct {
  53. }
  54. // Begin a new global transaction with given timeout and given name.
  55. func (g *GlobalTransactionManager) Begin(ctx context.Context, gtr *GlobalTransaction, timeout int32, name string) error {
  56. if gtr.Role != transaction.LAUNCHER {
  57. log.Infof("Ignore GlobalStatusBegin(): just involved in global transaction %s", gtr.Xid)
  58. return nil
  59. }
  60. if gtr.Xid != "" {
  61. return errors.New(fmt.Sprintf("Global transaction already exists,can't begin a new global transaction, currentXid = %s ", gtr.Xid))
  62. }
  63. req := message.GlobalBeginRequest{
  64. TransactionName: name,
  65. Timeout: timeout,
  66. }
  67. res, err := getty.GetGettyRemotingClient().SendSyncRequest(req)
  68. if err != nil {
  69. log.Errorf("GlobalBeginRequest error, xid %s, error %v", gtr.Xid, err)
  70. return err
  71. }
  72. if res == nil || res.(message.GlobalBeginResponse).ResultCode == message.ResultCodeFailed {
  73. log.Errorf("GlobalBeginRequest error, xid %s, res %v", gtr.Xid, res)
  74. return err
  75. }
  76. log.Infof("GlobalBeginRequest success, xid %s, res %v", gtr.Xid, res)
  77. gtr.Status = transaction.GlobalStatusBegin
  78. gtr.Xid = res.(message.GlobalBeginResponse).Xid
  79. seatactx.SetXID(ctx, res.(message.GlobalBeginResponse).Xid)
  80. return nil
  81. }
  82. // Commit the global transaction.
  83. func (g *GlobalTransactionManager) Commit(ctx context.Context, gtr *GlobalTransaction) error {
  84. if gtr.Role != transaction.LAUNCHER {
  85. log.Infof("Ignore Commit(): just involved in global gtr [{}]", gtr.Xid)
  86. return nil
  87. }
  88. if gtr.Xid == "" {
  89. return errors.New("Commit xid should not be empty")
  90. }
  91. // todo: replace retry with config
  92. var (
  93. err error
  94. res interface{}
  95. )
  96. for retry := 5; retry > 0; retry-- {
  97. req := message.GlobalCommitRequest{
  98. AbstractGlobalEndRequest: message.AbstractGlobalEndRequest{
  99. Xid: gtr.Xid,
  100. },
  101. }
  102. res, err = getty.GetGettyRemotingClient().SendSyncRequest(req)
  103. if err != nil {
  104. log.Errorf("GlobalCommitRequest error, xid %s, error %v", gtr.Xid, err)
  105. } else {
  106. break
  107. }
  108. }
  109. if err == nil && res != nil {
  110. gtr.Status = res.(message.GlobalCommitResponse).GlobalStatus
  111. }
  112. seatactx.UnbindXid(ctx)
  113. log.Infof("GlobalCommitRequest commit success, xid %s", gtr.Xid)
  114. return err
  115. }
  116. // Rollback the global transaction.
  117. func (g *GlobalTransactionManager) Rollback(ctx context.Context, gtr *GlobalTransaction) error {
  118. if gtr.Role != transaction.LAUNCHER {
  119. log.Infof("Ignore Commit(): just involved in global gtr [{}]", gtr.Xid)
  120. return nil
  121. }
  122. if gtr.Xid == "" {
  123. return errors.New("Commit xid should not be empty")
  124. }
  125. // todo: replace retry with config
  126. var (
  127. err error
  128. res interface{}
  129. )
  130. for retry := 5; retry > 0; retry-- {
  131. req := message.GlobalRollbackRequest{
  132. AbstractGlobalEndRequest: message.AbstractGlobalEndRequest{
  133. Xid: gtr.Xid,
  134. },
  135. }
  136. res, err = getty.GetGettyRemotingClient().SendSyncRequest(req)
  137. if err != nil {
  138. log.Errorf("GlobalRollbackRequest error, xid %s, error %v", gtr.Xid, err)
  139. } else {
  140. break
  141. }
  142. }
  143. if err == nil && res != nil {
  144. gtr.Status = res.(message.GlobalRollbackResponse).GlobalStatus
  145. }
  146. seatactx.UnbindXid(ctx)
  147. return err
  148. }
  149. // Suspend the global transaction.
  150. func (g *GlobalTransactionManager) Suspend() (api.SuspendedResourcesHolder, error) {
  151. panic("implement me")
  152. }
  153. // Resume the global transaction.
  154. func (g *GlobalTransactionManager) Resume(suspendedResourcesHolder api.SuspendedResourcesHolder) error {
  155. panic("implement me")
  156. }
  157. // report the global transaction status.
  158. func (g *GlobalTransactionManager) GlobalReport(globalStatus transaction.GlobalStatus) error {
  159. panic("implement me")
  160. }

Go Implementation For Seata