The taskQueueProcessing cluster role didn't filter any tasks. roles.task_manager only decided whether the task manager started (crates/services/src/task_manager/manager.rs:61-66).
In the claim scan, report, ACME, DKIM, DNS, calendar, thread-merge and restore tasks matched => true (manager.rs:301-310), so they ran on any node that had a task manager. A node whose role turned taskQueueProcessing off still ran them if it also did search indexing or maintenance.
Change
Each task type now answers to exactly one ClusterTaskType, in task_enabled() in manager.rs:
Reports → outboundMta. Report tasks build reports and send them to other domains. TLS reports may go straight to an HTTPS endpoint. That is the outbound MTA's job, so a node kept off outbound mail doesn't send them.
Everything else → taskQueueProcessing. ACME, DKIM and DNS automation, calendar alarms and iTIP, thread merges and restores have no dedicated role. taskQueueProcessing is the catch-all its name promises.
How claiming works now:
A node that may not run a task skips it before claiming. It takes no lock, so the task stays free for a node that may run it.
The task manager now also starts when outboundMta is a node's only task role, so reports still run there.
If no node's role allows a task type, those tasks wait. That was already true for the dedicated roles.
Tests
cluster::task_roles::task_role_tests is new. It runs two task managers over one PostgreSQL store (STORE=PostgreSql; it skips itself on RocksDb and SQLite, whose files two nodes can't share).
Node A has taskQueueProcessing only. Three tasks are scheduled: a DNS task, an unindex task (searchIndexing) and a TLS report (outboundMta). A runs the DNS task. The other two are still pending about 5 s later.
Node B comes up with searchIndexing and outboundMta. It runs the unindex task and the TLS report.
A new DNS task stays pending on B, then runs on A.
Results:
PostgreSql: pass.
On main: fails at step 1 (TLS report ran on node A).
system::system_tests (RocksDb): its quota step failed here with and without this change (main's manager.rs swapped in, same worktree), and passed on another worktree with main's code. It looks timing-dependent on this shared machine, not related to this PR.
## Problem
The `taskQueueProcessing` cluster role didn't filter any tasks. `roles.task_manager` only decided whether the task manager started (`crates/services/src/task_manager/manager.rs:61-66`).
In the claim scan, report, ACME, DKIM, DNS, calendar, thread-merge and restore tasks matched `=> true` (`manager.rs:301-310`), so they ran on any node that had a task manager. A node whose role turned `taskQueueProcessing` off still ran them if it also did search indexing or maintenance.
## Change
Each task type now answers to exactly one `ClusterTaskType`, in `task_enabled()` in `manager.rs`:
| Task types | Role |
|---|---|
| IndexDocument, UnindexDocument, IndexTrace | searchIndexing *(unchanged)* |
| AccountMaintenance, TenantMaintenance, DestroyAccount | accountMaintenance *(unchanged)* |
| StoreMaintenance | storeMaintenance *(unchanged)* |
| SpamFilterMaintenance | spamClassifierTraining *(unchanged)* |
| DmarcReport, TlsReport | **outboundMta** |
| CalendarAlarmEmail, CalendarAlarmNotification, CalendarItipMessage, MergeThreads, RestoreArchivedItem, AcmeRenewal, DkimManagement, DnsManagement | **taskQueueProcessing** |
Why these:
- **Reports → outboundMta.** Report tasks build reports and send them to other domains. TLS reports may go straight to an HTTPS endpoint. That is the outbound MTA's job, so a node kept off outbound mail doesn't send them.
- **Everything else → taskQueueProcessing.** ACME, DKIM and DNS automation, calendar alarms and iTIP, thread merges and restores have no dedicated role. `taskQueueProcessing` is the catch-all its name promises.
How claiming works now:
- A node that may not run a task skips it before claiming. It takes no lock, so the task stays free for a node that may run it.
- The task manager now also starts when `outboundMta` is a node's only task role, so reports still run there.
**If no node's role allows a task type, those tasks wait.** That was already true for the dedicated roles.
## Tests
`cluster::task_roles::task_role_tests` is new. It runs two task managers over one PostgreSQL store (`STORE=PostgreSql`; it skips itself on RocksDb and SQLite, whose files two nodes can't share).
1. Node A has `taskQueueProcessing` only. Three tasks are scheduled: a DNS task, an unindex task (`searchIndexing`) and a TLS report (`outboundMta`). A runs the DNS task. The other two are still pending about 5 s later.
2. Node B comes up with `searchIndexing` and `outboundMta`. It runs the unindex task and the TLS report.
3. A new DNS task stays pending on B, then runs on A.
Results:
- PostgreSql: pass.
- On `main`: fails at step 1 (`TLS report ran on node A`).
- `store::task_locks::task_lock_tests` (RocksDb): pass.
- `system::system_tests` (RocksDb): its quota step failed here with and without this change (`main`'s `manager.rs` swapped in, same worktree), and passed on another worktree with `main`'s code. It looks timing-dependent on this shared machine, not related to this PR.
A 3-node rehearsal found taskQueueProcessing didn't filter anything:
roles.task_manager only decided whether the task manager started, and
report, ACME, DKIM, DNS, calendar, thread-merge and restore tasks ran on
any node with a task manager (manager.rs returned true for them). A node
whose role left taskQueueProcessing off still ran them if it indexed or
did maintenance.
Every task type now answers to one ClusterTaskType (task_enabled):
- IndexDocument, UnindexDocument, IndexTrace: searchIndexing
- AccountMaintenance, TenantMaintenance, DestroyAccount:
accountMaintenance
- StoreMaintenance: storeMaintenance
- SpamFilterMaintenance: spamClassifierTraining
- DmarcReport, TlsReport: outboundMta. They build and send reports to
other domains (TLS reports can go straight to an HTTPS endpoint),
which is the outbound MTA's business.
- CalendarAlarmEmail, CalendarAlarmNotification, CalendarItipMessage,
MergeThreads, RestoreArchivedItem, AcmeRenewal, DkimManagement,
DnsManagement: taskQueueProcessing, the role for queue tasks with no
role of their own.
A node that may not run a task leaves it unclaimed (no lock), so a node
that may picks it up. The task manager also starts on a node whose only
task role is outboundMta, so reports still run there.
cluster::task_roles::task_role_tests (new, two task managers over one
PostgreSQL store): node A (taskQueueProcessing only) runs a DNS task and
leaves an unindex task and a TLS report pending; node B (searchIndexing
and outboundMta) comes up and runs those two; a DNS task scheduled next
stays pending on B and runs on A. On main node A runs the TLS report.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
The
taskQueueProcessingcluster role didn't filter any tasks.roles.task_manageronly decided whether the task manager started (crates/services/src/task_manager/manager.rs:61-66).In the claim scan, report, ACME, DKIM, DNS, calendar, thread-merge and restore tasks matched
=> true(manager.rs:301-310), so they ran on any node that had a task manager. A node whose role turnedtaskQueueProcessingoff still ran them if it also did search indexing or maintenance.Change
Each task type now answers to exactly one
ClusterTaskType, intask_enabled()inmanager.rs:Why these:
taskQueueProcessingis the catch-all its name promises.How claiming works now:
outboundMtais a node's only task role, so reports still run there.If no node's role allows a task type, those tasks wait. That was already true for the dedicated roles.
Tests
cluster::task_roles::task_role_testsis new. It runs two task managers over one PostgreSQL store (STORE=PostgreSql; it skips itself on RocksDb and SQLite, whose files two nodes can't share).taskQueueProcessingonly. Three tasks are scheduled: a DNS task, an unindex task (searchIndexing) and a TLS report (outboundMta). A runs the DNS task. The other two are still pending about 5 s later.searchIndexingandoutboundMta. It runs the unindex task and the TLS report.Results:
main: fails at step 1 (TLS report ran on node A).store::task_locks::task_lock_tests(RocksDb): pass.system::system_tests(RocksDb): its quota step failed here with and without this change (main'smanager.rsswapped in, same worktree), and passed on another worktree withmain's code. It looks timing-dependent on this shared machine, not related to this PR.