Skip to content

Job retention stopped after two cleanup failures: 270k completed rows retained, and status is unbounded free text #3514

Description

@chubes4

A local install has accumulated 271,542 rows in wp_datamachine_jobs, of which 270,381 (99.6%) are completed. Retention exists (#879), so this is not a missing feature — the cleanup runs appear to have failed and then nothing retried.

Two job rows record the failure in their own status text:

status "failed - Failed to create cleanup run."          : 1
status "failed - Failed to schedule cleanup chunk jobs." : 1

Observed

jobs: 271542 | oldest: 2026-05-10 20:52:38 | newest: 2026-08-31 22:03:07
  completed                         : 270381
  pending                           :    422
  failed - packet_failure           :    345
  failed - Exception: …TypeError…   :    332
  completed_no_items                :     23
  failed - scheduler_path_lost…     :     14
  processing                        :     11
  failed - Failed to schedule cleanup chunk jobs. : 1
  failed - Failed to create cleanup run.          : 1
pending AS actions: 20

Newest row is 18 days old at time of writing, so the table is not actively growing — it grew, cleanup failed, and the backlog stayed.

Two separate problems

1. Cleanup failure is terminal and silent

"Failed to create cleanup run" and "Failed to schedule cleanup chunk jobs" each occurred once and left 270k completed rows in place. Nothing retried and nothing surfaced. A retention mechanism whose failure mode is "stop permanently, record one row, carry on" is indistinguishable from having no retention.

Worth considering: retry with backoff, and a health signal when completed-job count exceeds the configured retention horizon by some factor.

2. status is an unbounded free-text column

It currently holds entire exception messages, including absolute file paths and third-party error strings:

failed - Exception: DataMachineCode\Workspace\WorktreeContextInjector::has_owner_terminal_disposable_cleanup_signal():
  Argument #1 ($metadata) must be of type array, null given, called in /Users/…/wp-content/plugins/dat…

failed - wp-ai-client request failed: … cURL error 28: Operation timed out after 513455 milliseconds …

Consequences:

  • GROUP BY status produces one group per distinct error string rather than per state, so the column can't be aggregated or indexed usefully.
  • Every unique error text is a distinct value, defeating any status index.
  • Row size inflates for the rows that matter least.
  • Absolute filesystem paths land in a data column.

A bounded status enum plus a separate nullable error_message (or a reference into the logs table) would fix aggregation, indexing and row size together.

Why this surfaced

A consumer reported a 47-second, 1.2 GB query against this table on a file-backed storage backend, where a full scan is one file read per row. The storage engine has its own defect and is tracked separately — but 271k unpruned rows is what made it reachable, and the two cleanup failures are why they are still there.

There is also a separate TypeError visible above (has_owner_terminal_disposable_cleanup_signal() receiving null for an array parameter, 332 occurrences) which looks like its own bug and is not addressed here.


AI assistance disclosure: investigated by Anthropic's Claude running in OpenCode, directed by me. The agent profiled the query path, aggregated the job table by status, and drafted this report. I reviewed the findings before filing.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions