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.go 5.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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 tm
  18. import (
  19. "context"
  20. "fmt"
  21. "sync"
  22. "github.com/pkg/errors"
  23. "github.com/seata/seata-go/pkg/common/log"
  24. "github.com/seata/seata-go/pkg/protocol/message"
  25. "github.com/seata/seata-go/pkg/remoting/getty"
  26. )
  27. type GlobalTransaction struct {
  28. Xid string
  29. Status message.GlobalStatus
  30. Role GlobalTransactionRole
  31. }
  32. var (
  33. // singletone ResourceManagerFacade
  34. globalTransactionManager *GlobalTransactionManager
  35. onceGlobalTransactionManager = &sync.Once{}
  36. )
  37. func GetGlobalTransactionManager() *GlobalTransactionManager {
  38. if globalTransactionManager == nil {
  39. onceGlobalTransactionManager.Do(func() {
  40. globalTransactionManager = &GlobalTransactionManager{}
  41. })
  42. }
  43. return globalTransactionManager
  44. }
  45. type GlobalTransactionManager struct {
  46. }
  47. // Begin a new global transaction with given timeout and given name.
  48. func (g *GlobalTransactionManager) Begin(ctx context.Context, gtr *GlobalTransaction, timeout int32, name string) error {
  49. if gtr.Role != LAUNCHER {
  50. log.Infof("Ignore GlobalStatusBegin(): just involved in global transaction %s", gtr.Xid)
  51. return nil
  52. }
  53. if gtr.Xid != "" {
  54. return errors.New(fmt.Sprintf("Global transaction already exists,can't begin a new global transaction, currentXid = %s ", gtr.Xid))
  55. }
  56. req := message.GlobalBeginRequest{
  57. TransactionName: name,
  58. Timeout: timeout,
  59. }
  60. res, err := getty.GetGettyRemotingClient().SendSyncRequest(req)
  61. if err != nil {
  62. log.Errorf("GlobalBeginRequest error, xid %s, error %v", gtr.Xid, err)
  63. return err
  64. }
  65. if res == nil || res.(message.GlobalBeginResponse).ResultCode == message.ResultCodeFailed {
  66. log.Errorf("GlobalBeginRequest error, xid %s, res %v", gtr.Xid, res)
  67. return err
  68. }
  69. log.Infof("GlobalBeginRequest success, xid %s, res %v", gtr.Xid, res)
  70. gtr.Status = message.GlobalStatusBegin
  71. gtr.Xid = res.(message.GlobalBeginResponse).Xid
  72. SetXID(ctx, res.(message.GlobalBeginResponse).Xid)
  73. return nil
  74. }
  75. // Commit the global transaction.
  76. func (g *GlobalTransactionManager) Commit(ctx context.Context, gtr *GlobalTransaction) error {
  77. if gtr.Role != LAUNCHER {
  78. log.Infof("Ignore Commit(): just involved in global gtr [{}]", gtr.Xid)
  79. return nil
  80. }
  81. if gtr.Xid == "" {
  82. return errors.New("Commit xid should not be empty")
  83. }
  84. // todo: replace retry with config
  85. var (
  86. err error
  87. res interface{}
  88. )
  89. for retry := 5; retry > 0; retry-- {
  90. req := message.GlobalCommitRequest{
  91. AbstractGlobalEndRequest: message.AbstractGlobalEndRequest{
  92. Xid: gtr.Xid,
  93. },
  94. }
  95. res, err = getty.GetGettyRemotingClient().SendSyncRequest(req)
  96. if err != nil {
  97. log.Errorf("GlobalCommitRequest error, xid %s, error %v", gtr.Xid, err)
  98. } else {
  99. break
  100. }
  101. }
  102. if err == nil {
  103. log.Infof("GlobalCommitRequest commit success, xid %s", gtr.Xid)
  104. gtr.Status = res.(message.GlobalCommitResponse).GlobalStatus
  105. UnbindXid(ctx)
  106. return nil
  107. }
  108. log.Errorf("GlobalCommitRequest commit failed, xid %s, error %v", gtr.Xid, err)
  109. return err
  110. }
  111. // Rollback the global transaction.
  112. func (g *GlobalTransactionManager) Rollback(ctx context.Context, gtr *GlobalTransaction) error {
  113. if gtr.Role != LAUNCHER {
  114. log.Infof("Ignore Commit(): just involved in global gtr [{}]", gtr.Xid)
  115. return nil
  116. }
  117. if gtr.Xid == "" {
  118. return errors.New("Commit xid should not be empty")
  119. }
  120. // todo: replace retry with config
  121. var (
  122. err error
  123. res interface{}
  124. )
  125. for retry := 5; retry > 0; retry-- {
  126. req := message.GlobalRollbackRequest{
  127. AbstractGlobalEndRequest: message.AbstractGlobalEndRequest{
  128. Xid: gtr.Xid,
  129. },
  130. }
  131. res, err = getty.GetGettyRemotingClient().SendSyncRequest(req)
  132. if err != nil {
  133. log.Errorf("GlobalRollbackRequest error, xid %s, error %v", gtr.Xid, err)
  134. } else {
  135. break
  136. }
  137. }
  138. if err == nil {
  139. log.Errorf("GlobalRollbackRequest rollback success, xid %s", gtr.Xid)
  140. gtr.Status = res.(message.GlobalRollbackResponse).GlobalStatus
  141. UnbindXid(ctx)
  142. return nil
  143. }
  144. log.Errorf("GlobalRollbackRequest rollback failed, xid %s, error %v", gtr.Xid, err)
  145. return err
  146. }
  147. // Suspend the global transaction.
  148. func (g *GlobalTransactionManager) Suspend() (SuspendedResourcesHolder, error) {
  149. panic("implement me")
  150. }
  151. // Resume the global transaction.
  152. func (g *GlobalTransactionManager) Resume(suspendedResourcesHolder SuspendedResourcesHolder) error {
  153. panic("implement me")
  154. }
  155. // report the global transaction status.
  156. func (g *GlobalTransactionManager) GlobalReport(globalStatus message.GlobalStatus) error {
  157. panic("implement me")
  158. }