Skip to content

fix(service-job): migrate early registrations across the placeholder→DbJobAdapter upgrade — cron jobs finally run - #4172

Merged
os-zhuang merged 1 commit into
mainfrom
claude/four-issues-review-0f6199
Jul 30, 2026
Merged

fix(service-job): migrate early registrations across the placeholder→DbJobAdapter upgrade — cron jobs finally run#4172
os-zhuang merged 1 commit into
mainfrom
claude/four-issues-review-0f6199

Conversation

@baozhoutao

@baozhoutao baozhoutao commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Closes #4174

Summary

Plugin-registered cron jobs never fired in the default (adapter: 'auto'/'db') configuration. Three stacked causes, found via real-app dogfooding (A/B measured: an interval 15s job ran 23 times while a cron */1 * * * * job ran 0 times):

  1. JobServicePlugin.init registers a placeholder IntervalJobAdapter synchronously so callers can getService('job') during init — but that placeholder silently ignores cron schedules (no timer, no error).
  2. The upgrade to the croner-backed DbJobAdapter happens in kernel:ready, which runs after every business plugin's start() — so all their registrations land on the placeholder.
  3. The upgrade swapped the service via replaceService without migrating the already-registered jobs: cron entries were lost for good, and the placeholder's interval timers kept running on the orphaned adapter — which is exactly why interval jobs looked healthy while cron jobs did nothing, and why none of them showed up in sys_job.

Fix

  • The kernel:ready upgrade now snapshots every registration made against the placeholder (getRegistrations()), stops the placeholder first (a brief gap beats a double-fire), then re-schedules everything on the DbJobAdapter — whose cron routing makes the cron entries actually run and persists them to sys_job.
  • IntervalJobAdapter warns per cron registration it cannot execute (it has no cron engine), and the no-engine path summarizes stranded cron jobs in one line instead of staying silent.
  • replaceService failure now returns early instead of migrating onto a service nobody resolves.

Tests

  • New job-service-plugin.test.ts: early cron + interval registrations both follow the upgrade (service swapped, listJobs complete, sys_job rows present, placeholder emptied, migrated handler still fires via trigger); the no-engine path warns loudly about stranded cron jobs.
  • pnpm vitest run in packages/services/service-job: 5 files, 39 tests, all green; pnpm build clean.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 30, 2026 1:47pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): packages/services.

6 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/automation/webhooks.mdx (via packages/services)
  • content/docs/kernel/runtime-services/audit-service.mdx (via packages/services)
  • content/docs/kernel/runtime-services/index.mdx (via packages/services)
  • content/docs/kernel/runtime-services/settings-service.mdx (via packages/services)
  • content/docs/plugins/packages.mdx (via packages/services)
  • content/docs/protocol/kernel/i18n-standard.mdx (via packages/services)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@baozhoutao baozhoutao self-assigned this Jul 30, 2026
@os-zhuang
os-zhuang merged commit 74aa3f0 into main Jul 30, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/four-issues-review-0f6199 branch July 30, 2026 15:00
…DbJobAdapter upgrade

Business plugins start() before kernel:ready, so their schedules all land on
the placeholder IntervalJobAdapter — which silently ignores cron schedules —
and the upgrade swapped the service without migrating anything. Default
config result: cron jobs never ran at all, while interval timers kept
running on the orphaned placeholder, invisible to sys_job.

The upgrade now snapshots every early registration, stops the placeholder,
and re-schedules them on the DbJobAdapter. The IntervalJobAdapter warns per
cron registration it cannot execute, and the no-engine path summarizes the
stranded cron jobs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

service-job: cron jobs registered before kernel:ready never fire — placeholder drops them and the DbJobAdapter upgrade does not migrate

2 participants