@@ -4,8 +4,6 @@ defmodule Realtime.Messages do
44 """
55
66 alias Realtime.Api.Message
7- alias Realtime.Channels
8- alias Realtime.Tenants.Connect
97 alias Realtime.Tenants.Repo
108
119 import Ecto.Query , only: [ from: 2 ]
@@ -14,50 +12,32 @@ defmodule Realtime.Messages do
1412 @ default_timeout 5_000
1513
1614 @ doc """
17- Persists a broadcast sent over WebSocket for `topic` if storage is enabled for such topic .
15+ Persists a broadcast sent over WebSocket for `topic` as a `persistence` message .
1816
19- Bypass RLS because the check has already been done on the message broadcast,
20- and then set `broadcasted_at` to avoid re-broadcasting the message twice.
17+ Only called after the sender's `persistence` policy authorized it, so the persisted row is always
18+ private. Bypasses RLS because that authorization already happened on the broadcast, and sets
19+ `broadcasted_at` to avoid re-broadcasting the message twice.
2120
2221 Automatically uses RPC if the database connection is not on the same node.
2322 """
24- @ spec store ( DBConnection . conn ( ) , String . t ( ) , String . t ( ) , String . t ( ) , term ( ) , boolean ( ) ) ::
25- { :ok , binary ( ) } | { :error , any ( ) } | { :error , :rpc_error , term } | { :error , :storage_disabled }
26- def store ( conn , tenant_id , topic , event , payload , private ) when node ( conn ) == node ( ) do
27- if Channels . storage_enabled? ( conn , tenant_id , topic ) do
28- insert ( conn , topic , event , payload , private )
29- else
30- { :error , :storage_disabled }
31- end
23+ @ spec store ( DBConnection . conn ( ) , String . t ( ) , String . t ( ) , term ( ) ) ::
24+ { :ok , binary ( ) } | { :error , any ( ) } | { :error , :rpc_error , term }
25+ def store ( conn , topic , event , payload ) when node ( conn ) == node ( ) do
26+ insert ( conn , topic , event , payload )
3227 end
3328
34- def store ( conn , tenant_id , topic , event , payload , private ) do
35- Realtime.GenRpc . call ( node ( conn ) , __MODULE__ , :store , [ conn , tenant_id , topic , event , payload , private ] , key: topic )
36- end
37-
38- @ doc """
39- Similar to `store/6` but runs asynchronously for callers that don't already hold a connection.
40- """
41- @ spec store_async ( String . t ( ) , String . t ( ) , String . t ( ) , term ( ) ) :: :ok
42- def store_async ( tenant_id , topic , event , payload ) do
43- Task.Supervisor . start_child ( Realtime.TaskSupervisor , fn ->
44- case Connect . lookup_or_start_connection ( tenant_id ) do
45- { :ok , conn } -> store ( conn , tenant_id , topic , event , payload , false )
46- { :error , _reason } -> :skip
47- end
48- end )
49-
50- :ok
29+ def store ( conn , topic , event , payload ) do
30+ Realtime.GenRpc . call ( node ( conn ) , __MODULE__ , :store , [ conn , topic , event , payload ] , key: topic )
5131 end
5232
53- defp insert ( conn , topic , event , payload , private ) do
33+ defp insert ( conn , topic , event , payload ) do
5434 changeset =
5535 Message . changeset ( % Message { } , % {
5636 topic: topic ,
57- extension: :broadcast ,
37+ extension: :persistence ,
5838 event: event ,
5939 payload: payload ,
60- private: private ,
40+ private: true ,
6141 broadcasted_at: NaiveDateTime . utc_now ( :microsecond )
6242 } )
6343
@@ -110,7 +90,7 @@ defmodule Realtime.Messages do
11090 where:
11191 m . topic == ^ topic and
11292 m . private == true and
113- m . extension == :broadcast and
93+ m . extension in [ :broadcast , :persistence ] and
11494 m . inserted_at >= ^ since and
11595 m . inserted_at < ^ now ,
11696 limit: ^ limit ,
0 commit comments