Problem/Motivation

Notifications are a basic feature of a workflow engine, but three of them shipped as separate submodules whose only content was the code that dispatches at one notification point.

  • orchestra_notification: two plugins, 259 lines, and no services file at all. The architecture page called it the shared notification core, but the emitter, the event, the audience resolver and the nine audience plugins have always been in the base module, and neither other dispatcher ever depended on it. A Notify node is a node type like the seven the base module already ships, and a recipients field is a node feature like its five.
  • orchestra_inbox_notification: one event subscriber, 181 lines. It injects nothing but base-module services, so merging it adds nothing to the inbox dependencies; its only tie to its host is the inbox route it builds the task link from.
  • orchestra_interaction_notification: one subscriber and one node feature. Its only service from outside the base module is its host own orchestra_interaction.token, and its node feature already read InteractionResolver::CONFIG_KEY, a key belonging to its host, to validate its own value.

Nothing in the project was conditional on any of the three being installed, and none of them was an off switch worth keeping. Who is notified is already decided per assignment by the Notify this audience flag, which a role or group audience has to opt into, and whether anything is delivered at all is decided by installing a channel.

orchestra_interaction_notification was the opposite of a clean off switch: it shipped the park_notify node feature and the schema for that key with no uninstall step, so a site that dropped it kept park_notify in its saved workflows with no schema left to type it.

Proposed resolution

Fold each dispatcher into the module that owns the thing being notified about, and keep the delivery channels separate, which is the seam that carries its weight: orchestra_mail and orchestra_easy_email are mutually exclusive in practice, and choosing between them is the operator decision.

  • Guard dispatch first. OrchestraNotification::hasChannel() answers whether any subscriber would receive the event, and every dispatch point asks it before resolving an audience. The separate modules used to spare a channel-less site that work by simply not being installed; merging them makes those paths unconditional, so the cost is guarded where it is paid.
  • Notify and NotifyAudience move to the base module plugin directories, with orchestra.node_feature.notify_to beside the five node-feature types the kernel already declares.
  • TaskNotificationSubscriber moves to orchestra_inbox.
  • ParkNotificationSubscriber and ParkNotification move to orchestra_interaction, with the park_notify schema beside orchestra.node_feature.interaction.
  • Each French catalog merges into its host catalog, and the two log messages that carry a module name follow their code.

The Notify node asks hasChannel() as a condition rather than an early return, so it still returns TaskDecision::Advance: a notification that reaches nobody must not hold the branch on that step.

Remaining tasks

Review the merge request. The three submodules stop existing, so a site that had them installed is reinstalled rather than upgraded; there are no update hooks before the first beta.

AI-Generated: Yes (Claude Code was used to draft this issue summary and to write the change and its test case. The new test was confirmed to fail with the guard disabled and to pass with it; phpcs over the whole module, cspell and the project translation check were run locally, and the full test suite runs in CI.)

Issue fork orchestra-3624863

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mably created an issue. See original summary.

mably’s picture

Status: Active » Needs review

  • mably committed b83a87f1 on 1.x
    task: #3624863 Fold the three notification dispatcher submodules into...
mably’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.