Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions contentcuration/automation/utils/appnexus/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,35 @@ def create_backend(self) -> Backend:
pass


class CompositeBackend:
def __init__(self, backend, prefixes):
self.backend = backend
self.prefixes = prefixes
self._connected = False

def connect(self, **kwargs):
"""
Loops through a list of prefixes in order to establish
which backend is available to connect.

"""
for prefix in self.prefixes:
self.backend.url_prefix = prefix
if self.backend.connect():
self._connected = True
return True
raise AssertionError(
f"Could not connect to any backend in list: {self.prefixes}"
)

def make_request(self, request):
if self._connected:
return self.backend.make_request(request)
else:
self.connect()
return self.backend.make_request(request)


class Adapter:
"""
Base class for adapters that interact with a backend interface.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from automation.models import RecommendationsCache
from automation.utils.appnexus import errors
from automation.utils.appnexus.base import BackendResponse
from automation.utils.appnexus.base import CompositeBackend
from django.test import TestCase
from kolibri_public.models import ContentNode as PublicContentNode
from mock import MagicMock
Expand Down Expand Up @@ -550,6 +551,8 @@ def test_prepare_url_with_none(self):

@patch("contentcuration.utils.recommendations.settings")
def test_create_backend_with_url_no_scheme(self, mock_settings):
mock_settings.SITE_ID = "production"
mock_settings.PRODUCTION_SITE_ID = "production"
mock_settings.CURRICULUM_AUTOMATION_API_URL = "api.example.com"
backend = self.factory.create_backend()

Expand All @@ -559,6 +562,8 @@ def test_create_backend_with_url_no_scheme(self, mock_settings):

@patch("contentcuration.utils.recommendations.settings")
def test_create_backend_with_url_with_scheme(self, mock_settings):
mock_settings.SITE_ID = "production"
mock_settings.PRODUCTION_SITE_ID = "production"
mock_settings.CURRICULUM_AUTOMATION_API_URL = "https://api.example.com"
backend = self.factory.create_backend()

Expand All @@ -568,6 +573,8 @@ def test_create_backend_with_url_with_scheme(self, mock_settings):

@patch("contentcuration.utils.recommendations.settings")
def test_create_backend_with_empty_url(self, mock_settings):
mock_settings.SITE_ID = "production"
mock_settings.PRODUCTION_SITE_ID = "production"
mock_settings.CURRICULUM_AUTOMATION_API_URL = ""
backend = self.factory.create_backend()

Expand All @@ -577,9 +584,21 @@ def test_create_backend_with_empty_url(self, mock_settings):

@patch("contentcuration.utils.recommendations.settings")
def test_create_backend_with_no_url(self, mock_settings):
mock_settings.SITE_ID = "production"
mock_settings.PRODUCTION_SITE_ID = "production"
mock_settings.CURRICULUM_AUTOMATION_API_URL = None
backend = self.factory.create_backend()

self.assertIsInstance(backend, Recommendations)
self.assertEqual(backend.base_url, None)
self.assertEqual(backend.connect_endpoint, "/connect")

@patch("contentcuration.utils.recommendations.settings")
def test_create_backend_to_unstable_url(self, mock_settings):
mock_settings.CURRICULUM_AUTOMATION_API_URL = "http://api.example.com:8080"
mock_settings.SITE_ID = "unstable"
mock_settings.PRODUCTION_SITE_ID = "production"

backend = self.factory.create_backend()
self.assertIsInstance(backend, CompositeBackend)
self.assertEqual(backend.prefixes, ["unstable", "stable"])
16 changes: 12 additions & 4 deletions contentcuration/contentcuration/utils/recommendations.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from automation.utils.appnexus.base import BackendFactory
from automation.utils.appnexus.base import BackendRequest
from automation.utils.appnexus.base import BackendResponse
from automation.utils.appnexus.base import CompositeBackend
from django.conf import settings
from django.db.models import Exists
from django.db.models import F
Expand Down Expand Up @@ -108,10 +109,17 @@ def _prepare_url(self, url):
)

def create_backend(self) -> Backend:
backend = Recommendations()
backend.base_url = self._prepare_url(settings.CURRICULUM_AUTOMATION_API_URL)
backend.connect_endpoint = "/connect"
return backend
if settings.SITE_ID == settings.PRODUCTION_SITE_ID:
backend = Recommendations()
backend.base_url = self._prepare_url(settings.CURRICULUM_AUTOMATION_API_URL)
backend.connect_endpoint = "/connect"
return backend
else:
backend = Recommendations()
backend.base_url = self._prepare_url(settings.CURRICULUM_AUTOMATION_API_URL)
backend.connect_endpoint = "/connect"

return CompositeBackend(backend, ["unstable", "stable"])


class RecommendationsAdapter(Adapter):
Expand Down