github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/framework/registry/factory.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 14 package registry 15 16 import ( 17 "encoding/json" 18 "reflect" 19 "strings" 20 21 "github.com/pingcap/log" 22 "github.com/pingcap/tiflow/engine/framework" 23 frameModel "github.com/pingcap/tiflow/engine/framework/model" 24 dcontext "github.com/pingcap/tiflow/engine/pkg/context" 25 "github.com/pingcap/tiflow/pkg/errors" 26 ) 27 28 // WorkerFactory is an interface that should be implemented by the author of 29 // WorkerImpl or JobMasterImpl (JobMaster is the worker of JobManager). 30 // It represents a constructor for a given type of worker. 31 type WorkerFactory interface { 32 // NewWorkerImpl return an implementation of the worker. its BaseWorker 33 // or BaseJobMaster field can be left nil, framework will fill it in. 34 NewWorkerImpl( 35 ctx *dcontext.Context, // We require a `dcontext` here to provide dependencies. 36 workerID frameModel.WorkerID, // the globally unique workerID for this worker to be created. 37 masterID frameModel.MasterID, // the masterID that this worker will report to. 38 config WorkerConfig, // the config used to initialize the worker. 39 ) (framework.WorkerImpl, error) 40 DeserializeConfig(configBytes []byte) (WorkerConfig, error) 41 // IsRetryableError passes in an error to business logic, and returns whether 42 // job should be re-created or terminated permanently when meeting this error. 43 IsRetryableError(err error) bool 44 } 45 46 // WorkerConstructor alias to the function that can construct a WorkerImpl 47 type WorkerConstructor[T framework.WorkerImpl, C any] func( 48 ctx *dcontext.Context, id frameModel.WorkerID, masterID frameModel.MasterID, config C, 49 ) T 50 51 // SimpleWorkerFactory is a WorkerFactory with built-in JSON codec for WorkerConfig. 52 type SimpleWorkerFactory[T framework.WorkerImpl, C any] struct { 53 constructor WorkerConstructor[T, C] 54 } 55 56 // NewSimpleWorkerFactory creates a new WorkerFactory. 57 func NewSimpleWorkerFactory[T framework.WorkerImpl, Config any]( 58 constructor WorkerConstructor[T, Config], 59 ) *SimpleWorkerFactory[T, Config] { 60 // Config must be a pointer 61 if !isPtr[Config]() { 62 // It's okay to panic here. 63 // The developer who used this function mistakenly should 64 // be able to figure out what happened. 65 log.Panic("expect worker's config type to be a pointer") 66 } 67 return &SimpleWorkerFactory[T, Config]{ 68 constructor: constructor, 69 } 70 } 71 72 // NewWorkerImpl implements WorkerFactory.NewWorkerImpl 73 func (f *SimpleWorkerFactory[T, C]) NewWorkerImpl( 74 ctx *dcontext.Context, 75 workerID frameModel.WorkerID, 76 masterID frameModel.MasterID, 77 config WorkerConfig, 78 ) (framework.WorkerImpl, error) { 79 return f.constructor(ctx, workerID, masterID, config.(C)), nil 80 } 81 82 // DeserializeConfig implements WorkerFactory.DeserializeConfig 83 func (f *SimpleWorkerFactory[T, C]) DeserializeConfig(configBytes []byte) (WorkerConfig, error) { 84 var config C 85 config = reflect.New(reflect.TypeOf(config).Elem()).Interface().(C) 86 if err := json.Unmarshal(configBytes, config); err != nil { 87 return nil, errors.ErrDeserializeConfig.Wrap(err).GenWithStackByArgs() 88 } 89 return config, nil 90 } 91 92 // IsRetryableError implements WorkerFactory.IsRetryableError 93 func (f *SimpleWorkerFactory[T, C]) IsRetryableError(err error) bool { 94 if errors.Is(err, errors.ErrDeserializeConfig) { 95 return false 96 } 97 if strings.Contains(err.Error(), string(errors.ErrDeserializeConfig.RFCCode())) { 98 return false 99 } 100 return true 101 }