@@ -9,12 +9,12 @@ defmodule GenEvent.Stream do
9
9
* `:id` - the event stream id for cancellation
10
10
* `:timeout` - the timeout in between events, defaults to `:infinity`
11
11
* `:duration` - the duration of the subscription, defaults to `:infinity`
12
- * `:mode` - if the subscription mode is sync or async, defaults to `:sync `
12
+ * `:mode` - if the subscription mode is ack, sync or async, defaults to `:ack `
13
13
"""
14
- defstruct manager: nil , id: nil , timeout: :infinity , duration: :infinity , mode: :sync
14
+ defstruct manager: nil , id: nil , timeout: :infinity , duration: :infinity , mode: :ack
15
15
16
16
@ typedoc "The stream mode"
17
- @ type mode :: :sync | :async
17
+ @ type mode :: :ack | : sync | :async
18
18
19
19
@ type t :: % __MODULE__ {
20
20
manager: GenEvent . manager ,
@@ -277,7 +277,7 @@ defmodule GenEvent do
277
277
The stream is a `GenEvent` struct that implements the `Enumerable`
278
278
protocol. Consumption of events only begins when enumeration starts.
279
279
280
- `The supported options are:
280
+ ## Options
281
281
282
282
* `:id` - an id to identify all live stream instances; when an `:id` is
283
283
given, existing streams can be called with via `cancel_streams`.
@@ -287,9 +287,23 @@ defmodule GenEvent do
287
287
* `:duration` (Enumerable) - only consume events during the X milliseconds
288
288
from the streaming start.
289
289
290
- * `:mode` - the mode to consume events, can be `:sync` (default) or
291
- `:async`. On sync, the event manager waits for the event to be consumed
292
- before moving on to the next event handler.
290
+ * `:mode` - the mode to consume events, can be `:ack` (default), `:sync`
291
+ or `:async`. See modes below.
292
+
293
+ ## Modes
294
+
295
+ GenEvent stream supports three different modes.
296
+
297
+ On `:ack`, the stream acknowledges each event, providing back pressure,
298
+ but processing of the message happens asynchronously, allowing the event
299
+ manager to move on to the next handler as soon as the event is
300
+ acknowledged.
301
+
302
+ On `:sync`, the event manager waits for the event to be consumed
303
+ before moving on to the next event handler.
304
+
305
+ On `:async`, all events are processed asynchronously but there is no
306
+ ack (which means there is no backpressure).
293
307
294
308
"""
295
309
@ spec stream ( manager , Keyword . t ) :: GenEvent.Stream . t
@@ -299,7 +313,7 @@ defmodule GenEvent do
299
313
id: Keyword . get ( options , :id ) ,
300
314
timeout: Keyword . get ( options , :timeout , :infinity ) ,
301
315
duration: Keyword . get ( options , :duration , :infinity ) ,
302
- mode: Keyword . get ( options , :mode , :sync ) }
316
+ mode: Keyword . get ( options , :mode , :ack ) }
303
317
end
304
318
305
319
@ doc """
@@ -478,7 +492,7 @@ defimpl Enumerable, for: GenEvent.Stream do
478
492
end
479
493
480
494
@ doc false
481
- def handle_event ( event , { :sync , mon_pid , pid , ref } = state ) do
495
+ def handle_event ( event , { mode , mon_pid , pid , ref } = state ) when mode in [ :sync , :ack ] do
482
496
sync = Process . monitor ( mon_pid )
483
497
send pid , { ref , sync , event }
484
498
receive do
@@ -515,11 +529,17 @@ defimpl Enumerable, for: GenEvent.Stream do
515
529
516
530
defp wrap_reducer ( fun ) do
517
531
fn
518
- { nil , _manager , event } , acc ->
519
- fun . ( event , acc )
520
- { ref , manager , event } , acc ->
532
+ { :ack , ref , manager , event } , acc ->
521
533
send manager , { ref , :next }
522
534
fun . ( event , acc )
535
+ { :async , _ , _manager , event } , acc ->
536
+ fun . ( event , acc )
537
+ { :sync , ref , manager , event } , acc ->
538
+ try do
539
+ fun . ( event , acc )
540
+ after
541
+ send manager , { ref , :next }
542
+ end
523
543
end
524
544
end
525
545
@@ -548,7 +568,7 @@ defimpl Enumerable, for: GenEvent.Stream do
548
568
send ( self ( ) , { :DOWN , mon_ref , :process , mon_pid , :normal } )
549
569
exit ( { reason , { __MODULE__ , :next , [ stream , acc ] } } )
550
570
{ ^ mon_ref , sync_ref , event } ->
551
- { { sync_ref , manager_pid , event } , acc }
571
+ { { stream . mode , sync_ref , manager_pid , event } , acc }
552
572
after
553
573
timeout ->
554
574
exit ( { :timeout , { __MODULE__ , :next , [ stream , acc ] } } )
0 commit comments