docs: add failure journal + uploaded_on features to goal artifacts
This commit is contained in:
parent
73e837c165
commit
7951f82dd5
2 changed files with 90 additions and 0 deletions
|
|
@ -201,6 +201,51 @@
|
|||
"Promotion to prod is a human action; the loop proposes, a human deploys.",
|
||||
"Record the exact cron entry, the scoped grants, and the rollback commands verbatim."
|
||||
]
|
||||
},
|
||||
{
|
||||
"feature_id": "F11",
|
||||
"title": "Persistent failure journal, bounded retry, failure API and module view",
|
||||
"acceptance_steps": [
|
||||
"Every failed (file, preset, format) task from the upload hook, manual `/generate`, and backfill appends an event to `<state-dir>/failures.jsonl`; replay derives the latest state per key across restarts and PM2 workers.",
|
||||
"Default retry policy is max 3 attempts (initial + 2 retries) with 5 min then 15 min backoff; a failed task gets at least one automatic retry when the scheduler next runs with no active backfill inside the maintenance window.",
|
||||
"Due retries run under the existing `run.lock`, process only the targeted file/preset/format pairs (bounded batch, default 50), and never trigger a full-library sweep; a manual `Run now` may ignore the window.",
|
||||
"A recovered task appends a normal `state.jsonl` completion and is marked `recovered`; an exhausted task stays `failed` with attempts, last error, and timestamps, and is not retried again.",
|
||||
"`GET /image-previews/failures?status=&limit=&offset=` returns persisted records plus file metadata (`filename_download`, `type`, `folder` when available), attempts, first/last failure, next retry, status, and error text; admin-only and read-only.",
|
||||
"The admin module shows a \"Failed previews\" table with file, preset, format, attempts, last error, next retry, and status; no toasts or user-facing notifications are added.",
|
||||
"Every failure logs a structured warn with `fileId`, `preset_key`, `format`, `attempt`, `next_retry_at`, and `error`; recovery logs at info. No file contents are logged.",
|
||||
"Journal compaction under the run lock retains unresolved rows plus the last 1,000 recovered rows, so the file cannot grow without bound.",
|
||||
"Targeted unit tests cover journal append/replay/idempotency, backoff schedule, max-attempt exhaustion, due-retry selection, and the failure endpoint response shape."
|
||||
],
|
||||
"passes": false,
|
||||
"blocked_by": [
|
||||
"F08"
|
||||
],
|
||||
"notes": [
|
||||
"Root cause: `/ops` is an in-memory 200-entry ring buffer per PM2 worker; after a long run the 17 failure details were unrecoverable.",
|
||||
"Do not reuse `/ops` for persistence; keep it as the live view. Journal is append-only for cluster safety; compact only under `run.lock`.",
|
||||
"Retry policy starts with constants; expose settings only if tuning is needed after the first real run.",
|
||||
"No user-facing notifications; logs and the read-only API/module table are the observability surface."
|
||||
]
|
||||
},
|
||||
{
|
||||
"feature_id": "F12",
|
||||
"title": "Host fix: `uploaded_on` integrity for TUS and legacy files (no Directus upgrade)",
|
||||
"acceptance_steps": [
|
||||
"Before change, record `count(*)`, `count(*) filter (where uploaded_on is null)`, and `count(*) filter (where created_on is null)` for `directus_files`; confirm the legacy null block explains the file-library ordering.",
|
||||
"In a transaction after a table backup, run `update directus_files set uploaded_on = coalesce(created_on, now()) where uploaded_on is null;` and verify only `uploaded_on` changed (`modified_on`/`modified_by` unchanged, no new activity/revisions).",
|
||||
"Set the column default to `(now() at time zone 'utc')` when absent, so future TUS inserts that omit `uploaded_on` receive a date.",
|
||||
"Upload one test file with `TUS_ENABLED=true`; confirm `uploaded_on` is non-null, `tus_id`/`tus_data` are null after finish, and the file appears at the top of the unfiltered folder with `-uploaded_on`.",
|
||||
"Keep `TUS_ENABLED=true`; no Directus upgrade and no extension code change required for this fix.",
|
||||
"Document latent 11.17.4 TUS defects not changed here: client-declared `type`/`filesize`, and stale `tus_id` placeholders hidden from `/files` if finish/cleanup fails."
|
||||
],
|
||||
"passes": false,
|
||||
"blocked_by": [],
|
||||
"notes": [
|
||||
"Source: v11.17.4 `api/src/services/tus/{data-store,server}.ts` omits `uploaded_on`; only `/files` (`FilesService.uploadOne`) sets it. Upstream #28042 fixed in 12.4.0, not backported to 11.x.",
|
||||
"Raw SQL is the only way to avoid bumping `modified_on`/`modified_by`; `ItemsService.updateOne` always runs payload specials even with `emitEvents:false`.",
|
||||
"TUS row insert omits `uploaded_on` entirely, so a DB default applies to future inserts. `now() at time zone 'utc'` matches Directus's UTC writes for the tz-less timestamp column.",
|
||||
"This is host data remediation, not extension code; keep it separate from the preview warmer."
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue