@@ -4,43 +4,38 @@ A Golang package for supporting worker supervisor model.
44The package help developer easy to run tasks.
55It's scalable with minimum effort.
66
7+ easyworker inspired by Erlang OTP.
8+
79# Design
810
911The package has two main part:
1012
11- * The supervisor: Manage worker , give a task to worker & collect result.
12- * The worker : Receive task, run task then send result to supervisor.
13+ * The supervisor: Manage child , give a task to child & collect result.
14+ * The child : Receive task, run task then send result to supervisor.
1315
1416## Supervisor
1517
1618Start worker and moniter worker.
1719Send task to worker and get result.
1820
19- ## Worker
21+ ## Child
2022
2123Run task with user's function and handle error.
2224If user's function panic worker will check retry config and re-run if needed.
2325
2426# Guide
2527
26- easywork support 2 type of worker:
28+ easywork support 2 type of worker and a type of supervisor :
2729
28- * Task. Add a list of task and run worker
29- * Stream. Start worker then push data to worker from channel
30+ * Task, Add a list of task and run worker.
31+ * Stream, Start worker then push data to worker from channel.
32+ * Supervisor, Start a supervisor for custom worker.
3033
3134## EasyTask
3235
3336This is simple way to run parallel task.
3437User doesn't to manage goroutine, channel,...
3538
36- ## EasyStream
37-
38- This is used for streaming type.
39- In this case, tasks are continuously send to worker by user's channel.
40- Results will receive from other channle of user.
41-
42- # Example
43-
4439EasyTask example:
4540
4641``` go
@@ -52,66 +47,73 @@ fnSum = func(a ...int) int {
5247 return sum
5348}
5449
50+ // number of workers
5551numWorkers := 3
52+
53+ // retry times
5654retryTimes := 0
57- retrySleep := 0
5855
59- config , _ := NewConfig (fnSum, numWorkers, retryTimes, retrySleep)
56+ // sleep time before re-run
57+ retrySleep := 0
6058
61- task , err := NewTask (config)
59+ // new config for EasyTask
60+ config , _ := easyworker.NewConfig (fnSum, numWorkers, retryTimes, retrySleep)
6261
63- if err != nil {
64- t.Error (" cannot create task, " , err)
65- return
66- }
62+ // new EasyTask
63+ task , _ := easyworker.NewTask (config)
6764
65+ // add tasks
6866myTask.AddTask (1 , 2 , 3 )
6967myTask.AddTask (3 , 4 , 5 , 6 , 7 )
7068
69+ // start workers
7170r , e := myTask.Run ()
71+
7272if e != nil {
7373 t.Error (" run task failed, " , e)
7474} else {
7575 fmt.Println (" task result:" , r)
7676}
7777```
7878
79+ ## EasyStream
80+
81+ This is used for streaming type.
82+ In this case, tasks are continuously send to worker by user's channel.
83+ Results will receive from other channle of user.
84+
7985EasyStream example:
8086
8187``` go
88+ // fun will do task
8289fnStr = func (a int , suffix string ) string {
8390 if a%3 == 0 {
8491 panic (" panic from user func" )
8592 }
8693 return fmt.Sprintf (" %d _%s " , a, suffix)
8794}
8895
89- inCh := make (chan []interface {}, 1 )
96+ inCh := make (chan []interface {})
9097outCh := make (chan interface {})
9198
9299// number of workers = number of cpu cores (logical cores)
93- config , _ := NewConfig (fnSum, DefaultNumWorker (), 3 , 1000 )
100+ config , _ := easyworker. NewConfig (fnSum, DefaultNumWorker (), 3 , 1000 )
94101
95102// test with stream.
96- myStream , err := NewStream (config, inCh, outCh)
97- if err != nil {
98- t.Error (" create EasyWorker failed, " , err)
99- }
103+ myStream , _ := easyworker.NewStream (config, inCh, outCh)
100104
101- e := myStream.Run ()
102- if e != nil {
103- t.Error (" run stream task failed, " , e)
104- } else {
105- fmt.Println (" stream is running" )
106- }
105+ // start stream.
106+ myStream.Run ()
107107
108+ // receive data from stream.
108109go func () {
109110 for {
110111 r := <- outCh
111112 fmt.Println (" stream result: " , r)
112113 }
113114}()
114115
116+ // send data to stream.
115117go func () {
116118 for i := 0 ; i < 15 ; i++ {
117119 input := []interface {}{i, " 3" }
@@ -121,8 +123,60 @@ go func() {
121123 }
122124}()
123125
124- time.Sleep (2 * time.Second )
126+ // wait for get result
127+ time.Sleep (time.Second )
125128
126- // Stop all worker
129+ // stop all worker
127130myStream.Stop ()
128- ```
131+ ```
132+
133+ ## Supervisor
134+
135+ This is used for generic purpose worker(child).
136+ Every children has a owner restart strategy.
137+
138+ Currently, child has three type of restart strategy:
139+
140+ * ALWAYS_RESTART, supervisor always restart child if it panic/done.
141+ * NORMAL_RESTART, supervisor will restart if child was panic.
142+ * NO_RESTART, supervisor will don't restart for any reason.
143+
144+ Child will be started after add to supervisor.
145+
146+ supervisor example:
147+
148+ ``` go
149+ // example function need to run in child.
150+ loopRun1 = func (a int ) {
151+ for i := 0 ; i < a; i++ {
152+ time.Sleep (time.Second )
153+ fmt.Println (" loop at" , i)
154+ }
155+ fmt.Println (" Loop exit.." )
156+ }
157+
158+ // example function run in child. It will panic if counter > 3
159+ LoopRunWithPanic = func (a int ) {
160+ for i := 0 ; i < a; i++ {
161+ time.Sleep (time.Second )
162+ fmt.Println (" loop at" , i)
163+ if i > 3 {
164+ panic (" test loop with panic" )
165+ }
166+ }
167+ // maybe you won't see this.
168+ fmt.Println (" Loop exit.." )
169+ }
170+
171+ // create a supervisor
172+ sup := easyworker.NewSupervisor ()
173+
174+ // add direct child to supervisor.
175+ sup.NewChild (easyworker.NORMAL_RESTART , LoopRun , 5 )
176+
177+ // create a child
178+ child , _ := easyworker.NewChild (ALWAYS_RESTART, LoopRunWithPanic , 5 )
179+
180+ // add exists child.
181+ sup.AddChild (child)
182+ ```
0 commit comments