Skip to content

[2.x] feat(queue): restore per-class queue routing on AbstractJob - #4656

Merged
imorland merged 2 commits into
2.xfrom
im/abstract-job-onqueue
May 12, 2026
Merged

[2.x] feat(queue): restore per-class queue routing on AbstractJob#4656
imorland merged 2 commits into
2.xfrom
im/abstract-job-onqueue

Conversation

@imorland

@imorland imorland commented May 12, 2026

Copy link
Copy Markdown
Member

Summary

Restores the $onQueue static property + constructor that 1.x's AbstractJob exposed, and wires every in-tree job through it so operators can route any shipped job onto a dedicated queue without subclassing.

Without this, there's no built-in way for an operator (or an extension) to dispatch all instances of a given job class onto a dedicated queue without patching every dispatch site. Multiple 2.x-compatible extensions have already re-implemented this hook themselves — see issue #4653 for examples from FoF\GeoIP\Jobs\RetrieveIP and Flarum\Gdpr\Jobs\GdprJob. Both have settled on the name $onQueue (rather than 1.x's $sendOnQueue), so this PR adopts the same name.

Changes

Flarum\Queue\AbstractJob (commit 1):

  • New public static ?string $onQueue = null; property.
  • New __construct() that calls $this->onQueue(static::$onQueue) when the static property is set on the concrete subclass (late-static-bound, so each subclass gets its own routing knob).

Every in-tree job that has its own constructor (commit 2) now calls parent::__construct() so it inherits the routing behavior:

  • Flarum\Notification\Job\SendEmailNotificationJob
  • Flarum\Notification\Job\SendNotificationsJob
  • Flarum\Mail\Job\SendAbandonedExtensionsEmailJob
  • Flarum\Mail\Job\SendInformationalEmailJob
  • Flarum\User\Job\RequestPasswordResetJob
  • Flarum\Search\Job\IndexJob
  • Flarum\Messages\Job\SendMessageNotificationsJob
  • Flarum\Pusher\SendPusherNotificationsJob
  • Flarum\ExtensionManager\Job\ComposerCommandJob
  • Flarum\Mentions\Job\SendMentionsNotificationsJob
  • Flarum\Gdpr\Jobs\ExportJob, ErasureJob

Cleanups for jobs that previously implemented the hook themselves:

  • Flarum\Gdpr\Jobs\GdprJob: drop the local $onQueue shadow (inherited now).
  • Flarum\Realtime\Push\Jobs\Job: drop the local $onQueue shadow and the workaround __construct() (inherited now). All concrete Send*Job subclasses in the same directory already call parent::__construct(), so routing flows through unchanged.

Behavior

  • AbstractJob::$onQueue defaults to null, so default behavior is unchanged.
  • Operators (or extensions) set SomeJob::$onQueue = 'queue-name' once at boot to route all instances of that job class onto a specific queue.
  • Late-static-binding means a Child extends Parent subclass's own $onQueue value wins over the parent's, as expected.

Test plan

  • New unit test tests/unit/Queue/AbstractJobTest.php covers: default behavior (no routing), routing via the static property, and late-static-binding under inheritance.
  • Existing queue unit + integration tests pass unchanged (tests/unit/Queue, tests/integration/queue).
  • PHPStan clean on every changed file.

Closes #4653

Reintroduces the `$onQueue` static property + constructor that 1.x jobs
relied on for per-class queue routing. Without this, operators have no
built-in way to send a specific job class to a dedicated queue without
patching every dispatch site, which is why multiple 2.x-compatible
extensions (`FoF\GeoIP\Jobs\RetrieveIP`, `Flarum\Gdpr\Jobs\GdprJob`)
have already re-implemented the same hook in their own base classes.

Property name follows the convention those extensions settled on
(`$onQueue` rather than 1.x's `$sendOnQueue`).

Closes #4653
@imorland
imorland requested a review from a team as a code owner May 12, 2026 20:14
@imorland imorland added this to the 2.0.0-rc.2 milestone May 12, 2026
…truct

Adds `parent::__construct()` to every existing job in core and the
monorepo extensions so that operators can route any of them via the
`$onQueue` static property without having to subclass.

Also removes the now-redundant local `$onQueue` shadow from
`Flarum\Gdpr\Jobs\GdprJob` and the workaround constructor from
`Flarum\Realtime\Push\Jobs\Job` — both are now provided by the base
class.

If we're restoring the convention, the standard library should lead
by example: every shipped job should be routable.
@imorland
imorland merged commit c57b7a3 into 2.x May 12, 2026
25 checks passed
@imorland
imorland deleted the im/abstract-job-onqueue branch May 12, 2026 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[2.x] AbstractJob lost queue-routing convention in 2.x — restore as

1 participant