MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-59

1.6 Background job infrastructure

Done
Description

The durable async substrate every later Epic depends on: long-running LLM calls (Epic 7's planning agent passes run 30-60 s and cannot live inside an HTTP request), scheduled work (Epic 5 notification digests, Epic 7 auto-suggest cadences), webhook fan-out (Epic 6 search indexing, Epic 7's GitHub PR-merged → mark-Subtask-done flow), and transactional email retries (Story 1.1's password-reset + Story 1.2's workspace invites currently fire synchronously and silently swallow provider failures). Ships the runtime + the patterns (idempotency, retries, dead-letter, replay) + the first real production job + the operator surface so failures surface to a human instead of disappearing.

Prerequisites: Story 1.1 ships the lib/email.ts abstraction the first real job (1.6.3) wraps; the password-reset + workspace-invite send-sites become the first job's callers (replacing today's synchronous fire-and-pray sends — captured as a finding in PRODECT_FINDINGS.md). Story 1.2 ships WorkspaceMembership, which 1.6.5's job-runs dashboard filters by (so workspace admins only see their workspace's runs). Story 1.5 ships AppLayout + Sidebar; the dashboard route in 1.6.5 hangs off the existing sidebar's "Settings" group.

Verification

  • Pull the merged Story branch; pnpm install && pnpm dev; in a second terminal, npx inngest-cli dev.
  • Sign in as a workspace owner; navigate to Settings → Job runs; confirm both tabs render with empty states.
  • Invite a new email address to the workspace → confirm the invite-acceptance row appears in "Recent runs" as succeeded within ~3 seconds; the dev-console email body matches the invite template.
  • Set FORCE_EMAIL_FAILURE_FOR=fail@example.test in the dev shell; invite fail@example.test → watch the run climb to attempts=3 then transition to failed; confirm the DLQ tab badge increments.
  • Open the DLQ tab → click Replay on the failed row → confirm a new succeeded run appears AND the DLQ row's "Replayed" column shows the timestamp.
  • Trigger a password reset → confirm the run appears in the "System" tab (gated to the configured platform-admin email).
  • Sign out; sign in as a member (non-owner) of the same workspace → navigate to Job runs → confirm Recent runs renders but Replay is disabled with the tooltip.
  • Open the Inngest dev UI in a third tab → confirm every run the dashboard shows is also present in Inngest's own UI, with the same attempt counts and durations. The two surfaces must agree.
  • Stop and restart pnpm dev; confirm the dashboard still shows historical runs (they're DB-persisted, not in-memory).
  • Resize the dashboard to a 375×812 viewport → confirm the table is horizontally scrollable inside the responsive shell; no layout regressions vs Story 1.5.
Status
Done
Type
Story