@@ -13,7 +13,8 @@ defmodule Electric.Client.Message do
1313 txids: [ ] ,
1414 op_position: 0 ,
1515 tags: [ ] ,
16- removed_tags: [ ]
16+ removed_tags: [ ] ,
17+ active_conditions: [ ]
1718 ]
1819
1920 @ type operation :: :insert | :update | :delete
@@ -29,7 +30,8 @@ defmodule Electric.Client.Message do
2930 txids: txids ( ) ,
3031 op_position: non_neg_integer ( ) ,
3132 tags: [ tag ( ) ] ,
32- removed_tags: [ tag ( ) ]
33+ removed_tags: [ tag ( ) ] ,
34+ active_conditions: [ boolean ( ) ]
3335 }
3436
3537 @ doc false
@@ -44,7 +46,8 @@ defmodule Electric.Client.Message do
4446 lsn: Map . get ( msg , "lsn" , nil ) ,
4547 op_position: Map . get ( msg , "op_position" , 0 ) ,
4648 tags: Map . get ( msg , "tags" , [ ] ) ,
47- removed_tags: Map . get ( msg , "removed_tags" , [ ] )
49+ removed_tags: Map . get ( msg , "removed_tags" , [ ] ) ,
50+ active_conditions: Map . get ( msg , "active_conditions" , [ ] )
4851 }
4952 end
5053
@@ -187,14 +190,22 @@ defmodule Electric.Client.Message do
187190
188191 @ enforce_keys [ :shape_handle , :offset , :schema ]
189192
190- defstruct [ :shape_handle , :offset , :schema , tag_to_keys: % { } , key_data: % { } ]
193+ defstruct [
194+ :shape_handle ,
195+ :offset ,
196+ :schema ,
197+ tag_to_keys: % { } ,
198+ key_data: % { } ,
199+ disjunct_positions: nil
200+ ]
191201
192202 @ type t :: % __MODULE__ {
193203 shape_handle: Client . shape_handle ( ) ,
194204 offset: Offset . t ( ) ,
195205 schema: Client . schema ( ) ,
196- tag_to_keys: % { String . t ( ) => MapSet . t ( String . t ( ) ) } ,
197- key_data: % { String . t ( ) => % { tags: MapSet . t ( String . t ( ) ) , msg: ChangeMessage . t ( ) } }
206+ tag_to_keys: % { optional ( term ( ) ) => MapSet . t ( String . t ( ) ) } ,
207+ key_data: % { optional ( String . t ( ) ) => map ( ) } ,
208+ disjunct_positions: [ [ non_neg_integer ( ) ] ] | nil
198209 }
199210 end
200211
@@ -251,6 +262,57 @@ defmodule Electric.Client.Message do
251262 end
252263 end
253264
265+ defmodule MoveInMessage do
266+ @ moduledoc """
267+ Represents a move-in event from the server.
268+
269+ Move-in events are sent when the server's subquery filter has changed and
270+ rows may now be included in the shape. The `patterns` field contains position
271+ and hash information that the client uses to update `active_conditions` on
272+ tracked rows.
273+ """
274+
275+ defstruct [ :patterns , :handle , :request_timestamp ]
276+
277+ @ type pattern :: % { pos: non_neg_integer ( ) , value: String . t ( ) }
278+ @ type t :: % __MODULE__ {
279+ patterns: [ pattern ( ) ] ,
280+ handle: Client . shape_handle ( ) ,
281+ request_timestamp: DateTime . t ( )
282+ }
283+
284+ def from_message (
285+ % { "headers" => % { "event" => "move-in" , "patterns" => patterns } } ,
286+ handle ,
287+ request_timestamp
288+ ) do
289+ % __MODULE__ {
290+ patterns: normalize_patterns ( patterns ) ,
291+ handle: handle ,
292+ request_timestamp: request_timestamp
293+ }
294+ end
295+
296+ def from_message (
297+ % { headers: % { event: "move-in" , patterns: patterns } } ,
298+ handle ,
299+ request_timestamp
300+ ) do
301+ % __MODULE__ {
302+ patterns: normalize_patterns ( patterns ) ,
303+ handle: handle ,
304+ request_timestamp: request_timestamp
305+ }
306+ end
307+
308+ defp normalize_patterns ( patterns ) do
309+ Enum . map ( patterns , fn
310+ % { "pos" => pos , "value" => value } -> % { pos: pos , value: value }
311+ % { pos: _ , value: _ } = pattern -> pattern
312+ end )
313+ end
314+ end
315+
254316 defguard is_insert ( msg ) when is_struct ( msg , ChangeMessage ) and msg . headers . operation == :insert
255317
256318 def parse ( % { "value" => _ } = msg , shape_handle , value_mapper_fun , request_timestamp ) do
@@ -288,6 +350,24 @@ defmodule Electric.Client.Message do
288350 [ MoveOutMessage . from_message ( msg , shape_handle , request_timestamp ) ]
289351 end
290352
353+ def parse (
354+ % { "headers" => % { "event" => "move-in" } } = msg ,
355+ shape_handle ,
356+ _value_mapper_fun ,
357+ request_timestamp
358+ ) do
359+ [ MoveInMessage . from_message ( msg , shape_handle , request_timestamp ) ]
360+ end
361+
362+ def parse (
363+ % { headers: % { event: "move-in" } } = msg ,
364+ shape_handle ,
365+ _value_mapper_fun ,
366+ request_timestamp
367+ ) do
368+ [ MoveInMessage . from_message ( msg , shape_handle , request_timestamp ) ]
369+ end
370+
291371 def parse ( "" , _handle , _value_mapper_fun , _request_timestamp ) do
292372 [ ]
293373 end
0 commit comments