Skip to main content

get_reapable

Function get_reapable 

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

Uploads older than seven days that no live spec and no page-history version references, oldest first, at most REAP_BATCH_LIMIT of them.

Seven days is generous on purpose: the window has to cover the gap between uploading a file and saving the page that references it, which is a teacher’s editing session and can span days.

FROM exercise_spec_uploads is the safety property of this whole feature, not an optimisation: file_uploads also holds CMS media, organization images, certificates and answer files, none of which are recorded 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.

The declares_spec_files gate is the second half of that safety. A service that does not declare what its specs reference gives the host no evidence at all that a file is unused, so none of its uploads are ever considered — the flag exists precisely so services written before the declarations do not lose files. The playground is exempt because it has no specs and no exercise service behind its reserved slug: what it uploads is throwaway by construction.

Both reference tables are consulted, and the history one is why this reaper collects less than it looks like it should: a restore has to be able to bring back a version whose specs name a file, so a file that ever reached a saved spec stays out of reach for as long as its history is kept. What is left to collect is uploads that never made it into a save — a file the teacher replaced before saving, or an editing session that was closed.

Progress is tracked by file_uploads.deleted_at, not by this table’s: the upload 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.