go-hep.org/x/hep@v0.38.1/fwk/worker.go (about) 1 // Copyright ©2017 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package fwk 6 7 import ( 8 "context" 9 "fmt" 10 ) 11 12 type workercontrol struct { 13 evts chan ctxType 14 done chan struct{} 15 errc chan error 16 runctx context.Context 17 } 18 19 type worker struct { 20 slot int 21 keys []string 22 //store datastore 23 ctxs []ctxType 24 msg msgstream 25 26 evts <-chan ctxType 27 done chan<- struct{} 28 errc chan<- error 29 runctx context.Context 30 } 31 32 func newWorker(i int, app *appmgr, ctrl *workercontrol) *worker { 33 wrk := &worker{ 34 slot: i, 35 keys: app.dflow.keys(), 36 ctxs: make([]ctxType, len(app.tsks)), 37 msg: newMsgStream(fmt.Sprintf("%s-worker-%03d", app.name, i), app.msg.lvl, nil), 38 evts: ctrl.evts, 39 done: ctrl.done, 40 errc: ctrl.errc, 41 runctx: ctrl.runctx, 42 } 43 for j, tsk := range app.tsks { 44 wrk.ctxs[j] = ctxType{ 45 id: -1, 46 slot: i, 47 msg: newMsgStream(tsk.Name(), app.msg.lvl, nil), 48 mgr: nil, // nobody's supposed to access mgr's state during event-loop 49 } 50 } 51 52 go wrk.run(app.tsks) 53 54 return wrk 55 } 56 57 func (wrk *worker) run(tsks []Task) { 58 defer func() { 59 wrk.done <- struct{}{} 60 }() 61 62 for { 63 select { 64 case ievt, ok := <-wrk.evts: 65 if !ok { 66 return 67 } 68 wrk.runTask(wrk.runctx, ievt, tsks) 69 70 case <-wrk.runctx.Done(): 71 //wrk.store.close() 72 return 73 } 74 } 75 } 76 77 func (wrk *worker) runTask(ctx context.Context, ievt ctxType, tsks []Task) { 78 wrk.msg.Debugf(">>> running evt=%d...\n", ievt.ID()) 79 80 evtstore := ievt.store.(*datastore) 81 evtctx, evtCancel := context.WithCancel(wrk.runctx) 82 defer evtCancel() 83 84 evt := taskrunner{ 85 ievt: ievt.ID(), 86 errc: make(chan error, len(tsks)), 87 evtctx: evtctx, 88 } 89 for i, tsk := range tsks { 90 ctx := wrk.ctxs[i] 91 ctx.store = evtstore 92 ctx.ctx = evtctx 93 go evt.run(i, ctx, tsk) 94 } 95 ndone := 0 96 errloop: 97 for { 98 select { 99 case err, ok := <-evt.errc: 100 if !ok { 101 return 102 } 103 ndone++ 104 if err != nil { 105 evtstore.close() 106 wrk.msg.flush() 107 108 wrk.errc <- err 109 return 110 } 111 if ndone == len(tsks) { 112 break errloop 113 } 114 case <-evtctx.Done(): 115 evtstore.close() 116 wrk.msg.flush() 117 return 118 } 119 } 120 err := evtstore.reset(wrk.keys) 121 evtstore.close() 122 wrk.msg.flush() 123 124 if err != nil { 125 wrk.errc <- err 126 return 127 } 128 } 129 130 type taskrunner struct { 131 errc chan error 132 evtctx context.Context 133 134 ievt int64 135 } 136 137 func (run taskrunner) run(i int, ctx ctxType, tsk Task) { 138 ctx.id = run.ievt 139 select { 140 case run.errc <- tsk.Process(ctx): 141 // FIXME(sbinet) dont be so eager to flush... 142 ctx.msg.flush() 143 case <-run.evtctx.Done(): 144 ctx.msg.flush() 145 } 146 }