Skip to content

Figures and the bin

How a figure is attached, what an asset records and how the viewer behaves are in Figures. This page is about removing one.

DELETE /api/v1/articles/{article_id}/figures/{asset_id}?keep_asset=true|false
keep_asset Does Who
true Unlink. This article's claim on the picture and its markdown image line go. The asset row and the stored bytes are untouched; the picture stays live and findable in the library. anybody who can edit the article
false (the default) Bin. The figure line is stripped from every article that carried it, and deleted_at is stamped on the asset. moderator only

A non-moderator's request is forced to keep_asset=true at the route, whatever was sent. An article grant is a grant over what the article says, not over the library the picture lives in — the same photograph may be hanging on four other articles in a library the grantee holds no claim on.

Either way the article is snapshotted, so a restore brings the figure line back.

The 30-day bin

TRASH_DAYS = 30.

Binning removes no bytes. The asset sits at /media/trash and can be restored, which re-appends the figure line to every section it used to be in — at the end of the section, not necessarily where it was, since the section may have been rewritten meanwhile.

The one job that destroys anything

purge_trashed_media runs daily and deletes the stored object, the tag and article link rows, and the asset row itself, for any asset binned more than 30 days ago.

The bucket is not versioned. After the purge there is no way back but a database dump and whatever the object store kept, which is nothing.

Three reasons it is shaped this way:

  • Daily, not hourly. Nothing about it is urgent — the delay is the feature — and a job that removes files should run seldom enough that a bad deploy is caught before its second run.
  • One beat, always. celery-beat is a separate service with exactly one replica, precisely because two schedulers would fire this twice.
  • It is the only one. Nothing else in the beat schedule removes anything; the other two jobs retry missing embeddings and apply topic claims, and both normally find nothing.

See Background work.