Repository navigation
Closed
Labels
DEV: backendP0 - criticalPriority: Release blocker or regressionPriority: Release blocker or regression
Description
Overview
This task involves adding core functionality for two key methods within a Backend abstract class:
connect: Establishes a connection to our external backend service.make_request: Sends requests to the connected service and handles the response accordingly.
Description and outcomes
-
Locate the
BackendandBackendResponseclasses. They reside incontentcuration/automation/utils/appnexus/base.py. -
Define variables:
base_url: Store the specific backend instance's base url.connect_endpoint: Use this path to check backend availability.
-
Sessions
- Sessions are used to construct requests in the
Backendclass - One of the biggest benefits to using sessions is the ability to reuse the same TCP connection for multiple requests on the same host.
- Sessions could present connectivity challenges if not handled correctly (for example stale connections). One way to ensure that connections are reliable is to implement a mechanism that sets the maximum connection age for sessions, ensuring they are only reusable for specific periods of time, after which they are recycled.
- Below are steps on how a custom session class with maximum connection age capabilities could be implemented.
- Create a class named
SessionWithMaxConnectionAgethat extendsrequests.Sessionincontentcuration/automation/utils/appnexus/base.py - In its constructor, accept an
ageargument for dynamic assignment of the maximum connection age. It has a default time of10s. - Within
__init__, declare and initialize a variablelast_usedwith the current time, to keep track of when the session was last used. - Override
request()and implement the logic below;- If the
current_time - last_used > age, close any open connections and reinitialize session - Set the
last_usedvariable to the current time. - Return the response, by calling
super().request(...) - Usage:
# Initializes a session with a maximum connection age of 60 seconds this.session = SessionWithMaxConnectionAge(60) - If the
- Create a class named
- Sessions are used to construct requests in the
-
Initialization
Backend- In the constructor, accept a
url_prefixargument for dynamic assignment of url prefixes during instantiation(eg, version) - Within
__init__, declare and initialize asessionvariable (of typeSessionWithMaxConnectionAge()) that will be used to make requests.
- In the constructor, accept a
BackendResponse- In the constructor, accept
kwargs - Within
__init__, dynamically set the class attributes usingkwargs
- In the constructor, accept
-
Construct full path
- Create a private method named
_construct_full_url. - This method should combine
base_url,url_prefix, andpathin that order, removing any trailing slashes beforehand.
base_url = 'http://localhost:8000' url_prefix = '/v1' path = '/embed-topics' full_url = _construct_full_url(base_url, url_prefix, path) print(full_url) # http://localhost:8000/v1/embed-topics
- Create a private method named
-
Connect to the backend
- Attempt to make a connection in the
connectmethod using the definedsessionvariable, utilizing both theconnect_endpointand_construct_full_urlas needed. - Ensure proper error handling based on the list of exceptions supported by the requests python package. Also, you can use this
connectmethod as inspiration.- Recycle the
sessionwhenRequestException, orConnectionErrorare initially encountered and retry the request, else raise an exception.
- Recycle the
- Attempt to make a connection in the
-
Make requests
- The
make_requestmethod should use thesession,connect_endpoint,_construct_full_url, and the providedrequestobject to make requests to the backend. - The
requestobject carries information likepath,method,headers,params, andbody, essential for invokingsession.request(). - Extract the JSON from the response above and use it to create the
BackendResponseobject, which is then returned. - Ensure proper error handling based on the list of exceptions supported by the requests python package. Also, you can use this
requestmethod as inspiration.- Recycle the
sessionwhenRequestException, orConnectionErrorare initially encountered and retry the request, else raise an exception.
- Recycle the
- The
-
Error handling
- The
requestspackage raises these exceptions, that can be categorized as below;- Connection related
RequestExceptionConnectionError
- Timeout related
Timeout
- HTTP related
HTTPErrorTooManyRedirects
- URL related
URLRequired
- Response related
JSONDecodeError
- Connection related
- Implement the error handling based on the categorizations above
- For each category, create a new exception class descriptive of the category. Add them to
contentcuration/automation/utils/appnexus/base.py - Raise the created exception classes for each category
- Add error logging for each raised exception
- The
Acceptance Criteria
- Initialization
- The
Backendclass constructor accepts aurl_prefixargument for dynamic assignment of url prefixes during instantiation. - A
sessionvariable of typeSessionWithMaxConnectionAgeis declared within theBackendclass constructor. - The
BackendResponseclass constructor accepts thekwargsargument. - A private
_construct_full_urlmethod in theBackendclass constructs the full url by combiningbase_url,url_prefix, andpath.
- The
- Connect to the backend:
- The
connectmethod uses thesessionvariable and_construct_full_urlto attempt a connection to the backend using theconnect_endpoint. - Appropriate error handling is implemented based on the supported exceptions.
- The
- Make requests
- The
make_requestmethod uses thesessionvariable and_construct_full_urlto make requests to the backend using the specifiedrequestobject. - The method returns a
BackendResponseobject constructed from the JSON response of thesession.request()call. - Appropriate error handling is implemented based on the supported exceptions.
- The
- The
BackendResponseclass constructor accepts keyword arguments and dynamically sets corresponding attributes. - Tests are written to verify correctness of added code
Assumptions and Dependencies
bodyfrom therequestobject is of typeJSON, thus should be handled appropriately.- Whereas some variable and method names already exist in the code, others are presented as suggestions. Feel free to adapt these names as necessary, for clarity.
Scope
The scope of this task is limited to;
- Implementing the core functionality of the
connectandmake_requestmethods
Accessibility Requirements
NA
Resources
requestsNetworkClientclass
Metadata
Metadata
Assignees
Labels
DEV: backendP0 - criticalPriority: Release blocker or regressionPriority: Release blocker or regression
Activity
[-][WIP - DO NOT ASSIGN]: Implement the core functionality for the `connect` and `make_request` methods of the `Backend` abstract class.[/-][+]Implement the core functionality for the `connect` and `make_request` methods of the `Backend` abstract class.[/+]bjester commentedon Mar 12, 2024
There's a
search-recommendationsbranch which this can be targeted againstAlexVelezLl commentedon May 16, 2024
Implemented in #4494