Job & Chain Queries
The client provides read-only methods for inspecting job chains and jobs. All query methods accept an optional transaction context and don’t require transactionHooks.
// Look up a single job chain or job by IDconst jobChain = await client.getJobChain({ id: jobChainId });const job = await client.getJob({ id: jobId });
// Paginated lists with filtersconst jobChains = await client.listJobChains({ filter: { typeName: ["send-email"], status: ["running"] }, limit: 20,});
const jobs = await client.listJobs({ filter: { jobChainId: [jobChainId], status: ["completed"] },});
// Cursor-based paginationconst nextPage = await client.listJobChains({ filter: { typeName: ["send-email"] }, cursor: jobChains.nextCursor,});
// Jobs within a specific job chain, ordered by chain indexconst jobChainJobs = await client.listJobChainJobs({ jobChainId });
// Blocker relationshipsconst blockers = await client.getJobBlockers({ jobId });const blockedJobs = await client.listBlockedJobs({ jobChainId });All lookup methods accept an optional typeName for type narrowing — the return type narrows to the specified type. If the entity exists but has a different type, JobTypeMismatchError is thrown.
See examples/showcase-queries for a complete working example demonstrating single lookups, paginated lists, chain job listing, and blocker queries. See also Client API reference and Dashboard.
Performance considerations
Section titled “Performance considerations”listJobChains joins each root row with the last job in the chain to resolve chain status. Filtering by status is not optimized — it applies to the joined last job and cannot use an index. Always provide a typeName or date range (from/to) filter to narrow the scan:
// Expensive — status filter alone still scans every root rowconst all = await client.listJobChains({ filter: { status: ["running"] },});
// Efficient — typeName narrows the scan via a partial indexconst filtered = await client.listJobChains({ filter: { typeName: ["send-email"], status: ["running"] },});On PostgreSQL, long-running unfiltered scans hold MVCC snapshots that prevent autovacuum from reclaiming dead tuples, causing table bloat over time. See PostgreSQL Internals for details.