github.com/orderbynull/buffalo@v0.11.1/worker/simple.go (about) 1 package worker 2 3 import ( 4 "context" 5 "sync" 6 "time" 7 8 "github.com/pkg/errors" 9 "github.com/sirupsen/logrus" 10 ) 11 12 var _ Worker = &Simple{} 13 14 // NewSimple creates a basic implementation of the Worker interface 15 // that is backed using just the standard library and goroutines. 16 func NewSimple() *Simple { 17 return NewSimpleWithContext(context.Background()) 18 } 19 20 // NewSimpleWithContext creates a basic implementation of the Worker interface 21 // that is backed using just the standard library and goroutines. 22 func NewSimpleWithContext(ctx context.Context) *Simple { 23 ctx, cancel := context.WithCancel(ctx) 24 25 l := logrus.New() 26 l.Level = logrus.InfoLevel 27 l.Formatter = &logrus.TextFormatter{} 28 29 return &Simple{ 30 Logger: l, 31 ctx: ctx, 32 cancel: cancel, 33 handlers: map[string]Handler{}, 34 moot: &sync.Mutex{}, 35 } 36 } 37 38 // Simple is a basic implementation of the Worker interface 39 // that is backed using just the standard library and goroutines. 40 type Simple struct { 41 Logger SimpleLogger 42 ctx context.Context 43 cancel context.CancelFunc 44 handlers map[string]Handler 45 moot *sync.Mutex 46 } 47 48 // Register Handler with the worker 49 func (w *Simple) Register(name string, h Handler) error { 50 w.moot.Lock() 51 defer w.moot.Unlock() 52 if _, ok := w.handlers[name]; ok { 53 return errors.Errorf("handler already mapped for name %s", name) 54 } 55 w.handlers[name] = h 56 return nil 57 } 58 59 // Start the worker 60 func (w *Simple) Start(ctx context.Context) error { 61 w.Logger.Info("Starting Simple Background Worker") 62 w.ctx, w.cancel = context.WithCancel(ctx) 63 return nil 64 } 65 66 // Stop the worker 67 func (w Simple) Stop() error { 68 w.Logger.Info("Stopping Simple Background Worker") 69 w.cancel() 70 return nil 71 } 72 73 // Perform a job as soon as possibly using a goroutine. 74 func (w Simple) Perform(job Job) error { 75 w.Logger.Debugf("Performing job %s", job) 76 if job.Handler == "" { 77 err := errors.Errorf("no handler name given for %s", job) 78 w.Logger.Error(err) 79 return err 80 } 81 w.moot.Lock() 82 defer w.moot.Unlock() 83 if h, ok := w.handlers[job.Handler]; ok { 84 go func() { 85 err := h(job.Args) 86 if err != nil { 87 w.Logger.Error(err) 88 } 89 w.Logger.Debugf("Completed job %s", job) 90 }() 91 return nil 92 } 93 err := errors.Errorf("no handler mapped for name %s", job.Handler) 94 w.Logger.Error(err) 95 return err 96 } 97 98 // PerformAt performs a job at a particular time using a goroutine. 99 func (w Simple) PerformAt(job Job, t time.Time) error { 100 return w.PerformIn(job, time.Until(t)) 101 } 102 103 // PerformIn performs a job after waiting for a specified amount 104 // using a goroutine. 105 func (w Simple) PerformIn(job Job, d time.Duration) error { 106 go func() { 107 select { 108 case <-time.After(d): 109 w.Perform(job) 110 case <-w.ctx.Done(): 111 w.cancel() 112 } 113 }() 114 return nil 115 } 116 117 // SimpleLogger is used by the Simple worker to write logs 118 type SimpleLogger interface { 119 Debugf(string, ...interface{}) 120 Infof(string, ...interface{}) 121 Errorf(string, ...interface{}) 122 Debug(...interface{}) 123 Info(...interface{}) 124 Error(...interface{}) 125 }