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.

process_router.go 4.7 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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 pcext
  18. import (
  19. "context"
  20. "github.com/pkg/errors"
  21. "github.com/seata/seata-go/pkg/saga/statemachine/constant"
  22. "github.com/seata/seata-go/pkg/saga/statemachine/engine"
  23. "github.com/seata/seata-go/pkg/saga/statemachine/process_ctrl"
  24. "github.com/seata/seata-go/pkg/saga/statemachine/statelang"
  25. )
  26. type StateMachineProcessRouter struct {
  27. stateRouters map[string]process_ctrl.StateRouter
  28. }
  29. func (s *StateMachineProcessRouter) Route(ctx context.Context, processContext process_ctrl.ProcessContext) (process_ctrl.Instruction, error) {
  30. stateInstruction, ok := processContext.GetInstruction().(StateInstruction)
  31. if !ok {
  32. return nil, errors.New("instruction is not a state instruction")
  33. }
  34. var state statelang.State
  35. if stateInstruction.TemporaryState() != nil {
  36. state = stateInstruction.TemporaryState()
  37. stateInstruction.SetTemporaryState(nil)
  38. } else {
  39. stateMachineConfig, ok := processContext.GetVariable(constant.VarNameStateMachineConfig).(engine.StateMachineConfig)
  40. if !ok {
  41. return nil, errors.New("state machine config not found")
  42. }
  43. stateMachine, err := stateMachineConfig.StateMachineRepository().GetStateMachineByNameAndTenantId(stateInstruction.StateMachineName(),
  44. stateInstruction.TenantId())
  45. if err != nil {
  46. return nil, err
  47. }
  48. state = stateMachine.States()[stateInstruction.StateName()]
  49. }
  50. stateType := state.Type()
  51. router := s.stateRouters[stateType]
  52. var interceptors []process_ctrl.StateRouterInterceptor
  53. if interceptAbleStateRouter, ok := router.(process_ctrl.InterceptAbleStateRouter); ok {
  54. interceptors = interceptAbleStateRouter.StateRouterInterceptor()
  55. }
  56. var executedInterceptors []process_ctrl.StateRouterInterceptor
  57. var exception error
  58. instruction, exception := func() (process_ctrl.Instruction, error) {
  59. if interceptors == nil || len(executedInterceptors) == 0 {
  60. executedInterceptors = make([]process_ctrl.StateRouterInterceptor, 0, len(interceptors))
  61. for _, interceptor := range interceptors {
  62. executedInterceptors = append(executedInterceptors, interceptor)
  63. err := interceptor.PreRoute(ctx, processContext, state)
  64. if err != nil {
  65. return nil, err
  66. }
  67. }
  68. }
  69. instruction, err := router.Route(ctx, processContext, state)
  70. if err != nil {
  71. return nil, err
  72. }
  73. return instruction, nil
  74. }()
  75. if interceptors == nil || len(executedInterceptors) == 0 {
  76. for i := len(executedInterceptors) - 1; i >= 0; i-- {
  77. err := executedInterceptors[i].PostRoute(ctx, processContext, instruction, exception)
  78. if err != nil {
  79. return nil, err
  80. }
  81. }
  82. // if 'Succeed' or 'Fail' State did not configured, we must end the state machine
  83. if instruction == nil && !stateInstruction.End() {
  84. err := EndStateMachine(ctx, processContext)
  85. if err != nil {
  86. return nil, err
  87. }
  88. }
  89. }
  90. return instruction, nil
  91. }
  92. func (s *StateMachineProcessRouter) InitDefaultStateRouters() {
  93. if s.stateRouters == nil || len(s.stateRouters) == 0 {
  94. s.stateRouters = make(map[string]process_ctrl.StateRouter)
  95. taskStateRouter := &TaskStateRouter{}
  96. s.stateRouters[constant.StateTypeServiceTask] = taskStateRouter
  97. s.stateRouters[constant.StateTypeScriptTask] = taskStateRouter
  98. s.stateRouters[constant.StateTypeChoice] = taskStateRouter
  99. s.stateRouters[constant.StateTypeCompensationTrigger] = taskStateRouter
  100. s.stateRouters[constant.StateTypeSubStateMachine] = taskStateRouter
  101. s.stateRouters[constant.StateTypeCompensateSubMachine] = taskStateRouter
  102. s.stateRouters[constant.StateTypeLoopStart] = taskStateRouter
  103. endStateRouter := &EndStateRouter{}
  104. s.stateRouters[constant.StateTypeSucceed] = endStateRouter
  105. s.stateRouters[constant.StateTypeFail] = endStateRouter
  106. }
  107. }
  108. func (s *StateMachineProcessRouter) StateRouters() map[string]process_ctrl.StateRouter {
  109. return s.stateRouters
  110. }
  111. func (s *StateMachineProcessRouter) SetStateRouters(stateRouters map[string]process_ctrl.StateRouter) {
  112. s.stateRouters = stateRouters
  113. }