Commit 1aab71e
feat: implement XqueueViewSet with full xqueue-watcher compatibility
- Add XqueueViewSet with complete xqueue-watcher service compatibility
- Implement get_submission service for retrieving pending submissions
- Add put_result service with row-level locking (select_for_update(nowait=True)) to prevent race conditions
- Ensure concurrent xqueue-watcher instances process each submission exactly once, even under high load
- Implement standardized response format for backward compatibility
- Add session management and authentication handling for XWatcher clients
- Add comprehensive test coverage for core interactions
feat: Improve transaction handling to prevent concurrent processing and add timeout mechanism (Get Submission)
- Implemented locking to ensure submissions are processed by a single xqueue watcher.
- Added timeout mechanism for submissions stuck in 'pulled' state.
- Updated tests to cover new error scenarios and timeout handling.
feat: Optimize submission retrieval and processing flow
- Renamed variables from 'submission_record' to 'external_grader' throughout the
codebase for better consistency with model naming
- Added new 'retry' status to integrate with submission processing retry services
- Removed unused 'is_processable' method that wasn't providing any value
- Enhanced test coverage
- Add new status external grader detail migration
feat: Add event emission for external grader scores
This commit adds the EXTERNAL_GRADER_SCORE_SUBMITTED event emission to the
put_result endpoint in the XQueueViewSet. When a grader submits a result and
the score is successfully saved, the system now emits an event with all the
necessary information for the LMS to render the graded XBlock.
Key changes:
- Add queue_key field to ExternalGraderDetail model
- Include queue_key in create_external_grader_detail method
- Emit EXTERNAL_GRADER_SCORE_SUBMITTED event after successful score update
- Implement robust false to propagate error and put submission in pending queue again
- Add migration for the new queue_key field
- Add openedx-events dependency
fix: persist queue_key and expose it in ExternalGraderDetail admin
This commit fixes grading flow issues caused by the missing `queue_key`
in ExternalGraderDetail records and improves overall observability of
external grader operations inside the LMS.
- `queue_key` was never passed into `ExternalGraderDetail.create_from_uuid`,
causing the field to always be saved as `NULL`.
- As a result, the external grading pipeline was unable to deliver correct
score updates because `score_update` requires a valid queue_key.
- The LMS received the EXTERNAL_GRADER_SCORE_SUBMITTED event, but the Block could not apply the score, leaving learners stuck on a loading spinner.
- Adds `queue_key` to the external grader creation flow so it is properly persisted in the database.
- Exposes `queue_key` in ExternalGraderDetailAdmin:
- Added to `list_display`
- Added to `readonly_fields`
- Added to `search_fields`
- Added to admin form fieldsets
- Field remains read-only to avoid accidental modification
- External grader responses now carry a valid `queue_key`, allowing XBlocks
to successfully execute `handle_ajax('score_update', ...)` and update scores.
- Learners no longer see an infinite loading spinner after submission.
- Admins gain full visibility into queue_key for debugging and operational
auditing without risking accidental edits.
This enables the event-driven approach for updating XBlocks with scoring data
from the edx-submissions service, supporting the gradual migration away from
HTTP-based XQueue callbacks.1 parent d9cc3b6 commit 1aab71e
23 files changed
Lines changed: 717 additions & 545 deletions
File tree
- docs/source/decisions
- requirements
- submissions
- migrations
- tests
- views
Lines changed: 33 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
275 | 275 | | |
276 | 276 | | |
277 | 277 | | |
278 | | - | |
| 278 | + | |
279 | 279 | | |
280 | 280 | | |
281 | 281 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | | - | |
| 11 | + | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
19 | 19 | | |
20 | | - | |
| 20 | + | |
21 | 21 | | |
22 | | - | |
| 22 | + | |
23 | 23 | | |
24 | | - | |
| 24 | + | |
25 | 25 | | |
26 | | - | |
27 | | - | |
| 26 | + | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
23 | | - | |
| 23 | + | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
60 | | - | |
| 60 | + | |
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
0 commit comments