github.com/nibnait/go-learn@v0.0.0-20220227013611-dfa47ea6d2da/src/test/chapter/ch7/43_microkernel/agent.go (about) 1 package microkernel 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "strings" 8 "sync" 9 ) 10 11 const ( 12 Waiting = iota 13 Running 14 ) 15 16 var WrongStateError = errors.New("can not take the operation in the current state") 17 18 type CollectorsError struct { 19 CollectorErrors []error 20 } 21 22 func (ce CollectorsError) Error() string { 23 var strs []string 24 for _, err := range ce.CollectorErrors { 25 strs = append(strs, err.Error()) 26 } 27 return strings.Join(strs, ";") 28 } 29 30 type Event struct { 31 Source string 32 Content string 33 } 34 35 type EventReceiver interface { 36 OnEvent(evt Event) 37 } 38 39 type Collector interface { 40 Init(evtReceiver EventReceiver) error 41 Start(agtCtx context.Context) error 42 Stop() error 43 Destory() error 44 } 45 46 type Agent struct { 47 collectors map[string]Collector 48 evtBuf chan Event 49 cancel context.CancelFunc 50 ctx context.Context 51 state int 52 } 53 54 func (agt *Agent) EventProcessGroutine() { 55 var evtSeg [10]Event 56 for { 57 for i := 0; i < 10; i++ { 58 select { 59 case evtSeg[i] = <-agt.evtBuf: 60 case <-agt.ctx.Done(): 61 return 62 } 63 } 64 fmt.Println(evtSeg) 65 } 66 67 } 68 69 func NewAgent(sizeEvtBuf int) *Agent { 70 agt := Agent{ 71 collectors: map[string]Collector{}, 72 evtBuf: make(chan Event, sizeEvtBuf), 73 state: Waiting, 74 } 75 76 return &agt 77 } 78 79 func (agt *Agent) RegisterCollector(name string, collector Collector) error { 80 if agt.state != Waiting { 81 return WrongStateError 82 } 83 agt.collectors[name] = collector 84 return collector.Init(agt) 85 } 86 87 func (agt *Agent) startCollectors() error { 88 var err error 89 var errs CollectorsError 90 var mutex sync.Mutex 91 92 for name, collector := range agt.collectors { 93 go func(name string, collector Collector, ctx context.Context) { 94 defer func() { 95 mutex.Unlock() 96 }() 97 err = collector.Start(ctx) 98 mutex.Lock() 99 if err != nil { 100 errs.CollectorErrors = append(errs.CollectorErrors, 101 errors.New(name+":"+err.Error())) 102 } 103 }(name, collector, agt.ctx) 104 } 105 if len(errs.CollectorErrors) == 0 { 106 return nil 107 } 108 return errs 109 } 110 111 func (agt *Agent) stopCollectors() error { 112 var err error 113 var errs CollectorsError 114 for name, collector := range agt.collectors { 115 if err = collector.Stop(); err != nil { 116 errs.CollectorErrors = append(errs.CollectorErrors, 117 errors.New(name+":"+err.Error())) 118 } 119 } 120 if len(errs.CollectorErrors) == 0 { 121 return nil 122 } 123 124 return errs 125 } 126 127 func (agt *Agent) destoryCollectors() error { 128 var err error 129 var errs CollectorsError 130 for name, collector := range agt.collectors { 131 if err = collector.Destory(); err != nil { 132 errs.CollectorErrors = append(errs.CollectorErrors, 133 errors.New(name+":"+err.Error())) 134 } 135 } 136 if len(errs.CollectorErrors) == 0 { 137 return nil 138 } 139 return errs 140 } 141 142 func (agt *Agent) Start() error { 143 if agt.state != Waiting { 144 return WrongStateError 145 } 146 agt.state = Running 147 agt.ctx, agt.cancel = context.WithCancel(context.Background()) 148 go agt.EventProcessGroutine() 149 return agt.startCollectors() 150 } 151 152 func (agt *Agent) Stop() error { 153 if agt.state != Running { 154 return WrongStateError 155 } 156 agt.state = Waiting 157 agt.cancel() 158 return agt.stopCollectors() 159 } 160 161 func (agt *Agent) Destory() error { 162 if agt.state != Waiting { 163 return WrongStateError 164 } 165 return agt.destoryCollectors() 166 } 167 168 func (agt *Agent) OnEvent(evt Event) { 169 agt.evtBuf <- evt 170 }