aboutsummaryrefslogtreecommitdiff
path: root/src/client/bridge/gateway/mod.rs
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2017-11-03 07:13:24 -0700
committerZeyla Hellyer <[email protected]>2017-11-03 07:13:38 -0700
commitb8efeaf5e920cbfc775cdee70f23aa41ab7b9dd5 (patch)
tree17eb07c8218f1e145d5eb3fba353fd1486b3874d /src/client/bridge/gateway/mod.rs
parentMake the Client return a Result (diff)
downloadserenity-b8efeaf5e920cbfc775cdee70f23aa41ab7b9dd5.tar.xz
serenity-b8efeaf5e920cbfc775cdee70f23aa41ab7b9dd5.zip
Redo client internals + gateway
This commit is a rewrite of the client module's internals and the gateway. The main benefit of this is that there is either 0 or 1 lock retrievals per event received, and the ability to utilize the ShardManager both internally and in userland code has been improved. The primary rework is in the `serenity::client` module, which now includes a few more structures, some changes to existing ones, and more functionality (such as to the `ShardManager`). The two notable additions to the client-gateway bridge are the `ShardMessenger` and `ShardManagerMonitor`. The `ShardMessenger` is a simple-to-use interface for users to use to interact with shards. The user is given one of these in the `serenity::client::Context` in dispatches to the `serenity::client::EventHandler`. This can be used for updating the presence of a shard, sending a guild chunk message, or sending a user's defined WebSocket message. The `ShardManagerMonitor` is a loop run in its own thread, potentially the main thread, that is responsible for receiving messages over an mpsc channel on what to do with shards via the `ShardManager`. For example, it will receive a message to shutdown a single shard, restart a single shard, or shutdown the entire thing. Users, in most applications, will not interact with the `ShardManagerMonitor`. Users using the `serenity::client::Client` interact with only the `ShardMessenger`. The `ShardManager` is now usable by the user and is available to them, and contains public functions for shutdowns, initializations, restarts, and complete shutdowns of shards. It contains utility functions like determining whether the `ShardManager` is responsible for a shard of a given ID and the IDs of shards currently active (having an associated `ShardRunner`). It can be found on `serenity::client::Client::shard_manager`. Speaking of the `ShardRunner`, it no longer owns a clone of an Arc to its assigned `serenity::gateway::Shard`. It now completely owns the Shard. This means that in order to open the shard, a `ShardRunner` no longer has to repeatedly retrieve a lock to it. This reduces the number of lock retrievals per event dispatching cycle from 3 or 4 depending on event type to 0 or 1 depending on whether it's a message create _and_ if the framework is in use. To interact with the Shard, one must now go through the previously mentioned `ShardMessenger`, which the `ShardRunner` will check for messages from on a loop. `serenity::client::Context` is now slightly different. Instead of the `shard` field being `Arc<Mutex<Shard>>`, it is an instance of a `ShardMessenger`. The interface is the same (minus losing some Shard-specific methods like `latency`), and `Context`'s shortcuts still exist (like `Context::online` or `Context::set_game`). It now additionally includes a `Context::shard_id` field which is a u64 containing the ID of the shard that the event was dispatched from. `serenity::client::Client` has one changed field name, one field that is now public, and a new field. `Client::shard_runners` is now `Client::shard_manager` of type `Arc<Mutex<ShardManager>>`. The `Client::token` field is now public. This can, for example, be mutated on token resets if you know what you're doing. `Client::ws_uri` is new and contains the URI for shards to use when connecting to the gateway. Otherwise, the Client's usage is unchanged. `serenity::gateway::Shard` has a couple of minor changes and many more public methods and fields. The `autoreconnect`, `check_heartbeat`, `handle_event`, `heartbeat`, `identify`, `initialize`, `reset`, `resume`, `reconnect`, and `update_presence` methods are now public. The `token` structfield is now public. There are new getters for various structfields, such as `heartbeat_instants` and `last_heartbeat_ack`. The breaking change on the `Shard` is that `Shard::handle_event` now takes an event by reference and, instead of returning `Result<Option<Event>>`, it now returns `Result<Option<ShardAction>>`. `serenity::gateway::ShardAction` is a light enum determining an action that someone _should_/_must_ perform on the shard, e.g. reconnecting or identifying. This is determined by `Shard::handle_event`. In total, there aren't too many breaking changes that most of userland use cases has to deal with -- at most, changing some usage of `Context`. Retrieving information like a Shard's latency is currently not possible anymore but work will be done to make this functionality available again.
Diffstat (limited to 'src/client/bridge/gateway/mod.rs')
-rw-r--r--src/client/bridge/gateway/mod.rs114
1 files changed, 104 insertions, 10 deletions
diff --git a/src/client/bridge/gateway/mod.rs b/src/client/bridge/gateway/mod.rs
index 0b873aa..752b015 100644
--- a/src/client/bridge/gateway/mod.rs
+++ b/src/client/bridge/gateway/mod.rs
@@ -1,28 +1,113 @@
+//! The client gateway bridge is support essential for the [`client`] module.
+//!
+//! This is made available for user use if one wishes to be lower-level or avoid
+//! the higher functionality of the [`Client`].
+//!
+//! Of interest are three pieces:
+//!
+//! ### [`ShardManager`]
+//!
+//! The shard manager is responsible for being a clean interface between the
+//! user and the shard runners, providing essential functions such as
+//! [`ShardManager::shutdown`] to shutdown a shard and [`ShardManager::restart`]
+//! to restart a shard.
+//!
+//! If you are using the `Client`, this is likely the only piece of interest to
+//! you. Refer to [its documentation][`ShardManager`] for more information.
+//!
+//! ### [`ShardQueuer`]
+//!
+//! The shard queuer is a light wrapper around an mpsc receiver that receives
+//! [`ShardManagerMessage`]s. It should be run in its own thread so it can
+//! receive messages to start shards in a queue.
+//!
+//! Refer to [its documentation][`ShardQueuer`] for more information.
+//!
+//! ### [`ShardRunner`]
+//!
+//! The shard runner is responsible for actually running a shard and
+//! communicating with its respective WebSocket client.
+//!
+//! It is performs all actions such as sending a presence update over the client
+//! and, with the help of the [`Shard`], will be able to determine what to do.
+//! This is, for example, whether to reconnect, resume, or identify with the
+//! gateway.
+//!
+//! ### In Conclusion
+//!
+//! For almost every - if not every - use case, you only need to _possibly_ be
+//! concerned about the [`ShardManager`] in this module.
+//!
+//! [`Client`]: ../../struct.Client.html
+//! [`client`]: ../..
+//! [`Shard`]: ../../../gateway/struct.Shard.html
+//! [`ShardManager`]: struct.ShardManager.html
+//! [`ShardManager::restart`]: struct.ShardManager.html#method.restart
+//! [`ShardManager::shutdown`]: struct.ShardManager.html#method.shutdown
+//! [`ShardQueuer`]: struct.ShardQueuer.html
+//! [`ShardRunner`]: struct.ShardRunner.html
+
mod shard_manager;
+mod shard_manager_monitor;
+mod shard_messenger;
mod shard_queuer;
mod shard_runner;
+mod shard_runner_message;
pub use self::shard_manager::ShardManager;
+pub use self::shard_manager_monitor::ShardManagerMonitor;
+pub use self::shard_messenger::ShardMessenger;
pub use self::shard_queuer::ShardQueuer;
pub use self::shard_runner::ShardRunner;
+pub use self::shard_runner_message::ShardRunnerMessage;
-use gateway::Shard;
-use parking_lot::Mutex;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::sync::mpsc::Sender;
-use std::sync::Arc;
-type Parked<T> = Arc<Mutex<T>>;
-type LockedShard = Parked<Shard>;
+/// A message either for a [`ShardManager`] or a [`ShardRunner`].
+///
+/// [`ShardManager`]: struct.ShardManager.html
+/// [`ShardRunner`]: struct.ShardRunner.html
+pub enum ShardClientMessage {
+ /// A message intended to be worked with by a [`ShardManager`].
+ ///
+ /// [`ShardManager`]: struct.ShardManager.html
+ Manager(ShardManagerMessage),
+ /// A message intended to be worked with by a [`ShardRunner`].
+ ///
+ /// [`ShardRunner`]: struct.ShardRunner.html
+ Runner(ShardRunnerMessage),
+}
+/// A message for a [`ShardManager`] relating to an operation with a shard.
+///
+/// [`ShardManager`]: struct.ShardManager.html
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum ShardManagerMessage {
+ /// Indicator that a [`ShardManagerMonitor`] should restart a shard.
+ ///
+ /// [`ShardManagerMonitor`]: struct.ShardManagerMonitor.html
Restart(ShardId),
+ /// Indicator that a [`ShardManagerMonitor`] should fully shutdown a shard
+ /// without bringing it back up.
+ ///
+ /// [`ShardManagerMonitor`]: struct.ShardManagerMonitor.html
Shutdown(ShardId),
- #[allow(dead_code)]
+ /// Indicator that a [`ShardManagerMonitor`] should fully shutdown all shards
+ /// and end its monitoring process for the [`ShardManager`].
+ ///
+ /// [`ShardManager`]: struct.ShardManager.html
+ /// [`ShardManagerMonitor`]: struct.ShardManagerMonitor.html
ShutdownAll,
}
+/// A message to be sent to the [`ShardQueuer`].
+///
+/// This should usually be wrapped in a [`ShardClientMessage`].
+///
+/// [`ShardClientMessage`]: enum.ShardClientMessage.html
+/// [`ShardQueuer`]: enum.ShardQueuer.html
+#[derive(Clone, Debug)]
pub enum ShardQueuerMessage {
/// Message to start a shard, where the 0-index element is the ID of the
/// Shard to start and the 1-index element is the total shards in use.
@@ -31,8 +116,8 @@ pub enum ShardQueuerMessage {
Shutdown,
}
-// A light tuplestruct wrapper around a u64 to verify type correctness when
-// working with the IDs of shards.
+/// A light tuplestruct wrapper around a u64 to verify type correctness when
+/// working with the IDs of shards.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ShardId(pub u64);
@@ -42,7 +127,16 @@ impl Display for ShardId {
}
}
+/// Information about a [`ShardRunner`].
+///
+/// The [`ShardId`] is not included because, as it stands, you probably already
+/// know the Id if you obtained this.
+///
+/// [`ShardId`]: struct.ShardId.html
+/// [`ShardRunner`]: struct.ShardRunner.html
+#[derive(Debug)]
pub struct ShardRunnerInfo {
- pub runner_tx: Sender<ShardManagerMessage>,
- pub shard: Arc<Mutex<Shard>>,
+ /// The channel used to communicate with the shard runner, telling it
+ /// what to do with regards to its status.
+ pub runner_tx: Sender<ShardClientMessage>,
}