1
1
package mysql
2
2
3
3
import (
4
- "context"
5
4
"fmt"
6
5
"sync"
7
6
"time"
@@ -33,12 +32,12 @@ type taskHandle struct {
33
32
34
33
runner DriverHandle
35
34
36
- ctx context.Context
37
- cancelFunc context.CancelFunc
38
- waitCh chan * drivers.ExitResult
39
- stats * common.TaskStatistics
35
+ waitCh chan * drivers.ExitResult
36
+ doneCh chan struct {}
37
+ stats * common.TaskStatistics
40
38
41
39
driverConfig * common.MySQLDriverConfig
40
+ shutdown bool
42
41
}
43
42
44
43
func newDtleTaskHandle (logger g.LoggerType , cfg * drivers.TaskConfig , state drivers.TaskState , started time.Time ) * taskHandle {
@@ -50,12 +49,24 @@ func newDtleTaskHandle(logger g.LoggerType, cfg *drivers.TaskConfig, state drive
50
49
startedAt : started ,
51
50
completedAt : time.Time {},
52
51
exitResult : nil ,
53
- waitCh : make (chan * drivers.ExitResult , 1 ),
52
+ waitCh : make (chan * drivers.ExitResult ),
53
+ doneCh : make (chan struct {}),
54
54
}
55
- h . ctx , h .cancelFunc = context . WithCancel ( context . TODO () )
55
+ go h .watchWaitCh ( )
56
56
return h
57
57
}
58
58
59
+ func (h * taskHandle ) watchWaitCh () {
60
+ select {
61
+ case r := <- h .waitCh :
62
+ h .stateLock .Lock ()
63
+ h .exitResult = r
64
+ h .stateLock .Unlock ()
65
+ close (h .doneCh )
66
+ case <- h .doneCh :
67
+ }
68
+ }
69
+
59
70
func (h * taskHandle ) TaskStatus () (* drivers.TaskStatus , error ) {
60
71
h .stateLock .RLock ()
61
72
defer h .stateLock .RUnlock ()
@@ -83,13 +94,14 @@ func (h *taskHandle) TaskStatus() (*drivers.TaskStatus, error) {
83
94
}, nil
84
95
}
85
96
97
+ // used when h.runner has not been setup
86
98
func (h * taskHandle ) onError (err error ) {
87
- h .waitCh <- & drivers.ExitResult {
99
+ common . WriteWaitCh ( h .waitCh , & drivers.ExitResult {
88
100
ExitCode : common .TaskStateDead ,
89
101
Signal : 0 ,
90
102
OOMKilled : false ,
91
103
Err : err ,
92
- }
104
+ })
93
105
}
94
106
95
107
func (h * taskHandle ) IsRunning () bool {
@@ -137,7 +149,8 @@ func (h *taskHandle) run(d *Driver) {
137
149
t := time .NewTimer (0 )
138
150
for {
139
151
select {
140
- case <- h .ctx .Done ():
152
+ case <- h .doneCh :
153
+ if ! t .Stop () { <- t .C }
141
154
return
142
155
case <- t .C :
143
156
if h .runner != nil {
@@ -168,12 +181,12 @@ func (h *taskHandle) NewRunner(d *Driver) (runner DriverHandle, err error) {
168
181
case common .TaskTypeSrc :
169
182
if h .driverConfig .OracleConfig != nil {
170
183
h .logger .Debug ("found oracle src" , "OracleConfig" , h .driverConfig .OracleConfig )
171
- runner , err = extractor .NewExtractorOracle (ctx , h .driverConfig , h .logger , d .storeManager , h .waitCh )
184
+ runner , err = extractor .NewExtractorOracle (ctx , h .driverConfig , h .logger , d .storeManager , h .waitCh , d . ctx )
172
185
if err != nil {
173
186
return nil , errors .Wrap (err , "NewExtractor" )
174
187
}
175
188
} else {
176
- runner , err = mysql .NewExtractor (ctx , h .driverConfig , h .logger , d .storeManager , h .waitCh , h .ctx )
189
+ runner , err = mysql .NewExtractor (ctx , h .driverConfig , h .logger , d .storeManager , h .waitCh , d .ctx )
177
190
if err != nil {
178
191
return nil , errors .Wrap (err , "NewOracleExtractor" )
179
192
}
@@ -183,13 +196,13 @@ func (h *taskHandle) NewRunner(d *Driver) (runner DriverHandle, err error) {
183
196
if h .driverConfig .KafkaConfig != nil {
184
197
h .logger .Debug ("found kafka" , "KafkaConfig" , h .driverConfig .KafkaConfig )
185
198
runner , err = kafka .NewKafkaRunner (ctx , h .driverConfig .KafkaConfig , h .logger ,
186
- d .storeManager , d .config .NatsAdvertise , h .waitCh , h .ctx )
199
+ d .storeManager , d .config .NatsAdvertise , h .waitCh , d .ctx )
187
200
if err != nil {
188
201
return nil , errors .Wrap (err , "NewKafkaRunner" )
189
202
}
190
203
} else {
191
204
runner , err = mysql .NewApplier (ctx , h .driverConfig , h .logger , d .storeManager ,
192
- d .config .NatsAdvertise , h .waitCh , d .eventer , h .taskConfig , h .ctx )
205
+ d .config .NatsAdvertise , h .waitCh , d .eventer , h .taskConfig , d .ctx )
193
206
if err != nil {
194
207
return nil , errors .Wrap (err , "NewApplier" )
195
208
}
@@ -265,23 +278,35 @@ func (h *taskHandle) emitStats(ru *common.TaskStatistics) {
265
278
}
266
279
}
267
280
268
- func (h * taskHandle ) Destroy () bool {
269
- h .stateLock .RLock ()
270
- //driver.des
271
- h .cancelFunc ()
281
+ func (h * taskHandle ) Destroy () {
282
+ if h .shutdown {
283
+ return
284
+ }
285
+ h .stateLock .Lock ()
286
+ h .shutdown = true
287
+ h .stateLock .Unlock ()
288
+
289
+ common .WriteWaitCh (h .waitCh , & drivers.ExitResult {
290
+ ExitCode : 0 ,
291
+ Signal : 0 ,
292
+ OOMKilled : false ,
293
+ Err : nil ,
294
+ })
295
+
272
296
if h .runner != nil {
273
297
err := h .runner .Shutdown ()
274
298
if err != nil {
275
299
h .logger .Error ("error in h.runner.Shutdown" , "err" , err )
276
300
}
277
301
}
278
- return h .procState == drivers .TaskStateExited
279
302
}
280
303
281
304
type DriverHandle interface {
282
305
Run ()
283
306
284
- // Shutdown is used to stop the task
307
+ // Shutdown is used to stop the task.
308
+ // Do not send ExitResult in Shutdown().
309
+ // pause API will call Shutdown and the task should not exit.
285
310
Shutdown () error
286
311
287
312
// Stats returns aggregated stats of the driver
0 commit comments