@@ -9,14 +9,15 @@ import (
9
9
"github.com/indeedeng/iwf/service"
10
10
)
11
11
12
- type sortedTimers struct {
13
- status service.InternalTimerStatus
14
- // Ordered slice of all timers being awaited on
15
- timers []* service.TimerInfo
12
+ type TimerManager struct {
13
+ // Does not map to the timers actually created by the workflow provider
14
+ PendingScheduling []* service.TimerInfo
15
+ // timers created through the workflow provider that are going to fire
16
+ ScheduledTimerTimes []int64
16
17
}
17
18
18
19
type GreedyTimerProcessor struct {
19
- pendingTimers sortedTimers
20
+ timerManger TimerManager
20
21
stateExecutionCurrentTimerInfos map [string ][]* service.TimerInfo
21
22
staleSkipTimerSignals []service.StaleSkipTimerSignal
22
23
provider interfaces.WorkflowProvider
@@ -32,13 +33,13 @@ func NewGreedyTimerProcessor(
32
33
33
34
tp := & GreedyTimerProcessor {
34
35
provider : provider ,
35
- pendingTimers : sortedTimers { status : service . TimerPending },
36
+ timerManger : TimerManager { },
36
37
stateExecutionCurrentTimerInfos : map [string ][]* service.TimerInfo {},
37
38
logger : provider .GetLogger (ctx ),
38
39
staleSkipTimerSignals : staleSkipTimerSignals ,
39
40
}
40
41
41
- // start some single thread that manages timers
42
+ // start some single thread that manages PendingScheduling
42
43
tp .createGreedyTimerScheduler (ctx , continueAsNewCounter )
43
44
44
45
err := provider .SetQueryHandler (ctx , service .GetCurrentTimerInfosQueryType , func () (service.GetCurrentTimerInfosQueryResponse , error ) {
@@ -52,14 +53,14 @@ func NewGreedyTimerProcessor(
52
53
return tp
53
54
}
54
55
55
- func (t * sortedTimers ) addTimer (toAdd * service.TimerInfo ) {
56
+ func (t * TimerManager ) addTimer (toAdd * service.TimerInfo ) {
56
57
57
- if toAdd == nil || toAdd .Status != t . status {
58
+ if toAdd == nil || toAdd .Status != service . TimerPending {
58
59
panic ("invalid timer added" )
59
60
}
60
61
61
62
insertIndex := 0
62
- for i , timer := range t .timers {
63
+ for i , timer := range t .PendingScheduling {
63
64
if toAdd .FiringUnixTimestampSeconds >= timer .FiringUnixTimestampSeconds {
64
65
// don't want dupes. Makes remove simpler
65
66
if toAdd == timer {
@@ -70,73 +71,79 @@ func (t *sortedTimers) addTimer(toAdd *service.TimerInfo) {
70
71
}
71
72
insertIndex = i + 1
72
73
}
73
- t .timers = append (
74
- t .timers [:insertIndex ],
75
- append ([]* service.TimerInfo {toAdd }, t .timers [insertIndex :]... )... )
74
+ t .PendingScheduling = append (
75
+ t .PendingScheduling [:insertIndex ],
76
+ append ([]* service.TimerInfo {toAdd }, t .PendingScheduling [insertIndex :]... )... )
76
77
}
77
78
78
- func (t * sortedTimers ) removeTimer (toRemove * service.TimerInfo ) {
79
- for i , timer := range t .timers {
79
+ func (t * TimerManager ) removeTimer (toRemove * service.TimerInfo ) {
80
+ for i , timer := range t .PendingScheduling {
80
81
if toRemove == timer {
81
- t .timers = append (t .timers [:i ], t .timers [i + 1 :]... )
82
+ t .PendingScheduling = append (t .PendingScheduling [:i ], t .PendingScheduling [i + 1 :]... )
82
83
return
83
84
}
84
85
}
85
86
}
86
87
87
- func (t * sortedTimers ) pruneToNextTimer (pruneTo int64 ) * service.TimerInfo {
88
+ func (t * TimerManager ) pruneToNextTimer (pruneTo int64 ) * service.TimerInfo {
88
89
89
- if len (t .timers ) == 0 {
90
+ if len (t .PendingScheduling ) == 0 {
90
91
return nil
91
92
}
92
93
93
- index := len (t .timers )
94
+ index := len (t .PendingScheduling )
94
95
95
- for i := len (t .timers ) - 1 ; i >= 0 ; i -- {
96
- timer := t .timers [i ]
97
- if timer .FiringUnixTimestampSeconds > pruneTo && timer .Status == t . status {
96
+ for i := len (t .PendingScheduling ) - 1 ; i >= 0 ; i -- {
97
+ timer := t .PendingScheduling [i ]
98
+ if timer .FiringUnixTimestampSeconds > pruneTo && timer .Status == service . TimerPending {
98
99
break
99
100
}
100
101
index = i
101
102
}
102
- t .timers = t .timers [:index ]
103
- return t .timers [index - 1 ]
103
+
104
+ // If index is 0, it means all timers are pruned
105
+ if index == 0 {
106
+ t .PendingScheduling = nil
107
+ return nil
108
+ }
109
+
110
+ prunedTimer := t .PendingScheduling [index - 1 ]
111
+ t .PendingScheduling = t .PendingScheduling [:index ]
112
+ return prunedTimer
104
113
}
105
114
106
115
func (t * GreedyTimerProcessor ) createGreedyTimerScheduler (
107
116
ctx interfaces.UnifiedContext ,
108
117
continueAsNewCounter * cont.ContinueAsNewCounter ) {
109
118
110
119
t .provider .GoNamed (ctx , "greedy-timer-scheduler" , func (ctx interfaces.UnifiedContext ) {
111
- // NOTE: next timer to fire is at the end of the slice
112
- var createdTimers []int64
113
120
for {
114
121
t .provider .Await (ctx , func () bool {
115
- // remove fired timers
122
+ // remove fired PendingScheduling
116
123
now := t .provider .Now (ctx ).Unix ()
117
- for i := len (createdTimers ) - 1 ; i >= 0 ; i -- {
118
- if createdTimers [i ] > now {
119
- createdTimers = createdTimers [:i + 1 ]
124
+ for i := len (t . timerManger . ScheduledTimerTimes ) - 1 ; i >= 0 ; i -- {
125
+ if t . timerManger . ScheduledTimerTimes [i ] > now {
126
+ t . timerManger . ScheduledTimerTimes = t . timerManger . ScheduledTimerTimes [:i + 1 ]
120
127
break
121
128
}
122
129
}
123
- next := t .pendingTimers .pruneToNextTimer (now )
124
- return (next != nil && (len (createdTimers ) == 0 || next .FiringUnixTimestampSeconds < createdTimers [len (createdTimers )- 1 ])) || continueAsNewCounter .IsThresholdMet ()
130
+ next := t .timerManger .pruneToNextTimer (now )
131
+ return (next != nil && (len (t . timerManger . ScheduledTimerTimes ) == 0 || next .FiringUnixTimestampSeconds < t . timerManger . ScheduledTimerTimes [len (t . timerManger . ScheduledTimerTimes )- 1 ])) || continueAsNewCounter .IsThresholdMet ()
125
132
})
126
133
127
134
if continueAsNewCounter .IsThresholdMet () {
128
135
break
129
136
}
130
137
131
138
now := t .provider .Now (ctx ).Unix ()
132
- next := t .pendingTimers .pruneToNextTimer (now )
133
- //next := t.pendingTimers .getEarliestTimer()
139
+ next := t .timerManger .pruneToNextTimer (now )
140
+ //next := t.timerManger .getEarliestTimer()
134
141
// only create a new timer when a pending timer exists before the next existing timer fires
135
- if next != nil && (len (createdTimers ) == 0 || next .FiringUnixTimestampSeconds < createdTimers [len (createdTimers )- 1 ]) {
142
+ if next != nil && (len (t . timerManger . ScheduledTimerTimes ) == 0 || next .FiringUnixTimestampSeconds < t . timerManger . ScheduledTimerTimes [len (t . timerManger . ScheduledTimerTimes )- 1 ]) {
136
143
fireAt := next .FiringUnixTimestampSeconds
137
144
duration := time .Duration (fireAt - now ) * time .Second
138
145
t .provider .NewTimer (ctx , duration )
139
- createdTimers = append (createdTimers , fireAt )
146
+ t . timerManger . ScheduledTimerTimes = append (t . timerManger . ScheduledTimerTimes , fireAt )
140
147
}
141
148
}
142
149
})
@@ -216,23 +223,23 @@ func (t *GreedyTimerProcessor) WaitForTimerFiredOrSkipped(
216
223
return service .TimerSkipped
217
224
}
218
225
219
- if timer .FiringUnixTimestampSeconds > = t .provider .Now (ctx ).Unix () {
226
+ if timer .FiringUnixTimestampSeconds < = t .provider .Now (ctx ).Unix () {
220
227
timer .Status = service .TimerFired
221
228
return service .TimerFired
222
229
}
223
230
224
231
// otherwise *cancelWaiting should return false to indicate that this timer isn't completed(fired or skipped)
225
- t .pendingTimers .removeTimer (timer )
232
+ t .timerManger .removeTimer (timer )
226
233
return service .TimerPending
227
234
}
228
235
229
- // RemovePendingTimersOfState is for when a state is completed, remove all its pending timers
236
+ // RemovePendingTimersOfState is for when a state is completed, remove all its pending PendingScheduling
230
237
func (t * GreedyTimerProcessor ) RemovePendingTimersOfState (stateExeId string ) {
231
238
232
239
timers := t .stateExecutionCurrentTimerInfos [stateExeId ]
233
240
234
241
for _ , timer := range timers {
235
- t .pendingTimers .removeTimer (timer )
242
+ t .timerManger .removeTimer (timer )
236
243
}
237
244
238
245
delete (t .stateExecutionCurrentTimerInfos , stateExeId )
@@ -256,7 +263,9 @@ func (t *GreedyTimerProcessor) AddTimers(
256
263
FiringUnixTimestampSeconds : cmd .GetFiringUnixTimestampSeconds (),
257
264
Status : service .TimerPending ,
258
265
}
259
- t .pendingTimers .addTimer (& timer )
266
+ }
267
+ if timer .Status == service .TimerPending {
268
+ t .timerManger .addTimer (& timer )
260
269
}
261
270
timers [idx ] = & timer
262
271
}
0 commit comments