feat(flow): scheduled trigger + fix flowsForTrigger (every event trigger was dead) (#2068) - #2126
Merged
Merged
Conversation
Run a flow on a schedule — n8n's Schedule/Cron trigger, the last native trigger family. A flow with trigger `schedule` and a `cron` expression runs when its time comes, driven by a worker rather than an event. - FlowScheduleService: given "now", lists the enabled schedule flows and, for each whose cron occurrence has passed since it last fired, queues a run (trigger `schedule`) and records the fire time in app config keyed by flow uuid (so the flow object is never rewritten). A flow never fired is due at once, then follows its cron. - FlowScheduleWorker: a TimedJob (5-min) that asks the service which flows are due each tick; scheduled runs are executed by the existing FlowRunWorker, so a scheduled flow shares the whole run lifecycle. Registered in info.xml. - The flow schema gains a `cron` property; the descriptor version is bumped so fresh installs ship it. 🔥 FIX — every event trigger was silently dead. OpenRegisterFlowResolver:: flowsForTrigger queried `findAll(config: ['register'=>…, 'schema'=>…])`, but ObjectService::findAll scopes via `config['filters']['register'|'schema']`. The wrong key returned ZERO objects, so no flow wired to any event (object/file/user/ share/tag) ever matched — triggers queued nothing. The scheduled trigger, which reuses the same query, surfaced it. Corrected to `filters`. (HermiqFlowResolver has the identical bug — fixed in its own repo.) Tests: FlowScheduleServiceTest (6 — due fires, recent not due, disabled, non- schedule, invalid/missing cron, no store); 154 flow unit tests green; phpcs clean. Playwright e2e tests/e2e/api-direct/flow-schedule.spec.ts (2 — a due flow fired by the worker shows in history; a non-schedule flow is not fired) — all 9 flow e2e pass. Live-verified on 8080: executing the worker queues a schedule run, and the findAll fix makes both scheduled and event flows match.
Contributor
Quality Report — ConductionNL/openregister @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 174/174 | |||
| npm | ✅ | ✅ 555/555 | |||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-07-25 21:01 UTC
Download the full PDF report from the workflow artifacts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Run a flow on a schedule — n8n's Schedule/Cron trigger, the last native trigger family — and a fix for a bug this work uncovered: every event trigger was silently firing nothing.
The bug (critical)
OpenRegisterFlowResolver::flowsForTriggerqueriedfindAll(config: ['register'=>…, 'schema'=>…]), butObjectService::findAllscopes viaconfig['filters']['register'|'schema']. The wrong key returned zero objects, so no flow wired to any event (object/file/user/share/tag) ever matched — triggers queued nothing. The scheduled trigger reuses the same query, which is what surfaced it. Corrected tofilters. (HermiqFlowResolverhas the identical bug — fixed in its own repo.)This was never caught before because the earlier trigger verification tested the listener → fire() path, not
flowsForTriggerreturning ids against the realObjectService.The feature
FlowScheduleService— lists enabledscheduleflows and, for each whose cron occurrence has passed since it last fired, queues a run (triggerschedule) and records the fire time in app config keyed by flow uuid (the flow object is never rewritten). A flow never fired is due at once, then follows its cron.FlowScheduleWorker— aTimedJob(5-min) that ticks the service; scheduled runs are executed by the existingFlowRunWorker, so a scheduled flow shares the whole run lifecycle.flowschema gainscron; descriptor version bumped so fresh installs ship it.Verification
FlowScheduleServiceTest(6: due fires, recent-not-due, disabled, non-schedule, invalid/missing cron, no store). 154 flow unit tests green; phpcs clean.tests/e2e/api-direct/flow-schedule.spec.ts(2): author a scheduled flow via API → tick the realFlowScheduleWorkerviaocc background-job:execute→ assert aschedulerun in history; a non-schedule flow is not fired. All 9 flow e2e pass (7 engine + 2 schedule).schedulerun; thefindAllfix makes both scheduled and event flows match.Out of scope
Sub-minute schedules (5-min tick) and per-flow timezone (cron evaluated in the server zone).
🤖 Generated with Claude Code