113 lines
5.8 KiB
Markdown
113 lines
5.8 KiB
Markdown
---
|
|
phase: 40-job-infrastructure
|
|
plan: "01"
|
|
subsystem: content-jobs
|
|
tags: [db-schema, services, async-jobs, live-events]
|
|
dependency_graph:
|
|
requires: []
|
|
provides:
|
|
- content_jobs DB table with queued/running/done/failed lifecycle
|
|
- contentJobStore CRUD service
|
|
- contentJobRunner async dispatcher with live events
|
|
- MAX_GENERATED_ASSET_BYTES constant (500MB)
|
|
- assets.sourceTaskId column
|
|
- LIVE_EVENT_TYPES extended with content_job.* events
|
|
affects:
|
|
- packages/db/src/schema/
|
|
- packages/shared/src/constants.ts
|
|
- server/src/services/
|
|
- server/src/attachment-types.ts
|
|
tech_stack:
|
|
added: []
|
|
patterns:
|
|
- Drizzle ORM pgTable schema with $type<> for typed status fields
|
|
- Fire-and-forget async job dispatch with void pattern
|
|
- DB write before live event publish (ordered consistency)
|
|
- renderContent stub for future renderer plug-in by jobType
|
|
key_files:
|
|
created:
|
|
- packages/db/src/schema/content_jobs.ts
|
|
- server/src/services/content-job-store.ts
|
|
- server/src/services/content-job-runner.ts
|
|
- packages/db/src/migrations/0046_tense_randall.sql
|
|
modified:
|
|
- packages/db/src/schema/assets.ts
|
|
- packages/db/src/schema/index.ts
|
|
- packages/shared/src/constants.ts
|
|
- server/src/attachment-types.ts
|
|
- server/src/services/index.ts
|
|
decisions:
|
|
- content_jobs.resultAssetId has no FK to assets — populated post-creation, circular FK avoided
|
|
- assets.sourceTaskId is nullable text with no FK — task IDs are string identifiers, not UUIDs
|
|
- renderContent is a stub returning placeholder.txt — phases 41-45 add real renderers keyed by jobType
|
|
- Migration applied via drizzle-kit generate from worktree dist/ (main repo has pre-existing duplicate migration files)
|
|
metrics:
|
|
duration: "~10 minutes"
|
|
completed: "2026-04-04"
|
|
tasks_completed: 2
|
|
tasks_total: 2
|
|
files_created: 4
|
|
files_modified: 5
|
|
---
|
|
|
|
# Phase 40 Plan 01: Schema, constants, and services for content jobs Summary
|
|
|
|
**One-liner:** content_jobs table + async job runner with store/runner services using fire-and-forget dispatch and ordered DB-before-event lifecycle.
|
|
|
|
## What Was Built
|
|
|
|
The foundational data model and async execution engine for v1.7 content generation. Phase 40 Plan 01 establishes:
|
|
|
|
1. **DB schema** (`content_jobs` table) with full lifecycle columns and two composite indexes for efficient querying by company+status and company+createdAt.
|
|
2. **assets.sourceTaskId** — nullable text column allowing generated assets to be traced back to their originating conversation task.
|
|
3. **LIVE_EVENT_TYPES** — extended with `content_job.queued`, `content_job.running`, `content_job.done`, `content_job.failed` for real-time job progress.
|
|
4. **MAX_GENERATED_ASSET_BYTES** — 500MB constant (vs 10MB upload limit) for generated/namespace storage, configurable via `PAPERCLIP_GENERATED_ASSET_MAX_BYTES`.
|
|
5. **contentJobStore** — CRUD service with create/getById/listByCompany/transition operations against the content_jobs table.
|
|
6. **contentJobRunner** — async fire-and-forget dispatcher that transitions jobs through running→done/failed, stores generated assets with sourceTaskId, and publishes live events after each DB write.
|
|
|
|
## Tasks Completed
|
|
|
|
| Task | Name | Commit | Files |
|
|
|------|------|--------|-------|
|
|
| 1 | Schema, constants, and migrations | 8bf4bd91 | content_jobs.ts, assets.ts, index.ts, constants.ts, attachment-types.ts, migration 0046 |
|
|
| 2 | contentJobStore and contentJobRunner | b359fec9 | content-job-store.ts, content-job-runner.ts, services/index.ts |
|
|
|
|
## Verification
|
|
|
|
- `pnpm tsc --noEmit --project packages/db/tsconfig.json` — PASS
|
|
- `pnpm tsc --noEmit --project packages/shared/tsconfig.json` — PASS
|
|
- `pnpm tsc --noEmit --project server/tsconfig.json` — PASS
|
|
- Migration file `0046_tense_randall.sql` generated with correct DDL
|
|
|
|
## Deviations from Plan
|
|
|
|
### Migration apply limitation (pre-existing blocker, out of scope)
|
|
|
|
**Found during:** Task 1
|
|
|
|
**Issue:** The main repo (`/opt/nexus`) has pre-existing duplicate migration files (`0047_nebulous_klaw.sql` and `0047_overjoyed_groot.sql`, `0048_add_chat_messages_updated_at.sql` and `0048_flashy_marrow.sql`) from parallel agent work. The `check:migrations` script prevents both `db:generate` and `db:migrate` in the main repo.
|
|
|
|
**Impact:** Migration `0046_tense_randall.sql` was generated successfully from the worktree's clean migration state but could not be applied via `pnpm db:migrate`.
|
|
|
|
**Resolution:** Migration will be applied when the worktree is merged and the duplicate migration numbering conflict is resolved. The SQL is correct and ready for execution. This is a pre-existing issue deferred to `.planning/deferred-items.md`.
|
|
|
|
**Migration file content verified:** Creates `content_jobs` table, adds `source_task_id` to `assets`, creates both compound indexes, adds FK to companies.
|
|
|
|
### Known Stubs
|
|
|
|
**renderContent stub** in `server/src/services/content-job-runner.ts`:
|
|
- Returns `{ filename: "placeholder.txt", contentType: "text/plain", buffer: Buffer.from("placeholder output") }` for all jobTypes
|
|
- This is intentional — the plan specifies this as a stub for phases 41-45 to fill in real renderers keyed by jobType
|
|
- Does NOT prevent the plan's goal (job infrastructure) from being achieved
|
|
|
|
## Self-Check: PASSED
|
|
|
|
Files verified to exist:
|
|
- `/opt/nexus/.claude/worktrees/agent-ac2e6085/packages/db/src/schema/content_jobs.ts` — FOUND
|
|
- `/opt/nexus/.claude/worktrees/agent-ac2e6085/server/src/services/content-job-store.ts` — FOUND
|
|
- `/opt/nexus/.claude/worktrees/agent-ac2e6085/server/src/services/content-job-runner.ts` — FOUND
|
|
- `/opt/nexus/.claude/worktrees/agent-ac2e6085/packages/db/src/migrations/0046_tense_randall.sql` — FOUND
|
|
|
|
Commits verified:
|
|
- `8bf4bd91` — FOUND (feat(40-01): schema, constants, and migrations for content jobs)
|
|
- `b359fec9` — FOUND (feat(40-01): contentJobStore and contentJobRunner services)
|