Skip to content

Commit 7f37f4c

Browse files
Dean KarnDean Karn
authored andcommitted
Merge pull request #7 from joeybloggs/v1
Add Consumer Hook
2 parents 5cff051 + 4d4c823 commit 7f37f4c

File tree

3 files changed

+73
-9
lines changed

3 files changed

+73
-9
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ type resultStruct struct {
5454
func main() {
5555
p := pool.NewPool(4, 16)
5656

57+
// can add a consumer hook for each consumer routine to get a value from
58+
// such as a database connection which each job can reuse via job.HookParam()
59+
// p.AddConsumerHook(func() interface{}{ return db connection or whatever})
60+
5761
fn := func(job *pool.Job) {
5862

5963
i := job.Params()[0].(int)
@@ -117,6 +121,10 @@ import (
117121
func main() {
118122
p := pool.NewPool(4, 16)
119123

124+
// can add a consumer hook for each consumer routine to get a value from
125+
// such as a database connection which each job can reuse via job.HookParam()
126+
// p.AddConsumerHook(func() interface{}{ return db connection or whatever})
127+
120128
fn := func(job *pool.Job) {
121129

122130
i := job.Params()[0].(int)

pool.go

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ const (
1111
errRecoveryString = "recovering from panic: %+v\nStack Trace:\n %s"
1212
)
1313

14+
// ConsumerHook type is a function that is called during the consumer startup
15+
// and the return value is added to each Job just prior to firing off the job.
16+
// This is good for say creating a database connection for every job to use but
17+
// not having more than there are consumers.
18+
type ConsumerHook func() interface{}
19+
1420
// ErrRecovery contains the error when a consumer goroutine needed to be recovers
1521
type ErrRecovery struct {
1622
s string
@@ -23,22 +29,30 @@ func (e *ErrRecovery) Error() string {
2329

2430
// Pool Contains all information for the pool instance
2531
type Pool struct {
26-
jobs chan *Job
27-
results chan interface{}
28-
cancel chan struct{}
29-
wg *sync.WaitGroup
30-
cancelled bool
31-
cancelLock sync.RWMutex
32+
jobs chan *Job
33+
results chan interface{}
34+
cancel chan struct{}
35+
wg *sync.WaitGroup
36+
cancelled bool
37+
cancelLock sync.RWMutex
38+
consumerHook ConsumerHook
3239
}
3340

3441
// JobFunc is the consumable function/job you wish to run
3542
type JobFunc func(job *Job)
3643

3744
// Job contains all information to run a job
3845
type Job struct {
39-
fn JobFunc
40-
params []interface{}
41-
pool *Pool
46+
fn JobFunc
47+
params []interface{}
48+
hookParam interface{}
49+
pool *Pool
50+
}
51+
52+
// HookParam returns the value, if any, set by the ConsumerHook.
53+
// Example a database connection.
54+
func (j *Job) HookParam() interface{} {
55+
return j.hookParam
4256
}
4357

4458
// Params returns an array of the params that were passed in during the Queueing of the funciton
@@ -82,13 +96,20 @@ func NewPool(consumers int, jobs int) *Pool {
8296
}
8397
}(p)
8498

99+
var consumerParm interface{}
100+
101+
if p.consumerHook != nil {
102+
consumerParm = p.consumerHook()
103+
}
104+
85105
for {
86106
select {
87107
case j := <-p.jobs:
88108
if reflect.ValueOf(j).IsNil() {
89109
return
90110
}
91111

112+
j.hookParam = consumerParm
92113
j.fn(j)
93114
p.wg.Done()
94115
case <-p.cancel:
@@ -100,6 +121,13 @@ func NewPool(consumers int, jobs int) *Pool {
100121
return p
101122
}
102123

124+
// AddConsumerHook registers a Consumer Hook function to be called by every consumer
125+
// and setting the return value on every job prior to running. Use case is for
126+
// reusing database connections.
127+
func (p *Pool) AddConsumerHook(fn ConsumerHook) {
128+
p.consumerHook = fn
129+
}
130+
103131
func (p *Pool) cancelJobs() {
104132
for range p.jobs {
105133
p.wg.Done()

pool_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,34 @@ func TestPool(t *testing.T) {
5252
Equal(t, count, 4)
5353
}
5454

55+
func TestConsumerHook(t *testing.T) {
56+
57+
pool := NewPool(4, 4)
58+
pool.AddConsumerHook(func() interface{} { return 1 })
59+
60+
fn := func(job *Job) {
61+
62+
j := job.HookParam().(int)
63+
job.Return(j)
64+
}
65+
66+
for i := 0; i < 4; i++ {
67+
pool.Queue(fn)
68+
}
69+
70+
var count int
71+
72+
for v := range pool.Results() {
73+
count++
74+
75+
val, ok := v.(int)
76+
Equal(t, ok, true)
77+
Equal(t, val, 1)
78+
}
79+
80+
Equal(t, count, 4)
81+
}
82+
5583
func TestCancel(t *testing.T) {
5684

5785
pool := NewPool(2, 4)

0 commit comments

Comments
 (0)