github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/pkg/pipeline/runner.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 pipeline
    15  
    16  import (
    17  	stdContext "context"
    18  
    19  	"github.com/pingcap/errors"
    20  	"github.com/pingcap/log"
    21  	"github.com/pingcap/ticdc/pkg/context"
    22  	"go.uber.org/zap"
    23  )
    24  
    25  type runner interface {
    26  	run(ctx context.Context) error
    27  	getOutputCh() chan Message
    28  	getNode() Node
    29  	getName() string
    30  }
    31  
    32  type nodeRunner struct {
    33  	name     string
    34  	node     Node
    35  	previous runner
    36  	outputCh chan Message
    37  }
    38  
    39  func newNodeRunner(name string, node Node, previous runner, outputChanSize int) *nodeRunner {
    40  	return &nodeRunner{
    41  		name:     name,
    42  		node:     node,
    43  		previous: previous,
    44  		outputCh: make(chan Message, outputChanSize),
    45  	}
    46  }
    47  
    48  func (r *nodeRunner) run(ctx context.Context) error {
    49  	nodeCtx := newNodeContext(ctx, Message{}, r.outputCh)
    50  	defer close(r.outputCh)
    51  	defer func() {
    52  		err := r.node.Destroy(nodeCtx)
    53  		if err != nil && errors.Cause(err) != stdContext.Canceled {
    54  			log.Error("found an error when stopping node", zap.String("node name", r.name), zap.Error(err))
    55  		}
    56  	}()
    57  	err := r.node.Init(nodeCtx)
    58  	if err != nil {
    59  		return err
    60  	}
    61  	// TODO: We can add monitoring for execution time and channel length here uniformly
    62  	for msg := range r.previous.getOutputCh() {
    63  		err := r.node.Receive(withMessage(nodeCtx, msg))
    64  		if err != nil {
    65  			return err
    66  		}
    67  	}
    68  	return nil
    69  }
    70  
    71  func (r *nodeRunner) getOutputCh() chan Message {
    72  	return r.outputCh
    73  }
    74  
    75  func (r *nodeRunner) getNode() Node {
    76  	return r.node
    77  }
    78  
    79  func (r *nodeRunner) getName() string {
    80  	return r.name
    81  }
    82  
    83  type headRunner chan Message
    84  
    85  func (h headRunner) getName() string {
    86  	return "header"
    87  }
    88  
    89  func (h headRunner) run(ctx context.Context) error {
    90  	panic("unreachable")
    91  }
    92  
    93  func (h headRunner) getOutputCh() chan Message {
    94  	return h
    95  }
    96  
    97  func (h headRunner) getNode() Node {
    98  	panic("unreachable")
    99  }
   100  
   101  func blackhole(runner runner) {
   102  	for range runner.getOutputCh() {
   103  		// ignore all messages in the outputCh of the runner
   104  	}
   105  }