1
1
package badger
2
2
3
3
import (
4
+ "context"
4
5
"fmt"
5
6
"strconv"
6
7
"sync"
@@ -23,11 +24,12 @@ type BadgerDB struct {
23
24
logger loggerForBadger
24
25
badgerDB * badger.DB
25
26
window config.ValueLoader [time.Duration ]
26
- close chan struct {}
27
- gcDone chan struct {}
28
27
path string
29
28
opts badger.Options
30
29
once sync.Once
30
+ wg sync.WaitGroup
31
+ bgCtx context.Context
32
+ cancel context.CancelFunc
31
33
}
32
34
33
35
// DefaultPath returns the default path for the deduplication service's badger DB
@@ -57,14 +59,16 @@ func NewBadgerDB(conf *config.Config, stats stats.Stats, path string) *Dedup {
57
59
WithSyncWrites (conf .GetBool ("BadgerDB.syncWrites" , false )).
58
60
WithDetectConflicts (conf .GetBool ("BadgerDB.detectConflicts" , false ))
59
61
62
+ bgCtx , cancel := context .WithCancel (context .Background ())
60
63
db := & BadgerDB {
61
64
stats : stats ,
62
65
logger : loggerForBadger {log },
63
66
path : path ,
64
- gcDone : make (chan struct {}),
65
- close : make (chan struct {}),
66
67
window : dedupWindow ,
67
68
opts : badgerOpts ,
69
+ wg : sync.WaitGroup {},
70
+ bgCtx : bgCtx ,
71
+ cancel : cancel ,
68
72
}
69
73
return & Dedup {
70
74
badgerDB : db ,
@@ -114,9 +118,11 @@ func (d *BadgerDB) Set(kvs []types.KeyValue) error {
114
118
}
115
119
116
120
func (d * BadgerDB ) Close () {
117
- close (d .close )
118
- <- d .gcDone
119
- _ = d .badgerDB .Close ()
121
+ d .cancel ()
122
+ d .wg .Wait ()
123
+ if d .badgerDB != nil {
124
+ _ = d .badgerDB .Close ()
125
+ }
120
126
}
121
127
122
128
func (d * BadgerDB ) init () error {
@@ -127,9 +133,10 @@ func (d *BadgerDB) init() error {
127
133
if err != nil {
128
134
return
129
135
}
136
+ d .wg .Add (1 )
130
137
rruntime .Go (func () {
138
+ defer d .wg .Done ()
131
139
d .gcLoop ()
132
- close (d .gcDone )
133
140
})
134
141
})
135
142
return err
@@ -138,12 +145,15 @@ func (d *BadgerDB) init() error {
138
145
func (d * BadgerDB ) gcLoop () {
139
146
for {
140
147
select {
141
- case <- d .close :
148
+ case <- d .bgCtx . Done () :
142
149
_ = d .badgerDB .RunValueLogGC (0.5 )
143
150
return
144
151
case <- time .After (5 * time .Minute ):
145
152
}
146
153
again:
154
+ if d .bgCtx .Err () != nil {
155
+ return
156
+ }
147
157
// One call would only result in removal of at max one log file.
148
158
// As an optimization, you could also immediately re-run it whenever it returns nil error
149
159
// (this is why `goto again` is used).
0 commit comments