@@ -5,6 +5,8 @@ defmodule Realtime.GenRpcPubSub do
55
66 @ behaviour Phoenix.PubSub.Adapter
77 alias Realtime.GenRpc
8+ alias Realtime.GenRpcPubSub.Worker
9+ alias Realtime.Nodes
810 use Supervisor
911
1012 @ impl true
@@ -45,36 +47,83 @@ defmodule Realtime.GenRpcPubSub do
4547 @ impl true
4648 def broadcast ( adapter_name , topic , message , dispatcher ) do
4749 worker = worker_name ( adapter_name , self ( ) )
48- GenRpc . abcast ( Node . list ( ) , worker , forward_to_local ( topic , message , dispatcher ) , key: worker )
50+
51+ if Application . get_env ( :realtime , :regional_broadcasting , false ) do
52+ my_region = Application . get_env ( :realtime , :region )
53+ # broadcast to all other nodes in the region
54+
55+ other_nodes = for node <- Realtime.Nodes . region_nodes ( my_region ) , node != node ( ) , do: node
56+ GenRpc . abcast ( other_nodes , worker , Worker . forward_to_local ( topic , message , dispatcher ) , key: worker )
57+
58+ # send a message to a node in each region to forward to the rest of the region
59+ other_region_nodes = nodes_from_other_regions ( my_region , worker )
60+
61+ GenRpc . abcast ( other_region_nodes , worker , Worker . forward_to_region ( topic , message , dispatcher ) , key: worker )
62+ else
63+ GenRpc . abcast ( Node . list ( ) , worker , Worker . forward_to_local ( topic , message , dispatcher ) , key: worker )
64+ end
65+
66+ :ok
67+ end
68+
69+ defp nodes_from_other_regions ( my_region , key ) do
70+ Enum . flat_map ( Nodes . all_node_regions ( ) , fn
71+ ^ my_region ->
72+ [ ]
73+
74+ region ->
75+ case Nodes . node_from_region ( region , key ) do
76+ { :ok , node } -> [ node ]
77+ _ -> [ ]
78+ end
79+ end )
4980 end
5081
5182 @ impl true
5283 def direct_broadcast ( adapter_name , node_name , topic , message , dispatcher ) do
5384 worker = worker_name ( adapter_name , self ( ) )
54- GenRpc . abcast ( [ node_name ] , worker , forward_to_local ( topic , message , dispatcher ) , key: worker )
85+ GenRpc . abcast ( [ node_name ] , worker , Worker . forward_to_local ( topic , message , dispatcher ) , key: worker )
5586 end
56-
57- defp forward_to_local ( topic , message , dispatcher ) , do: { :ftl , topic , message , dispatcher }
5887end
5988
6089defmodule Realtime.GenRpcPubSub.Worker do
6190 @ moduledoc false
6291 use GenServer
6392
93+ def forward_to_local ( topic , message , dispatcher ) , do: { :ftl , topic , message , dispatcher }
94+ def forward_to_region ( topic , message , dispatcher ) , do: { :ftr , topic , message , dispatcher }
95+
6496 @ doc false
65- def start_link ( { pubsub , worker } ) , do: GenServer . start_link ( __MODULE__ , pubsub , name: worker )
97+ def start_link ( { pubsub , worker } ) , do: GenServer . start_link ( __MODULE__ , { pubsub , worker } , name: worker )
6698
6799 @ impl true
68- def init ( pubsub ) do
100+ def init ( { pubsub , worker } ) do
69101 Process . flag ( :message_queue_data , :off_heap )
70102 Process . flag ( :fullsweep_after , 20 )
71- { :ok , pubsub }
103+ { :ok , { pubsub , worker } }
72104 end
73105
74106 @ impl true
75- def handle_info ( { :ftl , topic , message , dispatcher } , pubsub ) do
107+ # Forward to local
108+ def handle_info ( { :ftl , topic , message , dispatcher } , { pubsub , worker } ) do
109+ Phoenix.PubSub . local_broadcast ( pubsub , topic , message , dispatcher )
110+ { :noreply , { pubsub , worker } }
111+ end
112+
113+ # Forward to the rest of the region
114+ def handle_info ( { :ftr , topic , message , dispatcher } , { pubsub , worker } ) do
115+ # Forward to local first
76116 Phoenix.PubSub . local_broadcast ( pubsub , topic , message , dispatcher )
77- { :noreply , pubsub }
117+
118+ # Then broadcast to the rest of my region
119+ my_region = Application . get_env ( :realtime , :region )
120+ other_nodes = for node <- Realtime.Nodes . region_nodes ( my_region ) , node != node ( ) , do: node
121+
122+ if other_nodes != [ ] do
123+ Realtime.GenRpc . abcast ( other_nodes , worker , forward_to_local ( topic , message , dispatcher ) , key: worker )
124+ end
125+
126+ { :noreply , { pubsub , worker } }
78127 end
79128
80129 @ impl true
0 commit comments