Skip to content

fix(automation): re-bind scheduled-flow jobs on os dev hot-reload - #2313

Merged
os-zhuang merged 1 commit into
mainfrom
fix/dev-reload-scheduled-flow-rebind
Jun 25, 2026
Merged

fix(automation): re-bind scheduled-flow jobs on os dev hot-reload#2313
os-zhuang merged 1 commit into
mainfrom
fix/dev-reload-scheduled-flow-rebind

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Problem

Editing a schedule-triggered flow under objectstack dev silently kept firing the OLD definition until a full server restart. The terminal prints ✓ recompiled — server will auto-reload, but the scheduled job bound at boot keeps running the pre-edit flow (old runAs / schedule / logic) on its timer — with no signal the edit had no effect.

Root cause (a gap, not by design)

The dev watcher recompiles dist/objectstack.json; the server's MetadataPlugin reloads it into the MetadataManager (so GET /meta + UI HMR are fresh). But the AutomationEngine pulls its flow definitions and trigger/job bindings once at boot (ql.registry.listItems('flow')) and nothing re-registers them on reload. registerFlow / ScheduleTrigger.start are already idempotent and re-bind correctly — the reload path simply never called them.

This is a whole bug class: record-change flows also executed boot-time definitions after an edit; scheduled flows are just the most visible because they fire on a timer with no user interaction.

Fix

  • @objectstack/metadata — factor _reloadAndAnnounce; both reload sites (HMR POST handler + server-side artifact-file watcher) fire a generic metadata:reloaded hook after reloading (never on the initial boot load). MetadataPlugin stays decoupled from automation — it just announces.
  • @objectstack/service-automation — subscribe to metadata:reloaded and re-sync the engine from the metadata service: re-register every current flow (idempotent → re-binds the trigger; ScheduleTrigger.start cancels + reschedules the job) and unregister flows removed from the artifact so their jobs stop. Covers all auto-triggered flow types (schedule / record-change / api).

Why pull from the metadata service and not ql.registry? The reload writes the edited definitions only into the MetadataManager via register(). ql.registry is a boot-only cache the reload never refreshes, and programmatic register() does not fire the subscribe() watchCallbacks — so the metadata service is the only source carrying the edited definitions.

Production deployments are unaffected — nothing reloads the artifact there.

Tests

SuiteResult
flow-hot-reload.test.ts (new, service-automation)2/2 — edited scheduled flow re-binds to the new definition (fired job runs runAs user→system); deleted flow torn down
plugin-hmr-reload.test.ts (new, metadata)2/2 — reload fires metadata:reloaded; a throwing subscriber never breaks the reload
service-automation full suite223/223
metadata full suite252/252
trigger-schedule (schedule-path sanity)19/19

Source typechecks (tsup DTS build clean). Changeset included (both packages patch, same fixed group).

Discovered while dogfooding the #1888 schedule/runAs follow-up (#2308) — not caused by it.

🤖 Generated with Claude Code

Editing a schedule-triggered flow under `objectstack dev` silently kept firing
the OLD definition until a full server restart. The dev watcher recompiles
dist/objectstack.json and MetadataPlugin reloads it into the MetadataManager
(so GET /meta + UI HMR are fresh), but the AutomationEngine pulls its flow
definitions and trigger/job bindings ONCE at boot — nothing re-registered them
on reload. So the scheduled job bound at boot kept running the pre-edit flow
(old runAs/schedule/logic) on its timer, with no signal the edit had no effect.
MetadataPlugin now fires a generic `metadata:reloaded` hook after each artifact
reload (the HMR POST handler and the server-side artifact-file watcher; never on
the initial boot load). AutomationServicePlugin subscribes and re-syncs the
engine from the metadata service — re-registering every current flow (idempotent:
registerFlow re-binds the trigger, ScheduleTrigger.start cancels + reschedules
the job) and unregistering flows removed from the artifact so their jobs stop.
Covers all auto-triggered flow types (schedule / record-change / api), since
record-change flows were also executing boot-time definitions after an edit.
Production deployments are unaffected — nothing reloads the artifact there.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 25, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJun 25, 2026 3:02am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling size/m labels Jun 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/metadata, packages/services.

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

  • content/docs/concepts/cluster-semantics.mdx(via packages/metadata)
  • content/docs/concepts/metadata-lifecycle.mdx(via @objectstack/metadata)
  • content/docs/concepts/packages.mdx(via @objectstack/metadata)
  • content/docs/guides/packages.mdx(via @objectstack/metadata, packages/services)
  • content/docs/guides/runtime-services/audit-service.mdx(via packages/services)
  • content/docs/guides/runtime-services/index.mdx(via packages/services)
  • content/docs/guides/runtime-services/settings-service.mdx(via packages/services)
  • content/docs/protocol/objectos/i18n-standard.mdx(via packages/services)
  • content/docs/protocol/objectos/metadata-service.mdx(via @objectstack/metadata)

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.

@os-zhuang
os-zhuang merged commit 4b5ec6e into mainJun 25, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the fix/dev-reload-scheduled-flow-rebind branch June 25, 2026 03:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang