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

Suite Result
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 suite 223/223
metadata full suite 252/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

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 25, 2026 3:02am

Request Review

@github-actions github-actions Bot 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 main Jun 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 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.

1 participant