-
Notifications
You must be signed in to change notification settings - Fork 13
feat: add support for concurrent API requests to external services in BFF API layer #734
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
if not self.enterprise_customer_uuid: | ||
self._enterprise_customer_uuid = self.enterprise_customer.get('uuid') | ||
|
||
# Initialize the secured algolia api keys metadata derived from enterprise catalog |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[inform] Moved outside of context.py
and into BaseLearnerPortalHandler
.
logger = logging.getLogger(__name__) | ||
|
||
|
||
MOCK_TASK_DELAY = 5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[inform] Temporary constant to use with time.sleep(MOCK_TASK_DELAY)
to simulate longer requests.
Description:
Important
Depends on openedx/edx-enterprise#2415 (for enterprise-specific waffle-based feature flags)
Adds capability to execute API requests to external services concurrently within the BFF API layer with
concurrent.futures.ThreadPoolExecutor
. Only uses the concurrent approach if theenterprise_learner_bff_concurrent_requests
feature flag exposed by the LMS/enterprise/api/v1/enterprise-learner/
API (see PR) is enabled. This feature flag may be configured to a percentage-based rollout for a specific customer.Handlers add concurrent tasks to specific, named groups within
CONCURRENCY_GROUPS
Handlers, responsible for data fetching and processing logic, may define a named group of concurrent tasks, e.g.:
Then, the handler may define a
_get_concurrent_tasks
method that adds tasks for the named groups, e.g.:Then, in the handler's
load_and_process
method, the configured concurrent tasks may be executed as follows:ConcurrentTaskRunner
The
ConcurrentTaskRunner
exposes arun_group
method that executes the tasks in the given group. It usesconcurrent.futures.ThreadPoolExecutor
to submit tasks to concurrent threads.It then iterates through the tasks as they complete with
as_completed
adding the appropriate result metadata to the returnedresults
list.The handlers can pass the results list into another method
ConcurrentTaskRunner.handle_failed_tasks
along with a callback method for how to handle the error (e.g., logging,self.add_error
).How do handler subclasses add tasks to an existing group from a parent handler class?
As an example,
DashboardHandler
makes an API request to fetch enterprise course enrollments for the request user. This call can be made independently of other calls in the parentBaseLearnerPortalHandler
as it only depends on theenterprise_customer_uuid
.Given this,
DashboardHandler
may extend_get_concurrent_tasks
to add additional task(s) to an existing group configured inBASE_CONCURRENCY_GROUPS
, e.g.:Jira:
ENT-10429
Merge checklist:
./manage.py makemigrations
has been runPost merge: