github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/protocols/blockrecords/brprocessor/processor.go (about) 1 package brprocessor 2 3 import ( 4 "errors" 5 "sync" 6 7 "github.com/unicornultrafoundation/go-helios/native/dag" 8 "github.com/unicornultrafoundation/go-helios/native/idx" 9 "github.com/unicornultrafoundation/go-helios/utils/datasemaphore" 10 "github.com/unicornultrafoundation/go-helios/utils/workers" 11 12 "github.com/unicornultrafoundation/go-u2u/native/ibr" 13 ) 14 15 var ( 16 ErrBusy = errors.New("failed to acquire events semaphore") 17 ) 18 19 // Processor is responsible for processing incoming events 20 type Processor struct { 21 cfg Config 22 23 quit chan struct{} 24 wg sync.WaitGroup 25 26 callback Callback 27 28 inserter *workers.Workers 29 30 itemsSemaphore *datasemaphore.DataSemaphore 31 } 32 33 type ItemCallback struct { 34 Process func(br ibr.LlrIdxFullBlockRecord) error 35 Released func(br ibr.LlrIdxFullBlockRecord, peer string, err error) 36 } 37 38 type Callback struct { 39 Item ItemCallback 40 } 41 42 // New creates an event processor 43 func New(itemsSemaphore *datasemaphore.DataSemaphore, cfg Config, callback Callback) *Processor { 44 f := &Processor{ 45 cfg: cfg, 46 quit: make(chan struct{}), 47 itemsSemaphore: itemsSemaphore, 48 } 49 f.callback = callback 50 f.inserter = workers.New(&f.wg, f.quit, cfg.MaxTasks) 51 return f 52 } 53 54 // Start boots up the items processor. 55 func (f *Processor) Start() { 56 f.inserter.Start(1) 57 } 58 59 // Stop interrupts the processor, canceling all the pending operations. 60 // Stop waits until all the internal goroutines have finished. 61 func (f *Processor) Stop() { 62 close(f.quit) 63 f.itemsSemaphore.Terminate() 64 f.wg.Wait() 65 } 66 67 // Overloaded returns true if too much items are being processed 68 func (f *Processor) Overloaded() bool { 69 return f.inserter.TasksCount() > f.cfg.MaxTasks*3/4 70 } 71 72 func (f *Processor) Enqueue(peer string, items []ibr.LlrIdxFullBlockRecord, totalSize uint64, done func()) error { 73 metric := dag.Metric{Num: idx.Event(len(items)), Size: totalSize} 74 if !f.itemsSemaphore.Acquire(metric, f.cfg.SemaphoreTimeout) { 75 return ErrBusy 76 } 77 78 return f.inserter.Enqueue(func() { 79 if done != nil { 80 defer done() 81 } 82 defer f.itemsSemaphore.Release(metric) 83 for i, item := range items { 84 // process item 85 err := f.callback.Item.Process(item) 86 items[i].Txs = nil 87 items[i].Receipts = nil 88 f.callback.Item.Released(item, peer, err) 89 } 90 }) 91 } 92 93 func (f *Processor) TasksCount() int { 94 return f.inserter.TasksCount() 95 }