-
Notifications
You must be signed in to change notification settings - Fork 15
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_requestsfeature 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_GROUPSHandlers, 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_tasksmethod that adds tasks for the named groups, e.g.:Then, in the handler's
load_and_processmethod, the configured concurrent tasks may be executed as follows:ConcurrentTaskRunnerThe
ConcurrentTaskRunnerexposes arun_groupmethod that executes the tasks in the given group. It usesconcurrent.futures.ThreadPoolExecutorto submit tasks to concurrent threads.It then iterates through the tasks as they complete with
as_completedadding the appropriate result metadata to the returnedresultslist.The handlers can pass the results list into another method
ConcurrentTaskRunner.handle_failed_tasksalong 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,
DashboardHandlermakes an API request to fetch enterprise course enrollments for the request user. This call can be made independently of other calls in the parentBaseLearnerPortalHandleras it only depends on theenterprise_customer_uuid.Given this,
DashboardHandlermay extend_get_concurrent_tasksto add additional task(s) to an existing group configured inBASE_CONCURRENCY_GROUPS, e.g.:Jira:
ENT-10429
Merge checklist:
./manage.py makemigrationshas been runPost merge: