1
1
package worker
2
2
3
- import "errors"
3
+ import (
4
+ "errors"
5
+ "sync"
6
+ )
4
7
5
8
type Batch struct {
6
9
batchPosition int
7
10
batchSize int
8
11
itemsToSave []interface {}
9
12
pushHandler BatchHandler
10
13
flushHandler BatchHandler
14
+ mutex * sync.Mutex
11
15
}
12
16
13
17
type BatchHandler func ([]interface {}) error
@@ -23,26 +27,33 @@ func (b *Batch) Init(batchSize int, pushHandler BatchHandler, flushHandler Batch
23
27
24
28
b .pushHandler = pushHandler
25
29
b .flushHandler = flushHandler
30
+ b .mutex = & sync.Mutex {}
26
31
}
27
32
28
33
func (b * Batch ) Push (record interface {}) error {
29
34
if b .batchSize == 0 {
30
35
return errors .New ("batch not initialized" )
31
36
}
32
37
38
+ // lock around batch processing
39
+ b .mutex .Lock ()
40
+
33
41
// allocate the buffer of items to save, if needed
34
42
if b .itemsToSave == nil {
35
43
b .itemsToSave = make ([]interface {}, b .batchSize , b .batchSize )
36
44
b .batchPosition = 0
37
- }
38
-
39
- if b .batchPosition >= b .batchSize {
45
+ b .mutex .Unlock ()
46
+ } else if b .batchPosition >= b .batchSize {
40
47
batch := b .itemsToSave
41
48
42
49
// allocate a new buffer, put the inbound record as the first item
43
50
b .itemsToSave = make ([]interface {}, b .batchSize , b .batchSize )
44
51
b .itemsToSave [0 ] = record
45
52
b .batchPosition = 1
53
+
54
+ // release the lock
55
+ b .mutex .Unlock ()
56
+
46
57
if err := b .pushHandler (batch ); err != nil {
47
58
return err
48
59
}
@@ -52,24 +63,42 @@ func (b *Batch) Push(record interface{}) error {
52
63
} else {
53
64
b .itemsToSave [b .batchPosition ] = record
54
65
b .batchPosition ++
66
+ b .mutex .Unlock ()
55
67
}
56
68
57
69
return nil
58
70
}
59
71
72
+ func (b * Batch ) GetPosition () int {
73
+ b .mutex .Lock ()
74
+ pos := b .batchPosition
75
+ b .mutex .Unlock ()
76
+ return pos
77
+ }
78
+
60
79
func (b * Batch ) Flush () error {
61
80
if b .batchSize == 0 {
62
81
return errors .New ("batch not initialized" )
63
82
}
64
83
84
+ // lock around batch processing
85
+ b .mutex .Lock ()
65
86
if len (b .itemsToSave ) > 0 {
87
+
88
+ // snag the rest of the buffer as a slice, reset buffer
66
89
subSlice := (b .itemsToSave )[0 :b .batchPosition ]
67
90
b .itemsToSave = make ([]interface {}, b .batchSize , b .batchSize )
68
91
b .batchPosition = 0
92
+
93
+ // we've finished batch processing, unlock
94
+ b .mutex .Unlock ()
95
+
96
+ // call the configured flush handler
69
97
err := b .flushHandler (subSlice )
70
98
subSlice = nil
71
99
return err
72
100
}
101
+ b .mutex .Unlock ()
73
102
74
103
return nil
75
104
}
0 commit comments