🐾 fix(tasks): unsupported file types fail ingest terminally, no retries #8

Merged
r merged 1 commits from fix/unsupported-file-type-terminal into main 2026-08-03 16:28:58 +00:00
Owner

Recovers the in-flight work PR #6 deliberately excluded (it sat uncommitted on the merged fix/svg-ingest-rasterize branch), rebased onto current main.

What

An unparseable file type raised a bare ValueError, which ingest_from_daedalus handled like any transient fault: ERROR logging and Celery retries for input that can never succeed. Now:

  • parsers.py: new UnsupportedFileTypeError(ValueError) — subclasses ValueError so existing except ValueError callers are unaffected.
  • tasks.py: the task classifies it as a terminal client-data failure — WARNING (not ERROR) log, job failed with machine-readable reason: "unsupported_file_type", retry never called.
  • test_tasks.py: new IngestFromDaedalusFailureClassificationTests covering both branches (terminal vs transient-retry), with all Neo4j/S3 boundaries mocked.
  • docs/deploy.md: small related note.

Fixes applied on top of the recovered work

The original tests had never been run: IngestJob's primary key is id (not job_id), and calling the task via .run() bypasses Celery's request setup while the task persists self.request.id into the NOT NULL celery_task_id column — fixed with push_request(id=..., retries=0) in setUp.

Testing

library.tests.test_tasks + test_parsers: 22 tests, the only error being the pre-existing test_embed_item_failure which fails identically on clean main (throwaway postgres:17).

🤖 Generated with Claude Code

Recovers the in-flight work PR #6 deliberately excluded (it sat uncommitted on the merged `fix/svg-ingest-rasterize` branch), rebased onto current main. ## What An unparseable file type raised a bare `ValueError`, which `ingest_from_daedalus` handled like any transient fault: ERROR logging and Celery retries for input that can never succeed. Now: - `parsers.py`: new `UnsupportedFileTypeError(ValueError)` — subclasses `ValueError` so existing `except ValueError` callers are unaffected. - `tasks.py`: the task classifies it as a **terminal client-data failure** — WARNING (not ERROR) log, job `failed` with machine-readable `reason: "unsupported_file_type"`, `retry` never called. - `test_tasks.py`: new `IngestFromDaedalusFailureClassificationTests` covering both branches (terminal vs transient-retry), with all Neo4j/S3 boundaries mocked. - `docs/deploy.md`: small related note. ## Fixes applied on top of the recovered work The original tests had never been run: `IngestJob`'s primary key is `id` (not `job_id`), and calling the task via `.run()` bypasses Celery's request setup while the task persists `self.request.id` into the NOT NULL `celery_task_id` column — fixed with `push_request(id=..., retries=0)` in `setUp`. ## Testing `library.tests.test_tasks` + `test_parsers`: 22 tests, the only error being the pre-existing `test_embed_item_failure` which fails identically on clean main (throwaway postgres:17). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
r added 1 commit 2026-08-03 16:27:35 +00:00
Unsupported file types raised a bare ValueError from the parser, which
ingest_from_daedalus treated like any transient fault — ERROR logs and
pointless Celery retries for input that can never parse. A new
UnsupportedFileTypeError (ValueError subclass, so existing callers still
catch it) is classified in the task as a terminal client-data failure:
logged at WARNING, job marked failed with reason
"unsupported_file_type", never retried.

Recovered from uncommitted work predating PR #6 (which deliberately
excluded it); test fixes on top: IngestJob's pk is id not job_id, and
.run() needs push_request() since the task persists self.request.id
into the NOT NULL celery_task_id column.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
r merged commit 7237468e3c into main 2026-08-03 16:28:58 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: r/mnemosyne#8