From 1f9df1cc7ba7027aef3a38d01909a928ecf2a8c5 Mon Sep 17 00:00:00 2001
From: Erik Johnston <erik@matrix.org>
Date: Tue, 20 Aug 2019 11:49:44 +0100
Subject: Fixup _sort_server_list to be slightly more efficient

Also document that we are using the algorithm described in RFC2782 and
ensure we handle zero weight correctly.
---
 synapse/http/federation/srv_resolver.py | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

(limited to 'synapse/http')

diff --git a/synapse/http/federation/srv_resolver.py b/synapse/http/federation/srv_resolver.py
index bbda0a23f4..110b112e85 100644
--- a/synapse/http/federation/srv_resolver.py
+++ b/synapse/http/federation/srv_resolver.py
@@ -94,10 +94,18 @@ def _sort_server_list(server_list):
 
     results = []
     for priority in sorted(priority_map):
-        servers = priority_map.pop(priority)
+        servers = priority_map[priority]
 
+        # This algorithms follows the algorithm described in RFC2782.
+        #
+        # N.B. Weights can be zero, which means that you should pick that server
+        # last *or* that its the only server in this priority.
+
+        # We sort to ensure zero weighted items are first.
+        servers.sort(key=lambda s: s.weight)
+
+        total_weight = sum(s.weight for s in servers)
         while servers:
-            total_weight = sum(s.weight for s in servers)
             target_weight = random.randint(0, total_weight)
 
             for s in servers:
@@ -108,6 +116,7 @@ def _sort_server_list(server_list):
 
             results.append(s)
             servers.remove(s)
+            total_weight -= s.weight
 
     return results
 
-- 
cgit 1.5.1