@@ -115,26 +115,32 @@ defmodule Realtime.Api do
115115 Logger . debug ( "create_tenant #{ inspect ( attrs , pretty: true ) } " )
116116 tenant_id = Map . get ( attrs , :external_id ) || Map . get ( attrs , "external_id" )
117117
118- % Tenant { }
119- |> Tenant . changeset ( attrs )
120- |> region_aware_write ( :insert , tenant_id )
118+ if master_region? ( ) do
119+ % Tenant { }
120+ |> Tenant . changeset ( attrs )
121+ |> Repo . insert ( )
122+ else
123+ call ( :create_tenant , [ attrs ] , tenant_id )
124+ end
121125 end
122126
123127 @ doc """
124128 Updates a tenant.
125-
126- ## Examples
127-
128- iex> update_tenant(tenant, %{field: new_value})
129- {:ok, %Tenant{}}
130-
131- iex> update_tenant(tenant, %{field: bad_value})
132- {:error, %Ecto.Changeset{}}
133-
134129 """
135- def update_tenant ( % Tenant { } = tenant , attrs ) do
130+ @ spec update_tenant_by_external_id ( binary ( ) , map ( ) ) :: { :ok , Tenant . t ( ) } | { :error , term ( ) }
131+ def update_tenant_by_external_id ( tenant_id , attrs ) when is_binary ( tenant_id ) do
132+ if master_region? ( ) do
133+ tenant_id
134+ |> get_tenant_by_external_id ( use_replica?: false )
135+ |> update_tenant ( attrs )
136+ else
137+ call ( :update_tenant_by_external_id , [ tenant_id , attrs ] , tenant_id )
138+ end
139+ end
140+
141+ defp update_tenant ( % Tenant { } = tenant , attrs ) do
136142 changeset = Tenant . changeset ( tenant , attrs )
137- updated = region_aware_write ( changeset , :update , tenant . external_id )
143+ updated = Repo . update ( changeset )
138144
139145 case updated do
140146 { :ok , tenant } ->
@@ -150,42 +156,31 @@ defmodule Realtime.Api do
150156 updated
151157 end
152158
153- @ doc """
154- Deletes a tenant.
155-
156- ## Examples
157-
158- iex> delete_tenant(tenant)
159- {:ok, %Tenant{}}
160-
161- iex> delete_tenant(tenant)
162- {:error, %Ecto.Changeset{}}
163-
164- """
165- def delete_tenant ( % Tenant { } = tenant ) , do: Repo . delete ( tenant )
166-
167159 @ spec delete_tenant_by_external_id ( String . t ( ) ) :: boolean ( )
168160 def delete_tenant_by_external_id ( id ) do
169- from ( t in Tenant , where: t . external_id == ^ id )
170- |> region_aware_write ( :delete_all , id )
171- |> case do
172- { num , _ } when num > 0 -> true
173- _ -> false
161+ if master_region? ( ) do
162+ query = from ( t in Tenant , where: t . external_id == ^ id )
163+ { num , _ } = Repo . delete_all ( query )
164+ num > 0
165+ else
166+ call ( :delete_tenant_by_external_id , [ id ] , id )
174167 end
175168 end
176169
177- @ spec get_tenant_by_external_id ( String . t ( ) , atom ( ) ) :: Tenant . t ( ) | nil
178- def get_tenant_by_external_id ( external_id , repo \\ :replica )
179- when repo in [ :primary , :replica ] do
180- repo =
181- case repo do
182- :primary -> Repo
183- :replica -> Replica . replica ( )
184- end
170+ @ spec get_tenant_by_external_id ( String . t ( ) , Keyword . t ( ) ) :: Tenant . t ( ) | nil
171+ def get_tenant_by_external_id ( external_id , opts \\ [ ] ) do
172+ use_replica? = Keyword . get ( opts , :use_replica? , true )
185173
186- Tenant
187- |> repo . get_by ( external_id: external_id )
188- |> repo . preload ( :extensions )
174+ cond do
175+ use_replica? ->
176+ Replica . replica ( ) . get_by ( Tenant , external_id: external_id ) |> Replica . replica ( ) . preload ( :extensions )
177+
178+ ! use_replica? and master_region? ( ) ->
179+ Repo . get_by ( Tenant , external_id: external_id ) |> Repo . preload ( :extensions )
180+
181+ true ->
182+ call ( :get_tenant_by_external_id , [ external_id , opts ] , external_id )
183+ end
189184 end
190185
191186 defp list_extensions ( type ) do
@@ -195,26 +190,36 @@ defmodule Realtime.Api do
195190 end
196191
197192 def rename_settings_field ( from , to ) do
198- for extension <- list_extensions ( "postgres_cdc_rls" ) do
199- { value , settings } = Map . pop ( extension . settings , from )
200- new_settings = Map . put ( settings , to , value )
201-
202- extension
203- |> Changeset . cast ( % { settings: new_settings } , [ :settings ] )
204- |> region_aware_write ( :update! , extension . external_id )
193+ if master_region? ( ) do
194+ for extension <- list_extensions ( "postgres_cdc_rls" ) do
195+ { value , settings } = Map . pop ( extension . settings , from )
196+ new_settings = Map . put ( settings , to , value )
197+
198+ extension
199+ |> Changeset . cast ( % { settings: new_settings } , [ :settings ] )
200+ |> Repo . update ( )
201+ end
202+ else
203+ call ( :rename_settings_field , [ from , to ] , from )
205204 end
206205 end
207206
207+ @ spec preload_counters ( nil | Realtime.Api.Tenant . t ( ) , any ( ) ) :: nil | Realtime.Api.Tenant . t ( )
208208 @ doc """
209209 Updates the migrations_ran field for a tenant.
210210 """
211211 @ spec update_migrations_ran ( binary ( ) , integer ( ) ) :: { :ok , Tenant . t ( ) } | { :error , term ( ) }
212212 def update_migrations_ran ( external_id , count ) do
213- external_id
214- |> Cache . get_tenant_by_external_id ( )
215- |> Tenant . changeset ( % { migrations_ran: count } )
216- |> region_aware_write ( :update! , external_id )
217- |> tap ( fn _ -> Cache . distributed_invalidate_tenant_cache ( external_id ) end )
213+ if master_region? ( ) do
214+ tenant = get_tenant_by_external_id ( external_id , use_replica?: false )
215+
216+ tenant
217+ |> Tenant . changeset ( % { migrations_ran: count } )
218+ |> Repo . update ( )
219+ |> tap ( fn _ -> Cache . distributed_invalidate_tenant_cache ( external_id ) end )
220+ else
221+ call ( :update_migrations_ran , [ external_id , count ] , external_id )
222+ end
218223 end
219224
220225 def preload_counters ( nil ) , do: nil
@@ -257,21 +262,13 @@ defmodule Realtime.Api do
257262
258263 defp maybe_restart_db_connection ( _changeset ) , do: nil
259264
260- defp local_call ? do
265+ defp master_region ? do
261266 region = Application . get_env ( :realtime , :region )
262267 master_region = Application . get_env ( :realtime , :master_region ) || region
263268 region == master_region
264269 end
265270
266- defp region_aware_write ( % struct { } = argument , operation , tenant_id ) when struct in [ Changeset , Ecto.Query ] do
267- if local_call? ( ) ,
268- do: local_call ( operation , [ argument ] , tenant_id ) ,
269- else: remote_call ( operation , [ argument ] , tenant_id )
270- end
271-
272- defp local_call ( operation , args , _tenant_id ) , do: apply ( Realtime.Repo , operation , args )
273-
274- defp remote_call ( operation , args , tenant_id ) do
271+ defp call ( operation , args , tenant_id ) do
275272 master_region = Application . get_env ( :realtime , :master_region )
276273
277274 with { :ok , master_node } <- Nodes . node_from_region ( master_region , self ( ) ) ,
@@ -281,7 +278,7 @@ defmodule Realtime.Api do
281278 end
282279
283280 defp wrapped_call ( master_node , operation , args , tenant_id ) do
284- case GenRpc . call ( master_node , Realtime.Repo , operation , args , tenant_id: tenant_id ) do
281+ case GenRpc . call ( master_node , __MODULE__ , operation , args , tenant_id: tenant_id ) do
285282 { :error , :rpc_error , reason } -> { :error , reason }
286283 { :error , reason } -> { :error , reason }
287284 result -> { :ok , result }
0 commit comments