github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/cdc/sink/dmlsink/cloudstorage/encoding_worker.go (about)

     1  // Copyright 2022 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  package cloudstorage
    14  
    15  import (
    16  	"context"
    17  	"sync/atomic"
    18  
    19  	"github.com/pingcap/errors"
    20  	"github.com/pingcap/log"
    21  	"github.com/pingcap/tiflow/cdc/model"
    22  	"github.com/pingcap/tiflow/pkg/sink/codec"
    23  	"go.uber.org/zap"
    24  	"golang.org/x/sync/errgroup"
    25  )
    26  
    27  // encodingWorker denotes the worker responsible for encoding RowChangedEvents
    28  // to messages formatted in the specific protocol.
    29  type encodingWorker struct {
    30  	id           int
    31  	changeFeedID model.ChangeFeedID
    32  	encoder      codec.TxnEventEncoder
    33  	isClosed     uint64
    34  	inputCh      <-chan eventFragment
    35  	outputCh     chan<- eventFragment
    36  }
    37  
    38  func newEncodingWorker(
    39  	workerID int,
    40  	changefeedID model.ChangeFeedID,
    41  	encoder codec.TxnEventEncoder,
    42  	inputCh <-chan eventFragment,
    43  	outputCh chan<- eventFragment,
    44  ) *encodingWorker {
    45  	return &encodingWorker{
    46  		id:           workerID,
    47  		changeFeedID: changefeedID,
    48  		encoder:      encoder,
    49  		inputCh:      inputCh,
    50  		outputCh:     outputCh,
    51  	}
    52  }
    53  
    54  func (w *encodingWorker) run(ctx context.Context) error {
    55  	log.Debug("encoding worker started", zap.Int("workerID", w.id),
    56  		zap.String("namespace", w.changeFeedID.Namespace),
    57  		zap.String("changefeed", w.changeFeedID.ID))
    58  
    59  	eg, ctx := errgroup.WithContext(ctx)
    60  	eg.Go(func() error {
    61  		for {
    62  			select {
    63  			case <-ctx.Done():
    64  				return errors.Trace(ctx.Err())
    65  			case frag, ok := <-w.inputCh:
    66  				if !ok || atomic.LoadUint64(&w.isClosed) == 1 {
    67  					return nil
    68  				}
    69  				err := w.encodeEvents(frag)
    70  				if err != nil {
    71  					return errors.Trace(err)
    72  				}
    73  			}
    74  		}
    75  	})
    76  
    77  	return eg.Wait()
    78  }
    79  
    80  func (w *encodingWorker) encodeEvents(frag eventFragment) error {
    81  	err := w.encoder.AppendTxnEvent(frag.event.Event, frag.event.Callback)
    82  	if err != nil {
    83  		return errors.Trace(err)
    84  	}
    85  	msgs := w.encoder.Build()
    86  	frag.encodedMsgs = msgs
    87  	w.outputCh <- frag
    88  
    89  	return nil
    90  }
    91  
    92  func (w *encodingWorker) close() {
    93  	if !atomic.CompareAndSwapUint64(&w.isClosed, 0, 1) {
    94  		return
    95  	}
    96  }