@@ -18,8 +18,20 @@ defmodule Phoenix.Sync.Shape do
1818 end
1919 end
2020
21- This allows you to `subscribe/2` to the shape and receive notifications and
22- also retrieve the current dataset:
21+ This allows you to subscribe to the shape and receive notifications and
22+ also retrieve the current dataset.
23+
24+ `to_list/2` will return the current state of the shape as a list:
25+
26+ #{ inspect ( __MODULE__ ) } .to_list(MyApp.TodoShape)
27+ [
28+ {~s|"public"."todos"/"1"|, %MyApp.Todo{id: 1}},
29+ {~s|"public"."todos"/"2"|, %MyApp.Todo{id: 2}},
30+ # ...
31+ ]
32+
33+ `subscribe/2` registers the current process to receive change events (and
34+ `unsubscribe/1` allows you to stop receiving them):
2335
2436 # use the registered `name` of the shape to receive change events
2537 # within a GenServer or other process
@@ -29,27 +41,14 @@ defmodule Phoenix.Sync.Shape do
2941 end
3042
3143 # handle the shape events...
32- def handle_info({:sync, ref, {:insert, {_key, todo}}}, ref) do
33- {:noreply, state}
34- end
35-
36- def handle_info({:sync, ref, {:update, {_key, todo}}}, ref) do
44+ def handle_info({:sync, ref, event}, ref) do
45+ dbg(sync_event: event)
3746 {:noreply, state}
3847 end
3948
40- def handle_info({:sync, ref, {:delete, {_key, todo}}}, ref) do
41- {:noreply, state}
42- end
43-
44- def handle_info({:sync, ref, :up_to_date}, ref) do
45- {:noreply, state}
46- end
47-
48- def handle_info({:sync, ref, :must_refetch}, ref) do
49- {:noreply, state}
50- end
5149 """
5250
51+ @ doc false
5352 use GenServer
5453
5554 alias Phoenix.Sync.PredefinedShape
@@ -66,6 +65,48 @@ defmodule Phoenix.Sync.Shape do
6665 @ type subscription_msg_type ( ) :: operation ( ) | control ( )
6766 @ type subscribe_opts ( ) :: [ { :only , [ subscription_msg_type ( ) ] } | { :tag , term ( ) } ]
6867
68+ @ type shape_options ( ) :: [
69+ String . t ( )
70+ | Ecto.Queryable . t ( )
71+ | unquote ( NimbleOptions . option_typespec ( Phoenix.Sync.PredefinedShape . schema ( ) ) )
72+ | { :name , GenServer . name ( ) }
73+ ]
74+
75+ @ doc """
76+ Start a new shape process that will receive the sync stream events and
77+ maintain an in-memory copy of the dataset in sync with Postgres.
78+
79+ ## Options
80+
81+ Shapes are defined exactly as for `Phoenix.Sync.Client.stream/2`:
82+
83+ # using an `Ecto.Schema` module
84+ {:ok, pid} = #{ inspect ( __MODULE__ ) } .start_link(MyApp.Todo)
85+
86+ # or a full `Ecto.Query`
87+ {:ok, pid} = #{ inspect ( __MODULE__ ) } .start_link(
88+ from(t in MyApp.Todo, where: t.completed == true)
89+ )
90+
91+ # we can pass extra sync options
92+ {:ok, pid} = #{ inspect ( __MODULE__ ) } .start_link(
93+ from(t in MyApp.Todo, where: t.completed == true),
94+ replica: :full
95+ )
96+
97+ but also accept a `:name` much like other `GenServer` processes.
98+
99+ {:ok, pid} = #{ inspect ( __MODULE__ ) } .start_link(MyApp.Todo, name: TodosShape)
100+
101+ To start a Shape within a supervision tree, you pass the options as the child
102+ spec as if they were arguments:
103+
104+ children = [
105+ {#{ inspect ( __MODULE__ ) } , [MyApp.Todo, name: TodoShape]}
106+ ]
107+
108+ """
109+ @ spec start_link ( shape_options ( ) ) :: GenServer . on_start ( )
69110 def start_link ( args ) do
70111 with { :ok , stream_args , shape_opts } <- validate_args ( args ) do
71112 GenServer . start_link (
@@ -188,11 +229,13 @@ defmodule Phoenix.Sync.Shape do
188229 Enum . map ( rows , & elem ( & 1 , 1 ) )
189230 end
190231
232+ @ impl GenServer
191233 def init ( { stream_args , _shape_opts } ) do
192234 { :ok , % { stream_pid: nil , table: nil , subscriptions: % { } } ,
193235 { :continue , { :start_shape , stream_args } } }
194236 end
195237
238+ @ impl GenServer
196239 def handle_continue ( { :start_shape , stream_args } , state ) do
197240 { :ok , table_name } = Shape.Registry . register ( self ( ) )
198241
@@ -225,6 +268,7 @@ defmodule Phoenix.Sync.Shape do
225268 { :noreply , % { state | stream_pid: pid , table: table } }
226269 end
227270
271+ @ impl GenServer
228272 def handle_call ( :subscribers , _from , state ) do
229273 { :reply , Map . keys ( state . subscriptions ) , state }
230274 end
@@ -244,6 +288,7 @@ defmodule Phoenix.Sync.Shape do
244288 { :reply , :ok , % { state | subscriptions: subscriptions } }
245289 end
246290
291+ @ impl GenServer
247292 def handle_info ( { :sync_message , msg } , state ) do
248293 state = state |> handle_sync_message ( msg ) |> notify_subscribers ( msg )
249294
0 commit comments