| @@ -20,36 +20,48 @@ import ( | |||
| ) | |||
| var ( | |||
| TCC_ACTION_NAME = "TccActionName" | |||
| TRY_METHOD = "Try" | |||
| CONFIRM_METHOD = "Confirm" | |||
| CANCEL_METHOD = "Cancel" | |||
| ACTION_START_TIME = "action-start-time" | |||
| ACTION_NAME = "actionName" | |||
| PREPARE_METHOD = "sys::prepare" | |||
| COMMIT_METHOD = "sys::commit" | |||
| ROLLBACK_METHOD = "sys::rollback" | |||
| HOST_NAME = "host-name" | |||
| TCC_METHOD_ARGUMENTS = "arguments" | |||
| TCC_METHOD_RESULT = "result" | |||
| // TCCActionName | |||
| TCCActionName = "TCCActionName" | |||
| // TryMethod | |||
| TryMethod = "Try" | |||
| // ConfirmMethod | |||
| ConfirmMethod = "Confirm" | |||
| // CancelMethod | |||
| CancelMethod = "Cancel" | |||
| // ActionStartTime | |||
| ActionStartTime = "action-start-time" | |||
| // ActionName | |||
| ActionName = "actionName" | |||
| // PrepareMethod | |||
| PrepareMethod = "sys::prepare" | |||
| // CommitMethod | |||
| CommitMethod = "sys::commit" | |||
| // RollbackMethod | |||
| RollbackMethod = "sys::rollback" | |||
| // HostName | |||
| HostName = "host-name" | |||
| // TCCMethodArguments | |||
| TCCMethodArguments = "arguments" | |||
| // TCCMethodResult | |||
| TCCMethodResult = "result" | |||
| businessActionContextType = reflect.TypeOf(&context.BusinessActionContext{}) | |||
| ) | |||
| type TccService interface { | |||
| type TCCService interface { | |||
| Try(ctx *context.BusinessActionContext) (bool, error) | |||
| Confirm(ctx *context.BusinessActionContext) bool | |||
| Cancel(ctx *context.BusinessActionContext) bool | |||
| } | |||
| type TccProxyService interface { | |||
| GetTccService() TccService | |||
| type TCCProxyService interface { | |||
| GetTCCService() TCCService | |||
| } | |||
| func ImplementTCC(v TccProxyService) { | |||
| func ImplementTCC(v TCCProxyService) { | |||
| valueOf := reflect.ValueOf(v) | |||
| log.Debugf("[Implement] reflect.TypeOf: %s", valueOf.String()) | |||
| @@ -61,7 +73,7 @@ func ImplementTCC(v TccProxyService) { | |||
| log.Errorf("%s must be a struct ptr", valueOf.String()) | |||
| return | |||
| } | |||
| proxyService := v.GetTccService() | |||
| proxyService := v.GetTCCService() | |||
| makeCallProxy := func(methodDesc *proxy.MethodDescriptor, resource *TCCResource) func(in []reflect.Value) []reflect.Value { | |||
| return func(in []reflect.Value) []reflect.Value { | |||
| businessContextValue := in[0] | |||
| @@ -85,28 +97,28 @@ func ImplementTCC(v TccProxyService) { | |||
| t := typeOf.Field(i) | |||
| methodName := t.Name | |||
| f := valueOfElem.Field(i) | |||
| if f.Kind() == reflect.Func && f.IsValid() && f.CanSet() && methodName == TRY_METHOD { | |||
| if f.Kind() == reflect.Func && f.IsValid() && f.CanSet() && methodName == TryMethod { | |||
| if t.Type.NumIn() != 1 && t.Type.In(0) != businessActionContextType { | |||
| panic("prepare method argument is not BusinessActionContext") | |||
| } | |||
| actionName := t.Tag.Get(TCC_ACTION_NAME) | |||
| actionName := t.Tag.Get(TCCActionName) | |||
| if actionName == "" { | |||
| panic("must tag TccActionName") | |||
| panic("must tag TCCActionName") | |||
| } | |||
| commitMethodDesc := proxy.Register(proxyService, CONFIRM_METHOD) | |||
| cancelMethodDesc := proxy.Register(proxyService, CANCEL_METHOD) | |||
| commitMethodDesc := proxy.Register(proxyService, ConfirmMethod) | |||
| cancelMethodDesc := proxy.Register(proxyService, CancelMethod) | |||
| tryMethodDesc := proxy.Register(proxyService, methodName) | |||
| tccResource := &TCCResource{ | |||
| ResourceGroupID: "", | |||
| AppName: "", | |||
| ActionName: actionName, | |||
| PrepareMethodName: TRY_METHOD, | |||
| CommitMethodName: COMMIT_METHOD, | |||
| PrepareMethodName: TryMethod, | |||
| CommitMethodName: CommitMethod, | |||
| CommitMethod: commitMethodDesc, | |||
| RollbackMethodName: CANCEL_METHOD, | |||
| RollbackMethodName: CancelMethod, | |||
| RollbackMethod: cancelMethodDesc, | |||
| } | |||
| @@ -124,27 +136,34 @@ func proceed(methodDesc *proxy.MethodDescriptor, ctx *context.BusinessActionCont | |||
| args = make([]interface{}, 0) | |||
| ) | |||
| branchID, err := doTccActionLogStore(ctx, resource) | |||
| branchID, err := doTCCActionLogStore(ctx, resource) | |||
| if err != nil { | |||
| return nil, errors.WithStack(err) | |||
| } | |||
| ctx.BranchID = branchID | |||
| ctx.BranchID = strconv.FormatInt(branchID, 10) | |||
| args = append(args, ctx) | |||
| returnValues := proxy.Invoke(methodDesc, nil, args) | |||
| errValue := returnValues[len(returnValues)-1] | |||
| if errValue.IsValid() && !errValue.IsNil() { | |||
| err := tccResourceManager.BranchReport(meta.BranchTypeTCC, ctx.XID, branchID, meta.BranchStatusPhaseOneFailed, nil) | |||
| if err != nil { | |||
| log.Errorf("branch report err: %v", err) | |||
| } | |||
| } | |||
| return returnValues, nil | |||
| } | |||
| func doTccActionLogStore(ctx *context.BusinessActionContext, resource *TCCResource) (string, error) { | |||
| ctx.ActionContext[ACTION_START_TIME] = time.CurrentTimeMillis() | |||
| ctx.ActionContext[PREPARE_METHOD] = resource.PrepareMethodName | |||
| ctx.ActionContext[COMMIT_METHOD] = resource.CommitMethodName | |||
| ctx.ActionContext[ROLLBACK_METHOD] = resource.RollbackMethodName | |||
| ctx.ActionContext[ACTION_NAME] = ctx.ActionName | |||
| func doTCCActionLogStore(ctx *context.BusinessActionContext, resource *TCCResource) (int64, error) { | |||
| ctx.ActionContext[ActionStartTime] = time.CurrentTimeMillis() | |||
| ctx.ActionContext[PrepareMethod] = resource.PrepareMethodName | |||
| ctx.ActionContext[CommitMethod] = resource.CommitMethodName | |||
| ctx.ActionContext[RollbackMethod] = resource.RollbackMethodName | |||
| ctx.ActionContext[ActionName] = ctx.ActionName | |||
| ip, err := gxnet.GetLocalIP() | |||
| if err == nil { | |||
| ctx.ActionContext[HOST_NAME] = ip | |||
| ctx.ActionContext[HostName] = ip | |||
| } else { | |||
| log.Warn("getLocalIP error") | |||
| } | |||
| @@ -155,13 +174,13 @@ func doTccActionLogStore(ctx *context.BusinessActionContext, resource *TCCResour | |||
| applicationData, err := json.Marshal(applicationContext) | |||
| if err != nil { | |||
| log.Errorf("marshal applicationContext failed:%v", applicationContext) | |||
| return "", err | |||
| return 0, err | |||
| } | |||
| branchID, err := tccResourceManager.BranchRegister(meta.BranchTypeTCC, ctx.ActionName, "", ctx.XID, applicationData, "") | |||
| if err != nil { | |||
| log.Errorf("TCC branch Register error, xid: %s", ctx.XID) | |||
| return "", errors.WithStack(err) | |||
| return 0, errors.WithStack(err) | |||
| } | |||
| return strconv.FormatInt(branchID, 10), nil | |||
| return branchID, nil | |||
| } | |||