Skip to content

feat: upgrade database-jobs with upstream performance optimizations#61

Open
pyramation wants to merge 6 commits intomainfrom
feat/database-jobs-v2
Open

feat: upgrade database-jobs with upstream performance optimizations#61
pyramation wants to merge 6 commits intomainfrom
feat/database-jobs-v2

Conversation

@pyramation
Copy link
Copy Markdown
Contributor

@pyramation pyramation commented May 1, 2026

Summary

Upgrades @pgpm/database-jobs with upstream Graphile Worker performance optimizations. The old database-jobs is preserved as database-jobs-v1 for reference.

Related: https://github.com/constructive-io/constructive-planning/issues/772

Swap:

  • database-jobs → renamed to database-jobs-v1 (legacy, v0.15.5)
  • database-jobs-v2 → renamed to database-jobs (optimized, v0.22.0)

Performance fixes in the new database-jobs:

  • queue_name default → NULL (stops creating throwaway queues — the Feat/clean cli 2 #1 bottleneck)
  • get_job rewritten with Strategy 2 (pre-computed queue set via IN subquery, ~20x improvement)
  • is_available generated column + partial covering indexes (jobs_main_index, jobs_no_queue_index)
  • Statement-level notify trigger (FOR EACH STATEMENT instead of FOR EACH ROW)

New functions: remove_job(job_key), force_unlock_workers(worker_ids)

Intentionally excluded after analysis:

  • revision column — our architecture doesn't use job replacement tracking
  • flags / forbidden_flags — worker routing handled at K8s level, not SQL level
  • Integer FK refactor — deferred; high complexity for moderate gain

Preserved: database_id, scheduled_jobs, trigger helpers, actor_id injection, app_jobs schema, all existing function signatures.

Review & Testing Checklist for Human

  • Verify get_job Strategy 2 logic handles edge cases: expired locks, mixed NULL/non-NULL queue jobs, SKIP LOCKED contention under concurrent workers
  • Confirm add_job upsert behavior is correct — when a locked job is replaced, the old key is nulled and attempts maxed out, then a fresh row is inserted
  • Deploy to a test database and run EXPLAIN ANALYZE on get_job to confirm the partial indexes are used
  • Verify that existing trigger helpers still work since add_job signature dropped unused flags param

Notes

  • database-jobs-v1 is preserved as a reference — can be removed once the swap is validated in production
  • The is_available column is not read by app code but is required for the partial index optimization
  • add_job signature: (db_id, identifier, payload, job_key, queue_name, run_at, max_attempts, priority) — same as v1 minus the never-used flags param

Link to Devin session: https://app.devin.ai/sessions/88b82416d018482791c791cdc91118de
Requested by: @pyramation

…tions

New @pgpm/database-jobs-v2 package based on @pgpm/database-jobs v0.21.0 with:

Phase 1 - Critical performance fixes:
- Fix queue_name default from gen_random_uuid()::text to NULL
- Rewrite get_job with pre-computed queue set (Strategy 2 vs old per-row EXISTS)

Phase 2 - Index improvements:
- Add is_available generated column (locked_at IS NULL AND attempts < max_attempts)
- Replace priority_run_at_id_idx with partial covering indexes (jobs_main_index, jobs_no_queue_index)

Phase 3 - Modernization:
- Add revision column (incremented on upsert via job key)
- Add flags jsonb column with forbidden_flags filtering in get_job
- Change notify trigger from FOR EACH ROW to FOR EACH STATEMENT
- Add remove_job(job_key text) function
- Add force_unlock_workers(worker_ids text[]) function

Interface is fully backward-compatible: all existing function signatures preserved.

Refs: constructive-io/constructive-planning#772
@devin-ai-integration
Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

pyramation added 5 commits May 1, 2026 06:09
- Remove revision column (unused by our architecture — no job replacement tracking needed)
- Remove flags jsonb column and forbidden_flags parameter from get_job (worker routing is handled at K8s level, not SQL level)
- Remove flags parameter from add_job and all flags-related upsert logic
- Keep is_available generated column (powers partial indexes for get_job performance)
- Update snapshot test to reflect removed columns
- Rename database-jobs → database-jobs-v1 (legacy, v0.15.5)
- Rename database-jobs-v2 → database-jobs (optimized, v0.22.0)
- Update package.json, control files, and pgpm.plan for both
- Update CI workflow matrix accordingly

The new database-jobs now contains all the upstream performance
optimizations (Strategy 2 get_job, is_available partial indexes,
NULL queue_name default, statement-level notify trigger) plus
remove_job and force_unlock_workers functions.
@devin-ai-integration devin-ai-integration Bot changed the title feat: add @pgpm/database-jobs-v2 with upstream performance optimizations feat: upgrade database-jobs with upstream performance optimizations May 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant