github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/changestream/manifold.go (about) 1 // Copyright 2023 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package changestream 5 6 import ( 7 "github.com/juju/clock" 8 "github.com/juju/errors" 9 "github.com/juju/worker/v3" 10 "github.com/juju/worker/v3/dependency" 11 12 coredatabase "github.com/juju/juju/core/database" 13 "github.com/juju/juju/worker/common" 14 ) 15 16 // Logger represents the logging methods called. 17 type Logger interface { 18 Errorf(message string, args ...interface{}) 19 Warningf(message string, args ...interface{}) 20 Infof(message string, args ...interface{}) 21 Debugf(message string, args ...interface{}) 22 Tracef(message string, args ...interface{}) 23 IsTraceEnabled() bool 24 } 25 26 // EventQueueWorkerFn is an alias function that allows the creation of 27 // EventQueueWorker. 28 type EventQueueWorkerFn = func(coredatabase.TrackedDB, FileNotifier, clock.Clock, Logger) (EventQueueWorker, error) 29 30 // ManifoldConfig defines the names of the manifolds on which a Manifold will 31 // depend. 32 type ManifoldConfig struct { 33 DBAccessor string 34 FileNotifyWatcher string 35 36 Clock clock.Clock 37 Logger Logger 38 NewEventQueueWorker EventQueueWorkerFn 39 } 40 41 func (cfg ManifoldConfig) Validate() error { 42 if cfg.DBAccessor == "" { 43 return errors.NotValidf("empty DBAccessorName") 44 } 45 if cfg.FileNotifyWatcher == "" { 46 return errors.NotValidf("empty FileNotifyWatcherName") 47 } 48 if cfg.Clock == nil { 49 return errors.NotValidf("nil Clock") 50 } 51 if cfg.Logger == nil { 52 return errors.NotValidf("nil Logger") 53 } 54 if cfg.NewEventQueueWorker == nil { 55 return errors.NotValidf("nil NewEventQueueWorker") 56 } 57 return nil 58 } 59 60 // Manifold returns a dependency manifold that runs the changestream 61 // worker, using the resource names defined in the supplied config. 62 func Manifold(config ManifoldConfig) dependency.Manifold { 63 return dependency.Manifold{ 64 Inputs: []string{ 65 config.DBAccessor, 66 config.FileNotifyWatcher, 67 }, 68 Output: changeStreamOutput, 69 Start: func(context dependency.Context) (worker.Worker, error) { 70 if err := config.Validate(); err != nil { 71 return nil, errors.Trace(err) 72 } 73 74 var dbGetter DBGetter 75 if err := context.Get(config.DBAccessor, &dbGetter); err != nil { 76 return nil, errors.Trace(err) 77 } 78 79 var fileNotifyWatcher FileNotifyWatcher 80 if err := context.Get(config.FileNotifyWatcher, &fileNotifyWatcher); err != nil { 81 return nil, errors.Trace(err) 82 } 83 84 cfg := WorkerConfig{ 85 DBGetter: dbGetter, 86 FileNotifyWatcher: fileNotifyWatcher, 87 Clock: config.Clock, 88 Logger: config.Logger, 89 NewEventQueueWorker: config.NewEventQueueWorker, 90 } 91 92 w, err := newWorker(cfg) 93 if err != nil { 94 return nil, errors.Trace(err) 95 } 96 return w, nil 97 }, 98 } 99 } 100 101 func changeStreamOutput(in worker.Worker, out interface{}) error { 102 if w, ok := in.(*common.CleanupWorker); ok { 103 in = w.Worker 104 } 105 w, ok := in.(*changeStreamWorker) 106 if !ok { 107 return errors.Errorf("in should be a *changeStreamWorker; got %T", in) 108 } 109 110 switch out := out.(type) { 111 case *ChangeStream: 112 var target ChangeStream = w 113 *out = target 114 default: 115 return errors.Errorf("out should be a *changestream.ChangeStream; got %T", out) 116 } 117 return nil 118 }