diff options
author | Erik Johnston <erik@matrix.org> | 2019-08-27 13:56:42 +0100 |
---|---|---|
committer | Erik Johnston <erik@matrix.org> | 2019-08-27 13:56:42 +0100 |
commit | 91caa5b4303bfa0b4604ecf95d56ae72a7074b0b (patch) | |
tree | 6a33e81d62e260945816eb785fe6eb17f70fbd43 | |
parent | Fixup comments (diff) | |
download | synapse-91caa5b4303bfa0b4604ecf95d56ae72a7074b0b.tar.xz |
Fix off by one error in SRV result shuffling
-rw-r--r-- | synapse/http/federation/srv_resolver.py | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/synapse/http/federation/srv_resolver.py b/synapse/http/federation/srv_resolver.py index c8ca3fd0e9..3fe4ffb9e5 100644 --- a/synapse/http/federation/srv_resolver.py +++ b/synapse/http/federation/srv_resolver.py @@ -66,17 +66,18 @@ def _sort_server_list(server_list): for priority in sorted(priority_map): servers = priority_map[priority] - # This algorithms follows the algorithm described in RFC2782. + # This algorithms roughly follows the algorithm described in RFC2782, + # changed to remove an off-by-one error. # - # 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) + # N.B. Weights can be zero, which means that they should be picked + # rarely. total_weight = sum(s.weight for s in servers) - while servers: - target_weight = random.randint(0, total_weight) + + # Total weight can become zero if there are only zero weight servers + # left, which we handle by just shuffling and appending to the results. + while servers and total_weight: + target_weight = random.randint(1, total_weight) for s in servers: target_weight -= s.weight @@ -88,6 +89,10 @@ def _sort_server_list(server_list): servers.remove(s) total_weight -= s.weight + if servers: + random.shuffle(servers) + results.extend(servers) + return results |