Skip to content

Conversation

@mkrasnitski
Copy link
Collaborator

@mkrasnitski mkrasnitski commented Feb 8, 2025

Untangles the spaghetti of shard management code by removing the middleman ShardQueuer struct, which used a disorienting mess of mpsc channels to facilitate message passing between the ShardManager and each of its ShardRunners.

The new ShardManager::run function takes care of creating/spawning new runners as needed. This is fine to call without spawning a separate task (which was being done for ShardQueuer) because Client::start_connection previously already waited for the ShardQueuer loop to (essentially) finish before returning. In other words, the Client would start the ShardManager and then block, but the waiting was just being facilitated through channels, which wasn't obvious.

The only messages passed across channels now are ShardRunnerMessage (sent from the manager to a given runner), and a new ShardManagerMessage (sent from a runner back to the manager). For example, the manager can send a message to a runner telling it to restart, then the runner will shut itself down and ask the manager to reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent batches or not. Since we only use concurrent startup when first initializing all shards, and then switch it off once and don't re-enable it, this should be fine.

I've done some cursory testing of this using the repo examples, but I'd like some real apps to test this out before it's merged so that I know nothing is broken. Especially I'd like to make sure that concurrent shard starting works correctly.

@mkrasnitski mkrasnitski requested a review from GnomedDev February 8, 2025 04:08
@github-actions github-actions bot added gateway Related to the `gateway` module. examples Related to Serenity's examples. collector Related to the `collector` module. labels Feb 8, 2025
@mkrasnitski mkrasnitski force-pushed the shard-manager branch 2 times, most recently from 114a03c to b4e564a Compare February 8, 2025 04:44
@github-actions github-actions bot removed the collector Related to the `collector` module. label Feb 8, 2025
@arqunis arqunis added enhancement An improvement to Serenity. breaking change The public API is changed, resulting in miscompilations or unexpected new behaviour for users labels Feb 8, 2025
@mkrasnitski mkrasnitski force-pushed the shard-manager branch 4 times, most recently from c10edff to 57280c2 Compare February 12, 2025 22:20
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of dispatching new
runners as needed. This is fine to call without spawning a separate task
because `Client::start_connection` previously already waited for the
`ShardQueuer` loop to finish before returning, meaning that the
`ShardManager` was already long-running before, it just wasn't obvious.

Rename `Context::shard_messenger` back to `shard`
Copy link
Member

@GnomedDev GnomedDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very good, a lot better, just some concerns I spotted.

* Add docs
* Rename `ShardManagerMessage::Err` to `Quit`
* Move `ShardQueue` into its own file
* Change runner_info `Mutex` to a sync implementation and don't block
  when locking it
* Outline the shutdown logic in the `Drop` impl for `ShardManager`
Copy link
Member

@GnomedDev GnomedDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I am comfortable with this being merged now and getting some testing on next especially with follow up changes on the way.

People like me with big bots reliant on next may want to be ready to roll back after this PR as it is likely to cause issues that code review and small scale testing cannot find.

@arqunis arqunis merged commit 9b904ba into serenity-rs:next Feb 19, 2025
24 checks passed
@mkrasnitski mkrasnitski deleted the shard-manager branch February 20, 2025 03:14
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Mar 5, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Mar 5, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Mar 7, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Mar 10, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Mar 11, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
arqunis pushed a commit that referenced this pull request Mar 14, 2025
Follow up to #3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
GnomedDev pushed a commit to GnomedDev/serenity that referenced this pull request Mar 26, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
GnomedDev pushed a commit to GnomedDev/serenity that referenced this pull request Mar 26, 2025
Follow up to serenity-rs#3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
GnomedDev pushed a commit to GnomedDev/serenity that referenced this pull request Mar 26, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
GnomedDev pushed a commit to GnomedDev/serenity that referenced this pull request Mar 26, 2025
Follow up to serenity-rs#3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
GnomedDev pushed a commit that referenced this pull request Apr 28, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
GnomedDev pushed a commit that referenced this pull request Apr 28, 2025
Follow up to #3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
GnomedDev pushed a commit that referenced this pull request May 19, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
GnomedDev pushed a commit that referenced this pull request May 19, 2025
Follow up to #3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Jun 30, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Jun 30, 2025
Follow up to serenity-rs#3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Jun 30, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Jun 30, 2025
Follow up to serenity-rs#3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Jun 30, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Jun 30, 2025
Follow up to serenity-rs#3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Jul 28, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Jul 28, 2025
Follow up to serenity-rs#3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Jul 28, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Jul 28, 2025
Follow up to serenity-rs#3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Oct 7, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Oct 7, 2025
Follow up to serenity-rs#3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Oct 7, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Oct 7, 2025
Follow up to serenity-rs#3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Oct 7, 2025
Untangles the spaghetti of shard management code by removing the
middleman `ShardQueuer` struct, which used a disorienting mess of mpsc
channels to facilitate message passing between the `ShardManager` and
each of its `ShardRunner`s.

The new `ShardManager::run` function takes care of creating/spawning new
runners as needed. This is fine to call without spawning a separate task
(which was being done for `ShardQueuer`) because
`Client::start_connection` previously already waited for the
`ShardQueuer` loop to (essentially) finish before returning. In other
words, the Client would start the `ShardManager` and then block, but the
waiting was just being facilitated through channels, which wasn't
obvious.

The only messages passed across channels now are `ShardRunnerMessage`
(sent from the manager to a given runner), and a new
`ShardManagerMessage` (sent from a runner back to the manager). For
example, the manager can send a message to a runner telling it to
restart, then the runner will shut itself down and ask the manager to
reboot the shard by sending it a message back.

The shard queue now keeps track of if it should dispatch in concurrent
batches or not. Since we only use concurrent startup when first
initializing all shards, and then switch it off once and don't re-enable
it, this should be fine.
mkrasnitski added a commit to mkrasnitski/serenity that referenced this pull request Oct 7, 2025
Follow up to serenity-rs#3108.

Inlines the fields and methods of `ShardMessenger` into `Context` and changes
collectors to take `&Context`. Also, removes the `ShardRunnerMessage::{Close,
Message}` variants, adds an `UpdateVoiceState` variant (Songbird will want to
use this) and combines the 3 presence-related variants into one. Plus some
miscellaneous cleanup of the `ShardRunner` code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change The public API is changed, resulting in miscompilations or unexpected new behaviour for users enhancement An improvement to Serenity. examples Related to Serenity's examples. gateway Related to the `gateway` module.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants