@@ -14,33 +14,60 @@ defmodule GenStage.Streamer do
14
14
x , { acc , counter } -> { :cont , { [ x | acc ] , counter - 1 } }
15
15
end )
16
16
17
- { :producer , { stack , continuation } , Keyword . take ( opts , [ :dispatcher , :demand ] ) }
17
+ on_cancel =
18
+ case Keyword . get ( opts , :on_cancel , :continue ) do
19
+ :continue -> nil
20
+ :stop -> % { }
21
+ end
22
+
23
+ { :producer , { stack , continuation , on_cancel } , Keyword . take ( opts , [ :dispatcher , :demand ] ) }
24
+ end
25
+
26
+ def handle_subscribe ( :consumer , _opts , { pid , ref } , { stack , continuation , on_cancel } ) do
27
+ if on_cancel do
28
+ { :automatic , { stack , continuation , Map . put ( on_cancel , ref , pid ) } }
29
+ else
30
+ { :automatic , { stack , continuation , on_cancel } }
31
+ end
32
+ end
33
+
34
+ def handle_cancel ( _reason , { _ , ref } , { stack , continuation , on_cancel } ) do
35
+ case on_cancel do
36
+ % { ^ ref => _ } when map_size ( on_cancel ) == 1 ->
37
+ { :stop , :normal , { stack , continuation , Map . delete ( on_cancel , ref ) } }
38
+
39
+ % { ^ ref => _ } ->
40
+ { :noreply , [ ] , { stack , continuation , Map . delete ( on_cancel , ref ) } }
41
+
42
+ _ ->
43
+ { :noreply , [ ] , { stack , continuation , on_cancel } }
44
+ end
18
45
end
19
46
20
- def handle_demand ( _demand , { stack , continuation } ) when is_atom ( continuation ) do
21
- { :noreply , [ ] , { stack , continuation } }
47
+ def handle_demand ( _demand , { stack , continuation , on_cancel } ) when is_atom ( continuation ) do
48
+ { :noreply , [ ] , { stack , continuation , on_cancel } }
22
49
end
23
50
24
- def handle_demand ( demand , { stack , continuation } ) when demand > 0 do
51
+ def handle_demand ( demand , { stack , continuation , on_cancel } ) when demand > 0 do
25
52
case continuation . ( { :cont , { [ ] , demand } } ) do
26
53
{ :suspended , { list , 0 } , continuation } ->
27
- { :noreply , :lists . reverse ( list ) , { stack , continuation } }
54
+ { :noreply , :lists . reverse ( list ) , { stack , continuation , on_cancel } }
28
55
29
56
{ status , { list , _ } } ->
30
57
GenStage . async_info ( self ( ) , :stop )
31
- { :noreply , :lists . reverse ( list ) , { stack , status } }
58
+ { :noreply , :lists . reverse ( list ) , { stack , status , on_cancel } }
32
59
end
33
60
end
34
61
35
62
def handle_info ( :stop , state ) do
36
63
{ :stop , :normal , state }
37
64
end
38
65
39
- def handle_info ( msg , { stack , continuation } ) do
66
+ def handle_info ( msg , { stack , continuation , on_cancel } ) do
40
67
log =
41
68
~c" ** Undefined handle_info in ~tp~n** Unhandled message: ~tp~n** Stream started at:~n~ts"
42
69
43
70
:error_logger . warning_msg ( log , [ inspect ( __MODULE__ ) , msg , Exception . format_stacktrace ( stack ) ] )
44
- { :noreply , [ ] , { stack , continuation } }
71
+ { :noreply , [ ] , { stack , continuation , on_cancel } }
45
72
end
46
73
end
0 commit comments