github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/ctl/master/handle_error.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package master 15 16 import ( 17 "context" 18 "errors" 19 "os" 20 21 "github.com/pingcap/tiflow/dm/ctl/common" 22 "github.com/pingcap/tiflow/dm/pb" 23 "github.com/pingcap/tiflow/dm/pkg/binlog" 24 "github.com/spf13/cobra" 25 ) 26 27 // NewHandleErrorCmd creates a HandleError command. 28 // deprecated, replaced by binlog command. 29 func NewHandleErrorCmd() *cobra.Command { 30 cmd := &cobra.Command{ 31 Use: "handle-error <task-name | task-file> [-s source ...] [-b binlog-pos] <skip/replace/revert> [replace-sql1;replace-sql2;]", 32 Short: "`skip`/`replace`/`revert` the current error event or a specific binlog position (binlog-pos) event", 33 Hidden: true, 34 RunE: handleErrorFunc, 35 } 36 cmd.Flags().StringP("binlog-pos", "b", "", "position used to match binlog event if matched the handler-error operation will be applied. The format like \"mysql-bin|000001.000003:3270\"") 37 return cmd 38 } 39 40 func convertOp(t string) pb.ErrorOp { 41 switch t { 42 case "skip": 43 return pb.ErrorOp_Skip 44 case "replace": 45 return pb.ErrorOp_Replace 46 case "revert": 47 return pb.ErrorOp_Revert 48 default: 49 return pb.ErrorOp_InvalidErrorOp 50 } 51 } 52 53 // handleErrorFunc does handle error request. 54 func handleErrorFunc(cmd *cobra.Command, _ []string) error { 55 if len(cmd.Flags().Args()) < 2 { 56 cmd.SetOut(os.Stdout) 57 common.PrintCmdUsage(cmd) 58 return errors.New("please check output to see error") 59 } 60 61 taskName := common.GetTaskNameFromArgOrFile(cmd.Flags().Arg(0)) 62 operation := cmd.Flags().Arg(1) 63 var sqls []string 64 var err error 65 66 op := convertOp(operation) 67 switch op { 68 case pb.ErrorOp_Skip, pb.ErrorOp_Revert: 69 if len(cmd.Flags().Args()) > 2 { 70 common.PrintLinesf("replace-sqls can not be used for 'skip/revert' operation") 71 return errors.New("please check output to see error") 72 } 73 case pb.ErrorOp_Replace: 74 if len(cmd.Flags().Args()) <= 2 { 75 common.PrintLinesf("must specify the replace-sqls for replace operation") 76 return errors.New("please check output to see error") 77 } 78 79 sqls, err = common.ExtractSQLsFromArgs(cmd.Flags().Args()[2:]) 80 if err != nil { 81 return err 82 } 83 default: 84 common.PrintLinesf("invalid operation '%s', please use `skip`, `replace` or `revert`", operation) 85 return errors.New("please check output to see error") 86 } 87 request := &pb.HandleErrorRequest{ 88 Op: op, 89 Task: taskName, 90 Sqls: sqls, 91 } 92 return sendHandleErrorRequest(cmd, request) 93 } 94 95 func sendHandleErrorRequest(cmd *cobra.Command, request *pb.HandleErrorRequest) error { 96 binlogPos, err := cmd.Flags().GetString("binlog-pos") 97 if err != nil { 98 return err 99 } 100 if len(binlogPos) != 0 { 101 _, err = binlog.VerifyBinlogPos(binlogPos) 102 if err != nil { 103 return err 104 } 105 } 106 107 sources, err := common.GetSourceArgs(cmd) 108 if err != nil { 109 return err 110 } 111 112 ctx, cancel := context.WithCancel(context.Background()) 113 defer cancel() 114 115 request.BinlogPos = binlogPos 116 request.Sources = sources 117 118 resp := &pb.HandleErrorResponse{} 119 err = common.SendRequest( 120 ctx, 121 "HandleError", 122 request, 123 &resp, 124 ) 125 126 if err != nil { 127 return err 128 } 129 130 common.PrettyPrintResponse(resp) 131 return nil 132 }