Skip to content

fix(jobs): reconcile declared background jobs Nextcloud never registered (24 of 31 were missing) - #2172

Merged
rubenvdlinde merged 1 commit into
developmentfrom
fix/reconcile-background-jobs
Jul 27, 2026
Merged

fix(jobs): reconcile declared background jobs Nextcloud never registered (24 of 31 were missing)#2172
rubenvdlinde merged 1 commit into
developmentfrom
fix/reconcile-background-jobs

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Fixes #2170.

The problem

Nextcloud writes oc_jobs only when an app is installed or upgraded. Add a <job> to info.xml without bumping the app version and it is silently never registered — no error, no warning, and there is no occ background-job:add to correct it by hand.

Measured on a live instance: 24 of 31 declared jobs were absent. Not only flows — scheduled workflows, schedule reconciliation, sync, webhook retries, notification flushing, archival retention and DBAL introspection were all inert, with 59 flow runs sitting queued that could never execute.

It hides well, because the synchronous counterparts keep working. POST /api/flow-runs/test calls FlowRunService::execute() directly, so interactive flow testing was green while every asynchronous trigger queued into a void — staying queued forever rather than failing.

The fix

A repair step that parses the <job> declarations out of info.xml and adds any IJobList does not already have. Being a repair step, it runs on occ maintenance:repair, so an instance can be corrected without inventing a version bump. Idempotent; one unresolvable job is logged and skipped rather than aborting the run, since the whole point is to recover an instance.

Verified by controlled experiment

Deleted a registered job, ran the step, watched it come back:

INFO: [OpenRegister] Registered missing background job: OCA\OpenRegister\Cron\FlowScheduleWorker
INFO: [OpenRegister] Background jobs reconciled: 1 added, 0 skipped, 31 declared.

Separately, a version bump plus occ upgrade took the instance from 9 to 34 distinct registered job classes.

Two traps hit while writing this, both worth knowing

1. SimpleXML cannot reach a hyphenated element as $xml->background_jobs — it needs $xml->{'background-jobs'}. The mismatch returns nothing rather than erroring.

2. simplexml_load_file() silently returns false inside the Nextcloud runtime. NC installs a restrictive libxml external-entity loader at boot, and PHP 8 routes file access through it. The identical parse works in a bare php -r process and fails under require lib/base.php — so the step reported "no declarations found" against an info.xml holding 31 of them. Fixed by reading the file and parsing a string.

That second one generalises: any app code parsing XML by path is suspect for the same reason.

🤖 Generated with Claude Code

…gistered

Nextcloud writes oc_jobs only when an app is INSTALLED or UPGRADED. Add a <job>
to info.xml without bumping the app version and it is silently never registered
— no error, no warning, and there is no occ background-job:add to correct it.

Measured on a live instance: 24 of 31 declared jobs were absent. Not only flows —
scheduled workflows, schedule reconciliation, sync, webhook retries, notification
flushing, archival retention and DBAL introspection were all inert. 59 flow runs
sat queued and could never execute.

It hides well: the synchronous counterparts keep working. POST /api/flow-runs/test
calls FlowRunService::execute() directly, so interactive flow testing was green
while every asynchronous trigger queued into a void, staying "queued" forever
rather than failing.

This repair step parses the <job> declarations out of info.xml and adds any that
IJobList does not already have. Because it is a repair step it runs on
occ maintenance:repair, so an instance can be corrected without inventing a
version bump. Idempotent, and one unresolvable job is logged and skipped rather
than aborting the run — the point of the step is to recover an instance.

Two traps this hit while being written, both worth knowing:

1. SimpleXML cannot reach a hyphenated element as $xml->background_jobs; it
   needs $xml->{'background-jobs'}. The mismatch returns nothing rather than
   erroring.

2. simplexml_load_file() SILENTLY RETURNS FALSE inside the Nextcloud runtime.
   NC installs a restrictive libxml external-entity loader at boot, and PHP 8
   routes file access through it. The same parse works in a bare php -r process
   and fails under require lib/base.php — so the step reported "no <job>
   declarations found" against an info.xml holding 31 of them. Fixed by reading
   the file and parsing a string. Any app code parsing XML by path is suspect
   for the same reason.

Verified by controlled experiment on a live instance: deleted FlowScheduleWorker
from oc_jobs, ran the step, and it reported "Registered missing background job:
OCA\OpenRegister\Cron\FlowScheduleWorker / 1 added, 0 skipped, 31 declared" with
the row restored. Separately, a version bump plus occ upgrade took the instance
from 9 to 34 distinct registered job classes.

Refs or#2170.
@rubenvdlinde
rubenvdlinde merged commit 460378f into development Jul 27, 2026
15 of 18 checks passed
@rubenvdlinde
rubenvdlinde deleted the fix/reconcile-background-jobs branch July 27, 2026 20:44
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openregister @ 4df4294

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-27 20:47 UTC

Download the full PDF report from the workflow artifacts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant