# 6. Event-based XBlock Rendering for External Grader Integration#
Status#
Provisional 2025-03-18
Implemented by: openedx/edx-platform#34888
Context#
The Open edX platform currently renders XBlocks with scoring data through synchronous HTTP callback requests from XQueue. This approach introduces several challenges:
Tight Coupling: The XQueue service must know the specific callback URL for each XBlock, creating unnecessary coupling between services.
HTTP Dependency: Reliance on synchronous HTTP requests introduces potential points of failure, latency issues, and timeouts.
Complex State Management: Managing state across multiple services via HTTP callbacks makes tracking submission progress more difficult.
Limited Scalability: The callback model doesn’t scale well in distributed environments, particularly with high loads.
Consistency Issues: HTTP failures can lead to discrepancies between the actual submission state and what’s displayed to learners.
This ADR addresses the final component of the XQueue migration initiative, building upon previous decisions that established
Decision#
We will implement an event-driven approach to render XBlocks with scoring data, replacing the traditional HTTP callback mechanism. This involves:
Event Handler Implementation:
Create a specialized event handler in the LMS to process the
EXTERNAL_GRADER_SCORE_SUBMITTEDsignal.Implement a signal handler in
handlers.pyto react to score submission events.Develop a dedicated XBlock loader in
score_render.pythat can render blocks without HTTP requests.
Integration with Existing Event Structure:
Leverage the previously defined
EXTERNAL_GRADER_SCORE_SUBMITTEDsignal from edx-submissions.Ensure propagation of the
queue_keyidentifier across the submission pipeline.Register appropriate URL handlers in the LMS for submission processing.
Asynchronous Rendering Flow:
When a score is set via the edx-submissions service, emit the
EXTERNAL_GRADER_SCORE_SUBMITTEDevent.The LMS event handler receives this event and initiates the XBlock rendering process.
The XBlock loader retrieves the necessary scoring data and updates the XBlock state.
The rendered XBlock is presented to the learner with updated scoring information.
Technical Components:
# Signal handler registration
@receiver(EXTERNAL_GRADER_SCORE_SUBMITTED)
def handle_external_grader_score(sender, **kwargs):
"""
Handle the external grader score submitted event.
Retrieves the scoring data and initiates XBlock rendering.
"""
score_data = kwargs.get('score_data')
# Process score data and render XBlock
render_xblock_with_score(score_data)
def render_xblock_with_score(score_data):
"""
Render an XBlock with the provided scoring data.
This replaces the traditional HTTP callback approach.
"""
# Retrieve the XBlock
xblock = get_xblock_by_module_id(score_data.module_id)
# Update XBlock state with score information
update_xblock_state(xblock, score_data)
# Trigger rendering process
render_xblock(xblock)
Consequences#
Positive:#
Architectural Improvements:
Elimination of synchronous HTTP dependencies between services to render score.
More robust error handling.
Improved system observability through event tracking.
Performance Benefits:
Reduced latency in score rendering and feedback presentation.
Better scalability in high-load environments.
More efficient resource utilization without blocking HTTP calls.
User Experience:
More consistent experience for learners with faster score updates.
Reduced likelihood of rendering failures affecting feedback display.
Improved reliability in handling scoring events.
Negative:#
Implementation Complexity:
Requires additional signal handling infrastructure.
More complex testing scenarios to validate event-based flows.
Operational Considerations:
Requires monitoring of event emission and consumption.
Debugging complexity increases with asynchronous flows.
Need for proper error recovery mechanisms if events are missed.
Transition Challenges:
Temporary increased system complexity during migration period.
Careful coordination needed between edx-submissions and LMS changes.
Neutral:#
Documentation Needs:
Updated developer documentation for event-based architecture.
Event schema documentation for future integrations.
References#
Pull Requests:
Initial Event Definition: openedx/edx-submissions#283
ExternalGraderDetail Implementation: openedx/edx-submissions#283
SubmissionFile Implementation: openedx/edx-submissions#286
XQueueViewSet Implementation: openedx/edx-submissions#287
Event Emission Implementation: openedx/edx-submissions#292
Related Documentation:
XQueue Migration Plan: openedx/edx-platform#36258
Django Signals Documentation: https://docs.djangoproject.com/en/stable/topics/signals/
Open edX Events Framework: openedx/openedx-events
Architecture Guidelines:
Open edX Architecture Guidelines: https://openedx.atlassian.net/wiki/spaces/AC/pages/124125264/Architecture+Guidelines
OEP-19: Developer Documentation: https://open-edx-proposals.readthedocs.io/en/latest/oep-0019-bp-developer-documentation.html