@@ -75,9 +75,10 @@ routes(M1, M2, Opts) ->
7575% % If we have a route that has multiple resolving nodes, check
7676% % the load distribution strategy and choose a node. Supported strategies:
7777% % <pre>
78- % % All: Return all nodes (default).
79- % % Random: Distribute load evenly across all nodes, non-deterministically.
78+ % % All: Return all nodes (default).
79+ % % Random: Distribute load evenly across all nodes, non-deterministically.
8080% % By-Base: According to the base message's hashpath.
81+ % % By-Weight: According to the node's `weight' key.
8182% % Nearest: According to the distance of the node's wallet address to the
8283% % base message's hashpath.
8384% % </pre>
@@ -246,6 +247,19 @@ choose(0, _, _, _, _) -> [];
246247choose (N , <<" Random" >>, _ , Nodes , _Opts ) ->
247248 Node = lists :nth (rand :uniform (length (Nodes )), Nodes ),
248249 [Node | choose (N - 1 , <<" Random" >>, nop , lists :delete (Node , Nodes ), _Opts )];
250+ choose (N , <<" By-Weight" >>, _ , Nodes , Opts ) ->
251+ NodesWithWeight =
252+ [
253+ { Node , hb_util :int (hb_ao :get (<<" weight" >>, Node , Opts )) }
254+ ||
255+ Node <- Nodes
256+ ],
257+ Node = hb_util :weighted_random (NodesWithWeight ),
258+ [
259+ Node
260+ |
261+ choose (N - 1 , <<" By-Weight" >>, nop , lists :delete (Node , Nodes ), Opts )
262+ ];
249263choose (N , <<" By-Base" >>, Hashpath , Nodes , Opts ) when is_binary (Hashpath ) ->
250264 choose (N , <<" By-Base" >>, binary_to_bignum (Hashpath ), Nodes , Opts );
251265choose (N , <<" By-Base" >>, HashInt , Nodes , Opts ) ->
@@ -352,6 +366,17 @@ dynamic_routes_provider_test() ->
352366 hb_http :get (Node , <<" /~r outer@1.0/routes/1/node" >>, #{})
353367 ).
354368
369+ weighted_random_strategy_test () ->
370+ Nodes =
371+ [
372+ #{ <<" host" >> => <<" 1" >>, <<" weight" >> => 1 },
373+ #{ <<" host" >> => <<" 2" >>, <<" weight" >> => 99 }
374+ ],
375+ SimRes = simulate (1000 , 1 , Nodes , <<" By-Weight" >>),
376+ [One , _ ] = simulation_distribution (SimRes , Nodes ),
377+ ? assert (One < 20 ),
378+ ? assert (One > 5 ).
379+
355380strategy_suite_test_ () ->
356381 lists :map (
357382 fun (Strategy ) ->
0 commit comments