Skip to main content

get_reapable

Function get_reapable 

Source
pub async fn get_reapable(
    conn: &mut PgConnection,
) -> ModelResult<Vec<ReapableUpload>>
Expand description

Answer uploads past their origin’s retention window that no submission was ever made from, oldest first, at most REAP_BATCH_LIMIT of them.

FROM exercise_answer_uploads is the safety property of this whole feature, not an optimisation: file_uploads also holds CMS media, organization images and certificates, none of which are bound here, so the host cannot tell whether one is still needed. Widening this query to file_uploads would silently destroy course media. Never do it.

Files referenced only from a spec blob (e.g. ones a teacher attaches in the CMS editor) must be uploaded through the POST /api/v0/files/{exercise_service_slug} route instead: the host never inspects spec contents, so such a file never gets an exercise_task_submission_files row and a binding here would have it reaped a week later. Their lifecycle is crate::exercise_spec_uploads’, which reclaims them against declarations rather than submissions.

Progress is tracked by file_uploads.deleted_at, not by the binding’s: the binding is retired first and the object removed afterwards, so a row whose object delete failed still has a live file_uploads row and comes back on the next run. Filtering on u.deleted_at IS NULL instead would make every transient object-store error orphan its object permanently.