@@ -13,7 +13,6 @@ import (
13
13
"github.com/garethgeorge/backrest/internal/config"
14
14
"github.com/garethgeorge/backrest/internal/hook"
15
15
"github.com/garethgeorge/backrest/internal/oplog"
16
- "github.com/garethgeorge/backrest/internal/queue"
17
16
"github.com/garethgeorge/backrest/internal/rotatinglog"
18
17
"go.uber.org/zap"
19
18
"google.golang.org/protobuf/proto"
@@ -41,10 +40,14 @@ type Orchestrator struct {
41
40
config * v1.Config
42
41
OpLog * oplog.OpLog
43
42
repoPool * resticRepoPool
44
- taskQueue * queue. TimePriorityQueue [ scheduledTask ]
43
+ taskQueue taskQueue
45
44
hookExecutor * hook.HookExecutor
46
45
logStore * rotatinglog.RotatingLog
47
- runningTask atomic.Pointer [taskExecutionInfo ]
46
+
47
+ // now for the purpose of testing; used by Run() to get the current time.
48
+ now func () time.Time
49
+
50
+ runningTask atomic.Pointer [taskExecutionInfo ]
48
51
}
49
52
50
53
func NewOrchestrator (resticBin string , cfg * v1.Config , oplog * oplog.OpLog , logStore * rotatinglog.RotatingLog ) (* Orchestrator , error ) {
@@ -56,8 +59,10 @@ func NewOrchestrator(resticBin string, cfg *v1.Config, oplog *oplog.OpLog, logSt
56
59
OpLog : oplog ,
57
60
config : cfg ,
58
61
// repoPool created with a memory store to ensure the config is updated in an atomic operation with the repo pool's config value.
59
- repoPool : newResticRepoPool (resticBin , & config.MemoryStore {Config : cfg }),
60
- taskQueue : queue .NewTimePriorityQueue [scheduledTask ](),
62
+ repoPool : newResticRepoPool (resticBin , & config.MemoryStore {Config : cfg }),
63
+ taskQueue : newTaskQueue (func () time.Time {
64
+ return o .curTime ()
65
+ }),
61
66
hookExecutor : hook .NewHookExecutor (oplog , logStore ),
62
67
logStore : logStore ,
63
68
}
@@ -99,6 +104,13 @@ func NewOrchestrator(resticBin string, cfg *v1.Config, oplog *oplog.OpLog, logSt
99
104
return o , nil
100
105
}
101
106
107
+ func (o * Orchestrator ) curTime () time.Time {
108
+ if o .now != nil {
109
+ return o .now ()
110
+ }
111
+ return time .Now ()
112
+ }
113
+
102
114
func (o * Orchestrator ) ApplyConfig (cfg * v1.Config ) error {
103
115
o .mu .Lock ()
104
116
defer o .mu .Unlock ()
@@ -109,13 +121,12 @@ func (o *Orchestrator) ApplyConfig(cfg *v1.Config) error {
109
121
return fmt .Errorf ("failed to update repo pool config: %w" , err )
110
122
}
111
123
112
- return o .scheduleDefaultTasks (cfg )
124
+ return o .ScheduleDefaultTasks (cfg )
113
125
}
114
126
115
127
// rescheduleTasksIfNeeded checks if any tasks need to be rescheduled based on config changes.
116
- func (o * Orchestrator ) scheduleDefaultTasks (config * v1.Config ) error {
128
+ func (o * Orchestrator ) ScheduleDefaultTasks (config * v1.Config ) error {
117
129
zap .L ().Info ("scheduling default tasks, waiting for task queue reset." )
118
-
119
130
removedTasks := o .taskQueue .Reset ()
120
131
for _ , t := range removedTasks {
121
132
if err := t .task .Cancel (v1 .OperationStatus_STATUS_SYSTEM_CANCELLED ); err != nil {
@@ -184,22 +195,28 @@ func (o *Orchestrator) CancelOperation(operationId int64, status v1.OperationSta
184
195
}
185
196
186
197
tasks := o .taskQueue .Reset ()
198
+ remaining := make ([]scheduledTask , 0 , len (tasks ))
199
+
187
200
for _ , t := range tasks {
188
201
if t .task .OperationId () == operationId {
189
202
if err := t .task .Cancel (status ); err != nil {
190
203
return fmt .Errorf ("cancel task %q: %w" , t .task .Name (), err )
191
204
}
192
205
193
- nextTime := t .task .Next (t .runAt )
194
- if nextTime == nil {
195
- continue
206
+ // check if the task has a next after it's current 'runAt' time, if it does then we will schedule the next run.
207
+ if nextTime := t .task .Next (t .runAt ); nextTime != nil {
208
+ remaining = append (remaining , scheduledTask {
209
+ task : t .task ,
210
+ runAt : * nextTime ,
211
+ })
196
212
}
197
-
198
- t . runAt = * nextTime
213
+ } else {
214
+ remaining = append ( remaining , * t )
199
215
}
200
- o .taskQueue .Enqueue (t .runAt , t .priority , t ) // requeue the task.
201
216
}
202
217
218
+ o .taskQueue .Push (remaining ... )
219
+
203
220
return nil
204
221
}
205
222
@@ -214,7 +231,7 @@ func (o *Orchestrator) Run(mainCtx context.Context) {
214
231
}
215
232
216
233
t := o .taskQueue .Dequeue (mainCtx )
217
- if t . task == nil {
234
+ if t == nil {
218
235
continue
219
236
}
220
237
@@ -250,12 +267,12 @@ func (o *Orchestrator) Run(mainCtx context.Context) {
250
267
}
251
268
252
269
func (o * Orchestrator ) ScheduleTask (t Task , priority int , callbacks ... func (error )) {
253
- nextRun := t .Next (time . Now ())
270
+ nextRun := t .Next (o . curTime ())
254
271
if nextRun == nil {
255
272
return
256
273
}
257
274
zap .L ().Info ("scheduling task" , zap .String ("task" , t .Name ()), zap .String ("runAt" , nextRun .Format (time .RFC3339 )))
258
- o .taskQueue .Enqueue ( * nextRun , priority , scheduledTask {
275
+ o .taskQueue .Push ( scheduledTask {
259
276
task : t ,
260
277
runAt : * nextRun ,
261
278
priority : priority ,
@@ -324,11 +341,3 @@ type taskExecutionInfo struct {
324
341
operationId int64
325
342
cancel func ()
326
343
}
327
-
328
- type scheduledTask struct {
329
- task Task
330
- runAt time.Time
331
- priority int
332
- callbacks []func (error )
333
- config * v1.Config
334
- }
0 commit comments