Make the background job time-sensitive so cron actually runs it
Build package / php-lint (8.2) (push) Successful in 48s
Build package / php-lint (8.3) (push) Successful in 45s
Build package / php-lint (8.4) (push) Successful in 47s
Build package / xml-lint (push) Successful in 13s
Build package / unit-tests (push) Successful in 43s
Build package / package (push) Canceled after 0s
Build package / php-lint (8.2) (push) Successful in 48s
Build package / php-lint (8.3) (push) Successful in 45s
Build package / php-lint (8.4) (push) Successful in 47s
Build package / xml-lint (push) Successful in 13s
Build package / unit-tests (push) Successful in 43s
Build package / package (push) Canceled after 0s
The job was registered but never executed: `background-job:list` kept showing last_run = 1970-01-01. It was marked TIME_INSENSITIVE, and OC\Core\Service\CronService::runCli() reads `maintenance_window_start` and calls jobList->getNext($onlyTimeSensitive = true) whenever the current UTC hour is outside [start, start+4] -- so with a maintenance window configured, time-insensitive jobs are skipped for the other 20 hours of the day. A job whose entire purpose is a 5-minute (now configurable down to 60s) reaction time is time-sensitive by definition. Also fix the occ invocation in README.md and CLAUDE.md: background-job:worker takes job classes, not an app id, so the documented `background-job:worker workflow_deck_automation` matched nothing.
This commit is contained in:
@@ -22,6 +22,10 @@ The filter-matching logic (`WorkflowRunner::cardMatchesFilters()`, `::isOverdue(
|
|||||||
|
|
||||||
`RunWorkflowsJob` reads `workflow_deck_automation.interval` (seconds, default 300, clamped to a 60s minimum) via `IConfig::getSystemValueInt()` in its constructor. That works *because* `TimedJob` re-reads `$this->interval` on every cron pass from the freshly constructed job — so editing `config.php` takes effect immediately, with no `occ` command and no re-registration. Don't move this into `appinfo/info.xml` or a stored app config; the constants (`INTERVAL_CONFIG_KEY`, `DEFAULT_INTERVAL`, `MINIMUM_INTERVAL`) on the job are the single source of truth and are referenced from the README.
|
`RunWorkflowsJob` reads `workflow_deck_automation.interval` (seconds, default 300, clamped to a 60s minimum) via `IConfig::getSystemValueInt()` in its constructor. That works *because* `TimedJob` re-reads `$this->interval` on every cron pass from the freshly constructed job — so editing `config.php` takes effect immediately, with no `occ` command and no re-registration. Don't move this into `appinfo/info.xml` or a stored app config; the constants (`INTERVAL_CONFIG_KEY`, `DEFAULT_INTERVAL`, `MINIMUM_INTERVAL`) on the job are the single source of truth and are referenced from the README.
|
||||||
|
|
||||||
|
**The job must stay `IJob::TIME_SENSITIVE`.** It was `TIME_INSENSITIVE` at first, which looked harmless and was not: `OC\Core\Service\CronService::runCli()` reads `maintenance_window_start` (default `100`, i.e. unset) and, whenever the current UTC hour is outside `[start, start+4]`, calls `jobList->getNext($onlyTimeSensitive = true)` — time-insensitive jobs are then skipped for the other 20 hours of the day. On an instance with a maintenance window configured (Nextcloud's admin overview nags admins into setting one) the job simply never ran, showing `last_run = 1970-01-01` in `occ background-job:list` indefinitely. Note this gate only exists in `runCli()`, so it doesn't apply to ajax/webcron mode, and passing job classes explicitly (`occ background-job:worker '<class>'`) bypasses it — which is exactly why manual testing can look fine while cron does nothing.
|
||||||
|
|
||||||
|
To debug this job on a server: `occ background-job:list --class '<class>'` for its id and last run, then `occ background-job:execute <id> --force-execute` to run it right now regardless of the interval. `occ background-job:worker` takes **job classes**, not an app id.
|
||||||
|
|
||||||
## Registration is declarative, not Bootstrap-based
|
## Registration is declarative, not Bootstrap-based
|
||||||
|
|
||||||
Background jobs and classic personal settings are registered in `appinfo/info.xml` (`<background-jobs>`, `<settings><personal>/<personal-section>`), **not** via `IRegistrationContext` in `lib/AppInfo/Application.php` — that interface has no `registerBackgroundJob()`/`registerSettings()` methods on NC 34. `Application.php` is intentionally near-empty.
|
Background jobs and classic personal settings are registered in `appinfo/info.xml` (`<background-jobs>`, `<settings><personal>/<personal-section>`), **not** via `IRegistrationContext` in `lib/AppInfo/Application.php` — that interface has no `registerBackgroundJob()`/`registerSettings()` methods on NC 34. `Application.php` is intentionally near-empty.
|
||||||
@@ -45,7 +49,7 @@ npm run watch # rebuild on change during development
|
|||||||
|
|
||||||
To run a single PHPUnit test: `vendor/bin/phpunit --filter testUserFilterIsOrAgainstAssignedUsers tests/Unit/Service/WorkflowRunnerFilterTest.php`.
|
To run a single PHPUnit test: `vendor/bin/phpunit --filter testUserFilterIsOrAgainstAssignedUsers tests/Unit/Service/WorkflowRunnerFilterTest.php`.
|
||||||
|
|
||||||
There is no meaningful way to test the Deck integration itself outside a real Nextcloud+Deck instance (`php occ background-job:worker workflow_deck_automation`) — the unit tests intentionally stop at the pure filter logic.
|
There is no meaningful way to test the Deck integration itself outside a real Nextcloud+Deck instance (`php occ background-job:worker 'OCA\WorkflowDeckAutomation\BackgroundJob\RunWorkflowsJob'` — the argument is a job *class*, not an app id) — the unit tests intentionally stop at the pure filter logic.
|
||||||
|
|
||||||
### Release process
|
### Release process
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,14 @@ composer run test:unit # PHPUnit — reine Filter-Logik, benötigt keine Deck-I
|
|||||||
Ein echter End-to-End-Test (Karte anlegen, Workflow konfigurieren, Hintergrundjob auslösen, Verschiebung + Mail prüfen) lässt sich nur gegen eine echte Nextcloud-34-Instanz mit installierter Deck-App durchführen, z. B. per:
|
Ein echter End-to-End-Test (Karte anlegen, Workflow konfigurieren, Hintergrundjob auslösen, Verschiebung + Mail prüfen) lässt sich nur gegen eine echte Nextcloud-34-Instanz mit installierter Deck-App durchführen, z. B. per:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
php occ background-job:worker workflow_deck_automation
|
# Job-ID und letzten Lauf anzeigen
|
||||||
|
php occ background-job:list --class 'OCA\WorkflowDeckAutomation\BackgroundJob\RunWorkflowsJob'
|
||||||
|
|
||||||
|
# Sofort ausführen, unabhängig vom Intervall
|
||||||
|
php occ background-job:execute <id> --force-execute
|
||||||
|
|
||||||
|
# Oder dauerhaft als Worker laufen lassen (Argument ist die Job-Klasse, keine App-ID)
|
||||||
|
php occ background-job:worker 'OCA\WorkflowDeckAutomation\BackgroundJob\RunWorkflowsJob'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Release-Paket bauen
|
### Release-Paket bauen
|
||||||
|
|||||||
@@ -35,7 +35,14 @@ class RunWorkflowsJob extends TimedJob {
|
|||||||
// changed config.php takes effect on the next pass — no occ command
|
// changed config.php takes effect on the next pass — no occ command
|
||||||
// and no re-registration of the job needed.
|
// and no re-registration of the job needed.
|
||||||
$this->setInterval(self::resolveInterval($config));
|
$this->setInterval(self::resolveInterval($config));
|
||||||
$this->setTimeSensitivity(IJob::TIME_INSENSITIVE);
|
// Must stay TIME_SENSITIVE. If `maintenance_window_start` is set in
|
||||||
|
// config.php — and Nextcloud's admin overview actively nags admins
|
||||||
|
// to set it — CronService only picks up TIME_INSENSITIVE jobs during
|
||||||
|
// those 4 hours and skips them for the rest of the day. A job whose
|
||||||
|
// whole point is a 5-minute (configurable down to 60s) reaction time
|
||||||
|
// would then run a handful of times per night and look completely
|
||||||
|
// dead in between.
|
||||||
|
$this->setTimeSensitivity(IJob::TIME_SENSITIVE);
|
||||||
$this->setAllowParallelRuns(false);
|
$this->setAllowParallelRuns(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user