@@ -29,16 +29,16 @@ final class KafkaPollingSystem<Element>: Sendable {
29
29
/// Initializes the ``KafkaBackPressurePollingSystem``.
30
30
/// Private initializer. The ``KafkaBackPressurePollingSystem`` is not supposed to be initialized directly.
31
31
/// It must rather be initialized using the ``KafkaBackPressurePollingSystem.createSystemAndSequence`` function.
32
- init ( ) {
33
- self . stateMachineLock = NIOLockedValueBox ( StateMachine ( ) )
32
+ init ( pollClosure : @escaping ( ) -> Void ) {
33
+ self . stateMachineLock = NIOLockedValueBox ( StateMachine ( pollClosure : pollClosure ) )
34
34
}
35
35
36
36
/// Runs the poll loop with the specified poll interval.
37
37
///
38
38
/// - Parameter pollInterval: The desired time interval between two consecutive polls.
39
39
/// - Returns: An awaitable task representing the execution of the poll loop.
40
- func run( pollInterval: Duration , pollClosure : @escaping ( ) -> Void , source : Producer . Source ? ) async {
41
- switch self . stateMachineLock. withLockedValue ( { $0. run ( source , pollClosure ) } ) {
40
+ func run( pollInterval: Duration ) async {
41
+ switch self . stateMachineLock. withLockedValue ( { $0. run ( ) } ) {
42
42
case . alreadyClosed:
43
43
return
44
44
case . alreadyRunning:
@@ -84,7 +84,7 @@ final class KafkaPollingSystem<Element>: Sendable {
84
84
func yield( _ element: Element ) {
85
85
self . stateMachineLock. withLockedValue { stateMachine in
86
86
switch stateMachine. state {
87
- case . started ( let source, _, _) , . producing( let source, _, _) , . stopProducing( let source, _, _, _) :
87
+ case . idle ( let source, _, _) , . producing( let source, _, _) , . stopProducing( let source, _, _, _) :
88
88
// We can also yield when in .stopProducing,
89
89
// the AsyncSequenceProducer will buffer for us
90
90
let yieldResult = source? . yield ( element)
@@ -105,7 +105,7 @@ final class KafkaPollingSystem<Element>: Sendable {
105
105
case . none:
106
106
break
107
107
}
108
- case . idle , . finished:
108
+ case . finished:
109
109
return
110
110
}
111
111
}
@@ -149,9 +149,7 @@ extension KafkaPollingSystem {
149
149
/// The possible states of the state machine.
150
150
enum State {
151
151
/// Initial state.
152
- case idle
153
- /// The ``run()`` method has been invoked and the ``KafkaPollingSystem`` is ready.
154
- case started(
152
+ case idle(
155
153
source: Producer . Source ? ,
156
154
pollClosure: ( ) -> Void ,
157
155
running: Bool
@@ -175,7 +173,42 @@ extension KafkaPollingSystem {
175
173
}
176
174
177
175
/// The current state of the state machine.
178
- var state : State = . idle
176
+ var state : State
177
+
178
+ /// Allows the producer to synchronously `yield` new elements to the ``NIOAsyncSequenceProducer``
179
+ /// and to `finish` the sequence.
180
+ var source : Producer . Source ? {
181
+ get {
182
+ // Extracts source from state machine
183
+ switch self . state {
184
+ case . idle( let source, _, _) :
185
+ return source
186
+ case . producing( let source, _, _) :
187
+ return source
188
+ case . stopProducing( let source, _, _, _) :
189
+ return source
190
+ case . finished:
191
+ return nil
192
+ }
193
+ }
194
+ set {
195
+ // Add new source to current state
196
+ switch self . state {
197
+ case . idle( _, let pollClosure, let running) :
198
+ self . state = . idle( source: newValue, pollClosure: pollClosure, running: running)
199
+ case . producing( _, let pollClosure, let running) :
200
+ self . state = . producing( source: newValue, pollClosure: pollClosure, running: running)
201
+ case . stopProducing( _, let continuation, let pollClosure, let running) :
202
+ self . state = . stopProducing( source: newValue, continuation: continuation, pollClosure: pollClosure, running: running)
203
+ case . finished:
204
+ break
205
+ }
206
+ }
207
+ }
208
+
209
+ init ( pollClosure: @escaping ( ) -> Void ) {
210
+ self . state = . idle( source: nil , pollClosure: pollClosure, running: false )
211
+ }
179
212
180
213
/// Actions to take after ``run()`` has been invoked on the ``KafkaPollingSystem/StateMachine``.
181
214
enum RunAction {
@@ -187,15 +220,13 @@ extension KafkaPollingSystem {
187
220
case startLoop
188
221
}
189
222
190
- mutating func run( _ source : Producer . Source ? , _ pollClosure : @escaping ( ) -> Void ) -> RunAction {
223
+ mutating func run( ) -> RunAction {
191
224
switch self . state {
192
- case . idle:
193
- self . state = . started( source: source, pollClosure: pollClosure, running: true )
194
- case . started( let source, let pollClosure, let running) :
225
+ case . idle( let source, let pollClosure, let running) :
195
226
guard running == false else {
196
227
return . alreadyRunning
197
228
}
198
- self . state = . started ( source: source, pollClosure: pollClosure, running: true )
229
+ self . state = . idle ( source: source, pollClosure: pollClosure, running: true )
199
230
case . producing( let source, let pollClosure, let running) :
200
231
guard running == false else {
201
232
return . alreadyRunning
@@ -228,9 +259,7 @@ extension KafkaPollingSystem {
228
259
/// - Returns: The next action for the poll loop.
229
260
func nextPollLoopAction( ) -> PollLoopAction {
230
261
switch self . state {
231
- case . idle:
232
- fatalError ( " State machine must be initialized with prepare() " )
233
- case . started( _, let pollClosure, _) , . producing( _, let pollClosure, _) :
262
+ case . idle( _, let pollClosure, _) , . producing( _, let pollClosure, _) :
234
263
return . pollAndSleep( pollClosure: pollClosure)
235
264
case . stopProducing:
236
265
// We were asked to stop producing,
@@ -251,12 +280,12 @@ extension KafkaPollingSystem {
251
280
/// Our downstream consumer allowed us to produce more elements.
252
281
mutating func produceMore( ) -> ProduceMoreAction ? {
253
282
switch self . state {
254
- case . idle , . finished, . producing:
283
+ case . finished, . producing:
255
284
break
256
285
case . stopProducing( let source, let continuation, let pollClosure, let running) :
257
286
self . state = . producing( source: source, pollClosure: pollClosure, running: running)
258
287
return . resume( continuation)
259
- case . started ( let source, let pollClosure, let running) :
288
+ case . idle ( let source, let pollClosure, let running) :
260
289
self . state = . producing( source: source, pollClosure: pollClosure, running: running)
261
290
}
262
291
return nil
@@ -267,8 +296,6 @@ extension KafkaPollingSystem {
267
296
switch self . state {
268
297
case . idle, . finished, . stopProducing:
269
298
break
270
- case . started:
271
- fatalError ( " \( #function) is not supported in state \( self . state) " )
272
299
case . producing( let source, let pollClosure, let running) :
273
300
self . state = . stopProducing( source: source, continuation: nil , pollClosure: pollClosure, running: running)
274
301
}
@@ -280,11 +307,11 @@ extension KafkaPollingSystem {
280
307
/// After resuming the continuation, our poll loop will start running again.
281
308
mutating func suspendLoop( continuation: CheckedContinuation < Void , Never > ) {
282
309
switch self . state {
283
- case . idle , . finished:
310
+ case . finished:
284
311
return
285
312
case . stopProducing( _, . some, _, _) :
286
313
fatalError ( " Internal state inconsistency. Run loop is running more than once " )
287
- case . started ( let source, let pollClosure, let running) , . producing( let source, let pollClosure, let running) , . stopProducing( let source, _, let pollClosure, let running) :
314
+ case . idle ( let source, let pollClosure, let running) , . producing( let source, let pollClosure, let running) , . stopProducing( let source, _, let pollClosure, let running) :
288
315
self . state = . stopProducing( source: source, continuation: continuation, pollClosure: pollClosure, running: running)
289
316
}
290
317
}
@@ -304,9 +331,9 @@ extension KafkaPollingSystem {
304
331
/// Terminate the state machine and finish producing elements.
305
332
mutating func terminate( ) -> TerminateAction ? {
306
333
switch self . state {
307
- case . idle , . finished:
334
+ case . finished:
308
335
return nil
309
- case . started ( let source, _, _) , . producing( let source, _, _) :
336
+ case . idle ( let source, _, _) , . producing( let source, _, _) :
310
337
self . state = . finished
311
338
return . finishSequenceSource( source: source)
312
339
case . stopProducing( let source, let continuation, _, _) :
0 commit comments