@@ -75,15 +75,17 @@ defmodule Electric.Replication.ShapeLogCollector do
7575 :ok = GenServer . call ( server , { :relation_msg , rel , trace_context } , :infinity )
7676 end
7777
78- def subscribe ( server_ref , shape_handle , shape ) do
79- GenServer . call ( server ( server_ref ) , { :subscribe , shape_handle , shape } )
78+ def subscribe ( server_ref , shape_handle , shape , action ) when action in [ :restore , :create ] do
79+ GenServer . call ( server ( server_ref ) , { :subscribe , shape_handle , shape , action } )
8080 end
8181
8282 def notify_flushed ( server_ref , shape_handle , offset ) do
8383 GenServer . cast ( server ( server_ref ) , { :writer_flushed , shape_handle , offset } )
8484 end
8585
8686 def init ( opts ) do
87+ activate_mocked_functions_from_test_process ( )
88+
8789 stack_id = opts . stack_id
8890
8991 Process . set_label ( { :shape_log_collector , stack_id } )
@@ -124,7 +126,32 @@ defmodule Electric.Replication.ShapeLogCollector do
124126 )
125127 } )
126128
127- { :ok , state }
129+ { :ok , state , { :continue , :restore_shapes } }
130+ end
131+
132+ def handle_continue ( :restore_shapes , state ) do
133+ OpenTelemetry . with_span (
134+ "shape_log_collector.restore_shapes" ,
135+ [ ] ,
136+ state . stack_id ,
137+ fn ->
138+ { partitions , filter , layers } =
139+ state . stack_id
140+ |> Electric.ShapeCache.ShapeStatus . list_shapes ( )
141+ |> Enum . reduce (
142+ { state . partitions , state . filter , state . dependency_layers } ,
143+ fn { shape_handle , shape } , { partitions , filter , layers } ->
144+ {
145+ Partitions . add_shape ( partitions , shape_handle , shape ) ,
146+ Filter . add_shape ( filter , shape_handle , shape ) ,
147+ DependencyLayers . add_dependency ( layers , shape , shape_handle )
148+ }
149+ end
150+ )
151+
152+ { :noreply , % { state | partitions: partitions , filter: filter , dependency_layers: layers } }
153+ end
154+ )
128155 end
129156
130157 def handle_info ( { { :unsubscribe , shape_handle } , ref , :process , pid , _reason } , state ) do
@@ -138,7 +165,7 @@ defmodule Electric.Replication.ShapeLogCollector do
138165 )
139166 end
140167
141- def handle_call ( { :subscribe , shape_handle , shape } , { pid , _ref } , state ) do
168+ def handle_call ( { :subscribe , shape_handle , shape , action } , { pid , _ref } , state ) do
142169 OpenTelemetry . with_span (
143170 "shape_log_collector.subscribe" ,
144171 [ shape_handle: shape_handle ] ,
@@ -148,14 +175,23 @@ defmodule Electric.Replication.ShapeLogCollector do
148175 from = { pid , ref }
149176
150177 state =
151- % {
152- state
153- | partitions: Partitions . add_shape ( state . partitions , shape_handle , shape ) ,
154- filter: Filter . add_shape ( state . filter , shape_handle , shape ) ,
155- pids_by_shape_handle: Map . put ( state . pids_by_shape_handle , shape_handle , pid ) ,
156- dependency_layers:
157- DependencyLayers . add_dependency ( state . dependency_layers , shape , shape_handle )
158- }
178+ case action do
179+ :restore ->
180+ # Once we move consumer monitoring out of this process,
181+ # subscribing with action :restore will be a no-op that we can
182+ # filter in the `subscribe/4` function
183+ state
184+
185+ :create ->
186+ % {
187+ state
188+ | partitions: Partitions . add_shape ( state . partitions , shape_handle , shape ) ,
189+ filter: Filter . add_shape ( state . filter , shape_handle , shape ) ,
190+ dependency_layers:
191+ DependencyLayers . add_dependency ( state . dependency_layers , shape , shape_handle )
192+ }
193+ end
194+ |> Map . update! ( :pids_by_shape_handle , & Map . put ( & 1 , shape_handle , pid ) )
159195 |> Map . update! ( :subscriptions , fn { count , set } ->
160196 { count + 1 , MapSet . put ( set , from ) }
161197 end )
@@ -401,4 +437,12 @@ defmodule Electric.Replication.ShapeLogCollector do
401437 defp server ( stack_id ) when is_binary ( stack_id ) , do: name ( stack_id )
402438 defp server ( { :via , _ , _ } = name ) , do: name
403439 defp server ( pid ) when is_pid ( pid ) , do: pid
440+
441+ if Mix . env ( ) == :test do
442+ def activate_mocked_functions_from_test_process do
443+ Support.TestUtils . activate_mocked_functions_for_module ( __MODULE__ )
444+ end
445+ else
446+ def activate_mocked_functions_from_test_process , do: :noop
447+ end
404448end
0 commit comments