From a4d61a11adabb6135fa9071759270c13dd2ad33f Mon Sep 17 00:00:00 2001 From: Blaine Jester Date: Fri, 17 Nov 2023 09:28:15 -0800 Subject: [PATCH] There can be more than one network location for an instance --- .../test/utils/test_content_request.py | 21 +++++++++++++++++++ kolibri/core/content/utils/content_request.py | 20 ++++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/kolibri/core/content/test/utils/test_content_request.py b/kolibri/core/content/test/utils/test_content_request.py index 3335f9b7a21..bdcee22447d 100644 --- a/kolibri/core/content/test/utils/test_content_request.py +++ b/kolibri/core/content/test/utils/test_content_request.py @@ -44,6 +44,8 @@ def _facility(dataset_id=None): class BaseTestCase(TestCase): + multi_db = True + def _create_sync_and_network_location( self, sync_overrides=None, location_overrides=None ): @@ -642,6 +644,25 @@ def test_multiple_peers__version_filter(self): self.assertEqual(peers[0].id, network_location1.id) self.assertEqual(peers[1].id, network_location2.id) + def test_multiple_locations__same_instance_id(self): + dynamic_location = self._create_network_location( + connection_status=ConnectionStatus.Unknown, + ) + static_location = self._create_network_location( + location_type="static", + instance_id=dynamic_location.instance_id, + ) + self.assertEqual(dynamic_location.instance_id, static_location.instance_id) + + instance = PreferredDevices( + instance_ids=[ + dynamic_location.instance_id, + ], + ) + peers = list(instance) + self.assertEqual(len(peers), 1) + self.assertEqual(peers[0].id, static_location.id) + class PreferredDevicesWithClientTestCase(BaseTestCase): def setUp(self): diff --git a/kolibri/core/content/utils/content_request.py b/kolibri/core/content/utils/content_request.py index 89a7de7714d..c250dbffb95 100644 --- a/kolibri/core/content/utils/content_request.py +++ b/kolibri/core/content/utils/content_request.py @@ -246,11 +246,23 @@ def _get_and_validate_peer(self, instance_id): :return: The NetworkLocation object, or None if it is not available or does not match the validation conditions """ - try: - peer = NetworkLocation.objects.get( - instance_id=_uuid_to_hex(instance_id), **self._filters + peer = ( + NetworkLocation.objects.annotate( + okay=Case( + When( + connection_status=ConnectionStatus.Okay, + then=Value(True), + ), + default=Value(False), + output_field=BooleanField(), + ), ) - except NetworkLocation.DoesNotExist: + .order_by("-okay") + .filter(instance_id=_uuid_to_hex(instance_id), **self._filters) + .first() + ) + + if not peer: return None # if we're on a metered connection, we only want to download from local peers