github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/ha/ops.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 ha
    15  
    16  import (
    17  	"github.com/pingcap/tiflow/dm/config"
    18  	"github.com/pingcap/tiflow/dm/pkg/etcdutil"
    19  	"go.etcd.io/etcd/api/v3/mvccpb"
    20  	clientv3 "go.etcd.io/etcd/client/v3"
    21  )
    22  
    23  // PutRelayStageSourceBound puts the following data in one txn.
    24  // - relay stage.
    25  // - source bound relationship.
    26  func PutRelayStageSourceBound(cli *clientv3.Client, stage Stage, bound SourceBound) (int64, error) {
    27  	ops1, err := putRelayStageOp(stage)
    28  	if err != nil {
    29  		return 0, err
    30  	}
    31  	op2, err := putSourceBoundOp(bound)
    32  	if err != nil {
    33  		return 0, err
    34  	}
    35  	ops := make([]clientv3.Op, 0, len(ops1)+len(op2))
    36  	ops = append(ops, ops1...)
    37  	ops = append(ops, op2...)
    38  	_, rev, err := etcdutil.DoTxnWithRepeatable(cli, etcdutil.ThenOpFunc(ops...))
    39  	return rev, err
    40  }
    41  
    42  // PutRelayStageRelayConfigSourceBound puts the following data in one txn.
    43  // - relay stage.
    44  // - relay config for a worker
    45  // - source bound relationship.
    46  func PutRelayStageRelayConfigSourceBound(cli *clientv3.Client, stage Stage, bound SourceBound) (int64, error) {
    47  	ops1, err := putRelayStageOp(stage)
    48  	if err != nil {
    49  		return 0, err
    50  	}
    51  	op2, err := putSourceBoundOp(bound)
    52  	if err != nil {
    53  		return 0, err
    54  	}
    55  	op3 := putRelayConfigOp(bound.Worker, bound.Source)
    56  	ops := make([]clientv3.Op, 0, len(ops1)+len(op2)+1)
    57  	ops = append(ops, ops1...)
    58  	ops = append(ops, op2...)
    59  	ops = append(ops, op3)
    60  	_, rev, err := etcdutil.DoTxnWithRepeatable(cli, etcdutil.ThenOpFunc(ops...))
    61  	return rev, err
    62  }
    63  
    64  // DeleteSourceCfgRelayStageSourceBound deletes the following data in one txn.
    65  // - upstream source config.
    66  // - relay stage.
    67  // - source bound relationship.
    68  func DeleteSourceCfgRelayStageSourceBound(cli *clientv3.Client, source, worker string) (int64, error) {
    69  	sourceCfgOp := deleteSourceCfgOp(source)
    70  	relayStageOp := deleteRelayStageOp(source)
    71  	sourceBoundOp := deleteSourceBoundOp(worker)
    72  	lastBoundOp := deleteLastSourceBoundOp(worker)
    73  	ops := make([]clientv3.Op, 0, 3+len(sourceBoundOp))
    74  	ops = append(ops, sourceCfgOp)
    75  	ops = append(ops, relayStageOp)
    76  	ops = append(ops, sourceBoundOp...)
    77  	ops = append(ops, lastBoundOp)
    78  
    79  	_, rev, err := etcdutil.DoTxnWithRepeatable(cli, etcdutil.ThenOpFunc(ops...))
    80  	return rev, err
    81  }
    82  
    83  // PutSubTaskCfgStage puts the following data in one txn.
    84  // - subtask config.
    85  // - subtask stage.
    86  // NOTE: golang can't use two `...` in the func, so use `[]` instead.
    87  func PutSubTaskCfgStage(cli *clientv3.Client, cfgs []config.SubTaskConfig, stages []Stage, validatorStages []Stage) (int64, error) {
    88  	return operateSubtask(cli, mvccpb.PUT, cfgs, stages, validatorStages)
    89  }
    90  
    91  // DeleteSubTaskCfgStage deletes the following data in one txn.
    92  // - subtask config.
    93  // - subtask stage.
    94  // NOTE: golang can't use two `...` in the func, so use `[]` instead.
    95  func DeleteSubTaskCfgStage(cli *clientv3.Client, cfgs []config.SubTaskConfig, stages []Stage, validatorStages []Stage) (int64, error) {
    96  	return operateSubtask(cli, mvccpb.DELETE, cfgs, stages, validatorStages)
    97  }
    98  
    99  // operateSubtask puts/deletes KVs for the subtask in one txn.
   100  func operateSubtask(cli *clientv3.Client, evType mvccpb.Event_EventType, cfgs []config.SubTaskConfig, stages []Stage,
   101  	validatorStages []Stage,
   102  ) (int64, error) {
   103  	var (
   104  		ops1         []clientv3.Op
   105  		ops2         []clientv3.Op
   106  		validatorOps []clientv3.Op
   107  		err          error
   108  	)
   109  	switch evType {
   110  	case mvccpb.PUT:
   111  		ops1, err = putSubTaskCfgOp(cfgs...)
   112  		if err != nil {
   113  			return 0, err
   114  		}
   115  		ops2, err = putSubTaskStageOp(stages...)
   116  		if err != nil {
   117  			return 0, err
   118  		}
   119  		validatorOps, err = putValidatorStageOps(validatorStages...)
   120  		if err != nil {
   121  			return 0, err
   122  		}
   123  	case mvccpb.DELETE:
   124  		ops1 = deleteSubTaskCfgOp(cfgs...)
   125  		ops2 = deleteSubTaskStageOp(stages...)
   126  		validatorOps = deleteValidatorStageOps(validatorStages...)
   127  	}
   128  
   129  	ops := make([]clientv3.Op, 0, 2*len(cfgs)+len(stages))
   130  	ops = append(ops, ops1...)
   131  	ops = append(ops, ops2...)
   132  	ops = append(ops, validatorOps...)
   133  	_, rev, err := etcdutil.DoTxnWithRepeatable(cli, etcdutil.ThenOpFunc(ops...))
   134  	return rev, err
   135  }