headless_lms_models/
offered_answers_to_peer_review_temporary.rs

1use rand::Rng;
2
3use crate::{exercise_slide_submissions::ExerciseSlideSubmission, prelude::*};
4
5/// Returns an exercise slide submission id that has been given to be reviewed by the student within the hour.
6/// Does not return submissions that no longer need peer review.
7pub async fn try_to_restore_previously_given_exercise_slide_submission(
8    conn: &mut PgConnection,
9    exercise_id: Uuid,
10    user_id: Uuid,
11    course_id: Uuid,
12) -> ModelResult<Option<ExerciseSlideSubmission>> {
13    // Sometimes clean up the table to keep the table small and fast
14    if rand::rng().random_range(0..10) == 0 {
15        delete_expired_records(&mut *conn).await?;
16    }
17
18    let res = sqlx::query!(
19        "
20SELECT exercise_slide_submission_id
21FROM offered_answers_to_peer_review_temporary
22WHERE exercise_id = $1
23  AND user_id = $2
24  AND course_id = $3
25  AND created_at > now() - '1 hour'::interval
26  ",
27        exercise_id,
28        user_id,
29        course_id,
30    )
31    .fetch_optional(&mut *conn)
32    .await?;
33
34    if let Some(res) = res {
35        // In order to return the saved submission, it needs to have a peer review queue entry and the entry must not have received enough peer reviews.
36        match crate::peer_review_queue_entries::get_by_receiving_peer_reviews_exercise_slide_submission_id(&mut *conn, res.exercise_slide_submission_id).await.optional()? { Some(peer_review_queue_entry) => {
37          if peer_review_queue_entry.received_enough_peer_reviews || peer_review_queue_entry.removed_from_queue_for_unusual_reason || peer_review_queue_entry.deleted_at.is_some() {
38            return Ok(None);
39          }
40        } _ => {
41          return Ok(None)
42        }}
43
44        let ess = crate::exercise_slide_submissions::get_by_id(
45            &mut *conn,
46            res.exercise_slide_submission_id,
47        )
48        .await?;
49
50        if ess.deleted_at.is_some() {
51            return Ok(None);
52        }
53        return Ok(Some(ess));
54    }
55    Ok(None)
56}
57
58/// Returns an exercise slide submission id that has been given to be reviewed by the student within the hour.
59pub async fn save_given_exercise_slide_submission(
60    conn: &mut PgConnection,
61    exercise_slide_submission_id: Uuid,
62    exercise_id: Uuid,
63    user_id: Uuid,
64    course_id: Uuid,
65) -> ModelResult<()> {
66    let _res = sqlx::query!(
67        "
68INSERT INTO offered_answers_to_peer_review_temporary (
69    exercise_slide_submission_id,
70    user_id,
71    course_id,
72    exercise_id
73  )
74VALUES ($1, $2, $3, $4) ON CONFLICT (user_id, exercise_id) DO
75UPDATE
76SET exercise_slide_submission_id = $1,
77    course_id = $3,
78    created_at = now()
79",
80        exercise_slide_submission_id,
81        user_id,
82        course_id,
83        exercise_id,
84    )
85    .execute(&mut *conn)
86    .await?;
87
88    Ok(())
89}
90
91/// For clearing the table after the user has given a peer review so that they can receive a new submission to be reviewed
92pub async fn delete_saved_submissions_for_user(
93    conn: &mut PgConnection,
94    exercise_id: Uuid,
95    user_id: Uuid,
96) -> ModelResult<()> {
97    info!("Deleting expired records from offered_answers_to_peer_review_temporary");
98    let _res = sqlx::query!(
99        "
100DELETE FROM offered_answers_to_peer_review_temporary
101WHERE exercise_id = $1
102  AND user_id = $2
103",
104        exercise_id,
105        user_id
106    )
107    .execute(&mut *conn)
108    .await?;
109    Ok(())
110}
111
112/// Deletes entries older than 1 hour -- for keeping the table small and fast
113async fn delete_expired_records(conn: &mut PgConnection) -> ModelResult<()> {
114    info!("Deleting expired records from offered_answers_to_peer_review_temporary");
115    let _res = sqlx::query!(
116        "
117DELETE FROM offered_answers_to_peer_review_temporary
118WHERE created_at < now() - '1 hour'::interval
119"
120    )
121    .execute(&mut *conn)
122    .await?;
123    Ok(())
124}