From 35e00d570b26cfd7b36e1d0f198c613ad9247b2c Mon Sep 17 00:00:00 2001 From: ilee2u Date: Fri, 29 Sep 2023 15:21:58 -0400 Subject: [PATCH 1/2] docs: downstream effect events corrected --- .../0004-downstream-effect-events.rst | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/docs/decisions/0004-downstream-effect-events.rst b/docs/decisions/0004-downstream-effect-events.rst index 522372a8..5d4f3756 100644 --- a/docs/decisions/0004-downstream-effect-events.rst +++ b/docs/decisions/0004-downstream-effect-events.rst @@ -15,12 +15,13 @@ which edx-proctoring can call directly since it is a plugin that is installed di Decision -------- -We've decided to use an event driven architecture because unlike the legacy system (edx-porctoring), edx-exams is an independent service. +We've decided to use an event driven architecture because unlike the legacy system (edx-proctoring), edx-exams is an independent service. As such, we plan to use the event bus to send info to edx-platform services without needing a response as one would in a REST framework. -Below are lists of downstream effects of exam submission and review that we will or will not be translating into events in edx-exams as part of this decision. +Below are lists of downstream effects of exam submission and review that we will or will not be impementing as downstream effects that will be +triggered by events emitted in edx-exams per this decision. -Downstream effects to be implemented as events: +Downstream effects to be implemented: *********************************************** * Grades Override - A python API call to the grades app to generate a grade override when an exam attempt is rejected. @@ -56,21 +57,40 @@ Downstream effects that are not being implemented as part of this decision: * We will implement this later since we do not believe this to be an essential feature. -For easier visualization, here are all of the events we plan to implement, described from end to end: +For easier visualization, here are all of the downstream effects we plan to port, described from end to end: + +Downstream effects to be implemented as part of this decision: +************************************************************** + ====================================== ================================================================================================ ============================================ =============================================== ========================================================================= ====================================================================================== + Downstream Effect Context in which it's triggered Consumer Location Functions Called General Context for Calls Expected Result + ====================================== ================================================================================================ ============================================ =============================================== ========================================================================= ====================================================================================== + Grades Override When an exam attempt is rejected. lms/djangoapps/grades/signals.py override_subsection_grade in api.py When we need to override a grade from any service. A grade override object is created or modified in the grades service within the LMS. + Undo Grades Override When an exam attempt is verified after previously being rejected, OR when it is deleted/reset. lms/djangoapps/grades/signals.py undo_override_subsection_grade in services.py When we need to undo a grade override from any service. A grade override object is deleted in the grades service within the LMS. + Instructor Reset Subsection When an exam attempt is deleted/reset. lms/djangoapps/instructor/signals.py reset_student_attempts in enrollments.py When we need to reset a student’s state in a subsection. A learner's state for a subsection is reset. + Instructor Mark Subsection Completed When an exam attempt is completed. lms/djangoapps/instructor/signals.py update_exam_completion_task in tasks.py When we need to mark a subsection as completed. A subsection is marked completed for a learner. + Invalidate Certificate When an exam attempt is rejected. lms/djangoapps/certificates/signals.py invalidate_certificate in services.py When we need to invalidate a learner's certificate. A certificate object's status is set to "unavailable". + Set Credit Requirement Status When exam attempt is completed. openedx/core/djangoapps/credits/signals.py set_credit_requirement_status in services.py When we need to create or modify a learner's credit requirement status. A credit requirement status object is created or modified within the LMS. + ====================================== ================================================================================================ ============================================ =============================================== ========================================================================= ====================================================================================== + +Event Triggers: +*************** +We will define the events in edx-exams such that they are emitted whenever an exam attempt is submitted, rejected, verified, errored, or reset. +After these events are emitted, they will trigger their respective chosen downstream effects. + +For easier visualization, here are all of the events we plan to implement: Events to be implemented as part of this decision: ************************************************** - ====================================== ================================================================================================ =========================================================================================== ============================================ ================================================ ========================================================================= ====================================================================================== - Event Type Production Context Data sent Consumer Location Functions Called General Context for Calls Expected Result - ====================================== ================================================================================================ =========================================================================================== ============================================ ================================================ ========================================================================= ====================================================================================== - Grades Override When an exam attempt is rejected. user_id, course_key_or_id, usage_key_or_id, earned_all, earned_graded, overrider, comment lms/djangoapps/grades/signals.py override_subsection_grade in api.py When we need to override a grade from any service. A grade override object is created or modified in the grades service within the LMS. - Invalidate Certificate When an exam attempt is rejected. user_id, course_key_or_id lms/djangoapps/certificates/signals.py invalidate_certificate in services.py When we need to invalidate a learner's certificate. A certificate object's status is set to "unavailable". - Undo Grades Override When an exam attempt is verified after previously being rejected, OR when it is deleted/reset. user_id, course_key_or_id, usage_key_or_id lms/djangoapps/grades/signals.py undo_override_subsection_grade in services.py When we need to undo a grade override from any service. A grade override object is deleted in the grades service within the LMS. - Instructor Reset Subsection When an exam attempt is deleted/reset. username, course_id, content_id, requesting_user lms/djangoapps/instructor/signals.py reset_student_attempts in enrollments.py When we need to reset a student’s state in a subsection. A learner's state for a subsection is reset. - Remove Credit Requirement Status When an exam attempt is deleted/reset. user_id, course_key_or_id, req_namespace, req_name openedx/core/djangoapps/credits/signals.py remove_credit_requirement_status in services.py When we need to remove a learner's credit requirement status. A credit requirement status object is deleted within the LMS. - Set Credit Requirement Status When an exam attempt is completed. user_id, course_key_or_id, req_namespace, req_name, status openedx/core/djangoapps/credits/signals.py set_credit_requirement_status in services.py When we need to create or modify a learner's credit requirement status. A credit requirement status object is created or modified within the LMS. - Instructor Mark Subsection Completed When an exam attempt is completed. username, content_id lms/djangoapps/instructor/signals.py update_exam_completion_task in tasks.py When we need to mark a subsection as completed. A subsection is marked completed for a learner. - ====================================== ================================================================================================ =========================================================================================== ============================================ ================================================ ========================================================================= ====================================================================================== + ======================== ======================================== ======================================================================== + Event Type Context in which event is produced Downstream effects triggered + ======================== ======================================== ======================================================================== + Exam Attempt Submitted When an exam attempt is submitted. Instructor Mark Subsection Completed, Set Credit Requirement Status + Exam Attempt Rejected When an exam attempt is rejected. Set Credit Requirement Status, Grades Override, Invalidate Certificate + Exam Attempt Verified When an exam attempt is verified. Set Credit Requirement Status, Undo Grades Override + Exam Attempt Errored When exam attempt errors out. Set Credit Requirement Status + Exam Attempt Reset When an exam attempt is deleted/reset. Instructor Reset Subsection, Reset Credit Requirement Status + ======================== ======================================== ======================================================================== + Consequences ------------ From 6feb80f6fb0cfa9e235daa2f8e74e5a2bdbca523 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Mon, 2 Oct 2023 10:24:17 -0400 Subject: [PATCH 2/2] docs: improved ADR --- .../0004-downstream-effect-events.rst | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/docs/decisions/0004-downstream-effect-events.rst b/docs/decisions/0004-downstream-effect-events.rst index 5d4f3756..03d6a9cb 100644 --- a/docs/decisions/0004-downstream-effect-events.rst +++ b/docs/decisions/0004-downstream-effect-events.rst @@ -18,11 +18,10 @@ Decision We've decided to use an event driven architecture because unlike the legacy system (edx-proctoring), edx-exams is an independent service. As such, we plan to use the event bus to send info to edx-platform services without needing a response as one would in a REST framework. -Below are lists of downstream effects of exam submission and review that we will or will not be impementing as downstream effects that will be -triggered by events emitted in edx-exams per this decision. +Below are lists of expected downstream effects of exam submission and review. We have decided to implement some downstream effects and not others; these decisions are enumerated below. Those that will be implemented will be triggered by events emitted by the edx-exams service, as described in this decision. -Downstream effects to be implemented: -*********************************************** +Downstream effects to be implemented as part of this decision: +************************************************************** * Grades Override - A python API call to the grades app to generate a grade override when an exam attempt is rejected. @@ -30,7 +29,7 @@ Downstream effects to be implemented: * Instructor Delete Attempt - A python API call to the instructor app to delete an exam attempt. - * Instructor Complete Attempt - A python API call to the instructor app to mark an exam subsection as completed. + * Mark Exam Subsection Completed - A python API call to a function in the instructor app that causes the exam subsection to be marked as completed. * Invalidate Certificate - A python API call to the certificates app to invalidate a leaner’s edx certificate for a course. @@ -59,18 +58,19 @@ Downstream effects that are not being implemented as part of this decision: For easier visualization, here are all of the downstream effects we plan to port, described from end to end: -Downstream effects to be implemented as part of this decision: -************************************************************** - ====================================== ================================================================================================ ============================================ =============================================== ========================================================================= ====================================================================================== - Downstream Effect Context in which it's triggered Consumer Location Functions Called General Context for Calls Expected Result - ====================================== ================================================================================================ ============================================ =============================================== ========================================================================= ====================================================================================== - Grades Override When an exam attempt is rejected. lms/djangoapps/grades/signals.py override_subsection_grade in api.py When we need to override a grade from any service. A grade override object is created or modified in the grades service within the LMS. - Undo Grades Override When an exam attempt is verified after previously being rejected, OR when it is deleted/reset. lms/djangoapps/grades/signals.py undo_override_subsection_grade in services.py When we need to undo a grade override from any service. A grade override object is deleted in the grades service within the LMS. - Instructor Reset Subsection When an exam attempt is deleted/reset. lms/djangoapps/instructor/signals.py reset_student_attempts in enrollments.py When we need to reset a student’s state in a subsection. A learner's state for a subsection is reset. - Instructor Mark Subsection Completed When an exam attempt is completed. lms/djangoapps/instructor/signals.py update_exam_completion_task in tasks.py When we need to mark a subsection as completed. A subsection is marked completed for a learner. - Invalidate Certificate When an exam attempt is rejected. lms/djangoapps/certificates/signals.py invalidate_certificate in services.py When we need to invalidate a learner's certificate. A certificate object's status is set to "unavailable". - Set Credit Requirement Status When exam attempt is completed. openedx/core/djangoapps/credits/signals.py set_credit_requirement_status in services.py When we need to create or modify a learner's credit requirement status. A credit requirement status object is created or modified within the LMS. - ====================================== ================================================================================================ ============================================ =============================================== ========================================================================= ====================================================================================== +Table of downstream effects to be implemented as part of this decision: +*********************************************************************** + ====================================== ================================================================================================ ========================================================================= ====================================================================================== + Event Type Production Context General Context for Calls Expected Result + ====================================== ================================================================================================ ========================================================================= ====================================================================================== + Grades Override When an exam attempt is rejected. When we need to override a grade from any service. A grade override object is created or modified in the grades service within the LMS. + Undo Grades Override When an exam attempt is verified after previously being rejected, OR when it is deleted/reset. When we need to undo a grade override from any service. A grade override object is deleted in the grades service within the LMS. + Instructor Reset Subsection When an exam attempt is deleted/reset. When we need to reset a student’s state in a subsection. A learner's state for a subsection is reset. + Mark Exam Subsection Completed When an exam attempt is submitted. When we need to mark a subsection as completed. A subsection is marked completed for a learner. + Invalidate Certificate When an exam attempt is rejected. When we need to invalidate a learner's certificate. A certificate object's status is set to "unavailable". + Set Credit Requirement Status When exam attempt is submitted. When we need to create or modify a learner's credit requirement status. A credit requirement status object is created or modified within the LMS. + ====================================== ================================================================================================ ========================================================================= ====================================================================================== + Event Triggers: *************** @@ -79,6 +79,18 @@ After these events are emitted, they will trigger their respective chosen downst For easier visualization, here are all of the events we plan to implement: +Events Data Shape: +****************** +The event data for all of the events will be defined here: https://github.com/openedx/openedx-events/blob/main/openedx_events/learning/data.py + +ExamAttemptData: + +* student_user (UserData) +* course_key (CourseKey) +* usage_key (UsageKey) +* requesting_user (UserData) +* exam_type (str) (Can be: proctored, timed, practice, onboarding) + Events to be implemented as part of this decision: ************************************************** ======================== ======================================== ======================================================================== @@ -87,7 +99,7 @@ Events to be implemented as part of this decision: Exam Attempt Submitted When an exam attempt is submitted. Instructor Mark Subsection Completed, Set Credit Requirement Status Exam Attempt Rejected When an exam attempt is rejected. Set Credit Requirement Status, Grades Override, Invalidate Certificate Exam Attempt Verified When an exam attempt is verified. Set Credit Requirement Status, Undo Grades Override - Exam Attempt Errored When exam attempt errors out. Set Credit Requirement Status + Exam Attempt Errored When an exam attempt errors out. Set Credit Requirement Status Exam Attempt Reset When an exam attempt is deleted/reset. Instructor Reset Subsection, Reset Credit Requirement Status ======================== ======================================== ========================================================================