@@ -14,33 +14,34 @@ Create a pool and start running a job.
14
14
package main
15
15
16
16
import (
17
- " log"
18
- " context"
19
- " time"
17
+ " context"
18
+ " log"
19
+ " os"
20
+ " os/signal"
20
21
21
- " github.com/hmoragrega/workers"
22
+ " github.com/hmoragrega/workers"
22
23
)
23
24
24
25
func main () {
25
- var pool Pool
26
+ ctx , cancel := context.WithCancel (context.Background ())
27
+ stop := make (chan os.Signal , 1 )
28
+ signal.Notify (stop, os.Interrupt )
26
29
27
- job := workers. JobFunc ( func (ctx context. Context ) error {
28
- // my job code
29
- return nil
30
- } )
30
+ go func () {
31
+ <- stop
32
+ cancel ()
33
+ }( )
31
34
32
- if err := pool.Start (job); err != nil {
33
- log.Fatal (" cannot start pool" , err)
34
- }
35
+ job := workers.JobFunc (func (ctx context.Context ) error {
36
+ // my job code
37
+ return nil
38
+ })
35
39
36
- defer func () {
37
- ctx , cancel := context.WithTimeout (context.Background (), 5 *time.Second )
38
- defer cancel ()
40
+ var pool workers.Pool
39
41
40
- if err := pool.Close (ctx); err != nil {
41
- log.Fatal (" cannot close pool" , err)
42
- }
43
- }()
42
+ if err := pool.Run (ctx, job); err != nil {
43
+ log.Fatal (" job pool failed" , err)
44
+ }
44
45
}
45
46
```
46
47
@@ -55,34 +56,54 @@ behaviour
55
56
56
57
``` go
57
58
type Config struct {
58
- // Min indicates the minimum number of workers that can run concurrently.
59
- // By default the pool can have 0 workers, pausing it effectively.
60
- Min int
59
+ // Min indicates the minimum number of workers that can run concurrently.
60
+ // By default the pool can have 0 workers, pausing it effectively.
61
+ Min int
61
62
62
- // Max indicates the maximum number of workers that can run concurrently.
63
- // the default "0" indicates an infinite number of workers.
64
- Max int
63
+ // Max indicates the maximum number of workers that can run concurrently.
64
+ // the default "0" indicates an infinite number of workers.
65
+ Max int
65
66
66
- // Initial indicates the initial number of workers that should be running.
67
- // The default value will be the greater number between 1 or the given minimum.
68
- Initial int
67
+ // Initial indicates the initial number of workers that should be running.
68
+ // The default value will be the greater number between 1 or the given minimum.
69
+ Initial int
69
70
}
70
71
```
71
72
72
73
To have a pool with a tweaked config you can call ` NewWithConfig `
73
74
``` go
74
75
pool := workers.Must (NewWithConfig (workers.Config {
75
- Min : 3 ,
76
- Max : 10 ,
77
- Initial : 5 ,
76
+ Min : 3 ,
77
+ Max : 10 ,
78
+ Initial : 5 ,
78
79
}))
79
80
```
80
81
82
+ #### Running non-stop
83
+ If you want to keep the pool running in a blocking call you
84
+ can call ` Run ` or ` RunWithBuilder ` .
85
+
86
+ In this mode the pool will run until the given context is
87
+ terminated.
88
+
89
+ The pool then will be closed without a timeout.
90
+
91
+ ``` go
92
+ var pool workers.Pool
93
+
94
+ if err := pool.Run (job); err != nil {
95
+ log.Println (" pool the pool" , err)
96
+ }
97
+ ```
98
+
99
+ Alternatively you can start and stop the pool to have
100
+ a fine-grained control of the pool live-cycle.
101
+
81
102
#### Starting the pool
82
- To start the pool give it a job to run:
103
+ To start the pool give it a job (or a [ job builder ] ( #builder-jobs ) ) to run:
83
104
``` go
84
105
if err := pool.Start (job); err != nil {
85
- log.Println (" cannot start the pool" , err)
106
+ log.Println (" cannot start the pool" , err)
86
107
}
87
108
```
88
109
The operation will fail if:
@@ -96,7 +117,7 @@ given context is cancelled.
96
117
97
118
``` go
98
119
if err := pool.Close (ctx); err != nil {
99
- log.Println (" cannot start the pool" , err)
120
+ log.Println (" cannot start the pool" , err)
100
121
}
101
122
```
102
123
@@ -114,7 +135,7 @@ Alternative `CloseWithTimeout` can be used passing a
114
135
To add a new worker to the pool you can call
115
136
``` go
116
137
if err := pool.More (); err != nil {
117
- log.Println (" cannot add more workers" , err)
138
+ log.Println (" cannot add more workers" , err)
118
139
}
119
140
```
120
141
The operation will fail if:
@@ -126,7 +147,7 @@ The operation will fail if:
126
147
To remove a worker you can use ` Less ` .
127
148
``` go
128
149
if err := pool.Less (); err != nil {
129
- log.Println (" cannot remove more workers" , err)
150
+ log.Println (" cannot remove more workers" , err)
130
151
}
131
152
```
132
153
Less will remove a worker from the pool, immediately reducing
@@ -169,11 +190,13 @@ To extend the functionality of jobs you can use builders, middlewares
169
190
or wrappers.
170
191
171
192
#### Builder Jobs
172
- Some time you want to share data across job execution within the same worker.
173
- For example, you could share a buffer of pre-allocated memory.
193
+ Sometimes you want to share data across job execution within the same worker.
194
+
195
+ For this you can use a job builder to indicate that every worker that
196
+ joins the pool will have its own job.
174
197
175
- In this case you can use a job builder to indicate that every worker that
176
- joins the pool will have its own job.
198
+ ** NOTE: ** in this case, the jobs are not going to be running concurrently,
199
+ making much easier to avoid data races.
177
200
178
201
``` go
179
202
// JobBuilder is a job that needs to be built during
@@ -183,7 +206,31 @@ type JobBuilder interface {
183
206
New () Job
184
207
}
185
208
```
186
- In this case you will have to call ` StartWithBuilder ` method to start the pool.
209
+ You will have to call ` StartWithBuilder ` method to start the pool with a job builder.
210
+ ``` go
211
+ var (
212
+ numberOfWorkers = 3
213
+ workSlots = make ([]int , numberOfWorkers)
214
+ workerID int32
215
+ )
216
+
217
+ builder := JobBuilderFunc (func () Job {
218
+ workerID := atomic.AddInt32 (&workerID, 1 )
219
+
220
+ var count int
221
+ return JobFunc (func (ctx context.Context ) error {
222
+ // count is not shared across worker goroutines
223
+ // no need to protect it against data races
224
+ count++
225
+ // same for the slice, since each worker
226
+ // updated only its own index.
227
+ workSlots[workerID-1 ] = count
228
+ return nil
229
+ })
230
+ })
231
+
232
+ p.StartWithBuilder (builder)
233
+ ```
187
234
188
235
#### Job Middleware
189
236
A middleware allows to extend the job capabilities
@@ -239,7 +286,7 @@ pool.Start(workers.JobFunc(func(ctx context.Context) error {
239
286
If you need to add a middleware before starting the job instead of on pool creating
240
287
there's the little handy function ` Wrap ` that will easy applying them for you.
241
288
242
- ```
289
+ ``` go
243
290
// Wrap is a helper to apply a chain of middleware to a job.
244
291
func Wrap (job Job , middlewares ...Middleware ) Job
245
292
```
@@ -249,7 +296,7 @@ var pool Pool
249
296
250
297
job := workers.JobFunc(func(ctx context.Context) (err error) {
251
298
// work
252
- return err
299
+ return err
253
300
}
254
301
255
302
pool.Start (workers.Wrap (job, jobLogger (" my-job" )))
@@ -266,7 +313,7 @@ having to return error from you job function.
266
313
267
314
``` go
268
315
job := func (ctx context.Context ) {
269
- // work
316
+ // work
270
317
}
271
318
272
319
var pool workers.Pool
0 commit comments