Background
PR #1259 introduces the JobLog child table for per-job log persistence. Marks the legacy jobs_job.logs JSONB column as deprecated and leaves it in place as a read-only fallback for jobs created before the table existed.
Job.logs should not be removed yet — older jobs still surface their logs in the UI through the legacy fallback in serialize_job_logs. Removing the column outright would erase pre-migration job logs from the UI.
Approach
Two-step removal once #1259 has soaked:
- Backfill existing
jobs_job.logs.{stdout, stderr} entries into JobLog rows. One-off Django management command (or data migration), batched, idempotent. Each legacy stdout line becomes one JobLog row with level parsed from the [ts] LEVEL ... prefix where present, raw line otherwise. created_at parsed from the line's prefix when available, falling back to the Job.created_at of the parent.
- Drop the column. Schema migration removing
Job.logs SchemaField + the JobLogs Pydantic class. After this lands, serialize_job_logs collapses to the JobLog-only path and _legacy_logs_shape goes away.
Acceptance
Blocked by
Background
PR #1259 introduces the
JobLogchild table for per-job log persistence. Marks the legacyjobs_job.logsJSONB column as deprecated and leaves it in place as a read-only fallback for jobs created before the table existed.Job.logsshould not be removed yet — older jobs still surface their logs in the UI through the legacy fallback inserialize_job_logs. Removing the column outright would erase pre-migration job logs from the UI.Approach
Two-step removal once #1259 has soaked:
jobs_job.logs.{stdout, stderr}entries intoJobLogrows. One-off Django management command (or data migration), batched, idempotent. Each legacy stdout line becomes oneJobLogrow withlevelparsed from the[ts] LEVEL ...prefix where present, raw line otherwise.created_atparsed from the line's prefix when available, falling back to theJob.created_atof the parent.Job.logsSchemaField + theJobLogsPydantic class. After this lands,serialize_job_logscollapses to the JobLog-only path and_legacy_logs_shapegoes away.Acceptance
JobLogrows. Idempotent — running twice does not duplicate rows.Job.logs(separate, ships after the backfill is verified in production).serialize_job_logsand friends inami/jobs/models.pysimplified — drop the legacy fallback branch.Blocked by