From 315fe8e33b01ef894db248baea34d97f22f9d540 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 21 Jan 2024 17:06:43 +0100 Subject: [PATCH 1/8] Define type alias `Shared` --- src/gateway/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gateway/mod.rs b/src/gateway/mod.rs index 076ed54..c5f415e 100644 --- a/src/gateway/mod.rs +++ b/src/gateway/mod.rs @@ -122,3 +122,11 @@ impl GatewayEvent { } } } + +/// A type alias for [`Arc>`], used to make the public facing API concerned with +/// Composite structs more ergonomic. +/// ## Note +/// +/// While `T` does not have to implement `Composite` to be used with `Shared`, +/// the primary use of `Shared` is with types that implement `Composite`. +pub type Shared = Arc>; From 36ac6c1e5e811781f3fe398208d674c5f151b922 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 21 Jan 2024 17:07:19 +0100 Subject: [PATCH 2/8] Replace use of Arc> with Shared --- src/gateway/handle.rs | 6 +++--- tests/common/mod.rs | 17 ++++++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/gateway/handle.rs b/src/gateway/handle.rs index 620faba..d44dfa2 100644 --- a/src/gateway/handle.rs +++ b/src/gateway/handle.rs @@ -42,8 +42,8 @@ impl GatewayHandle { pub async fn observe>( &self, - object: Arc>, - ) -> Arc> { + object: Shared, + ) -> Shared { let mut store = self.store.lock().await; let id = object.read().unwrap().id(); if let Some(channel) = store.get(&id) { @@ -84,7 +84,7 @@ impl GatewayHandle { /// with all of its observable fields being observed. pub async fn observe_and_into_inner>( &self, - object: Arc>, + object: Shared, ) -> T { let channel = self.observe(object.clone()).await; let object = channel.read().unwrap().clone(); diff --git a/tests/common/mod.rs b/tests/common/mod.rs index bce419a..eae2b26 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,6 +1,5 @@ -use std::sync::{Arc, RwLock}; - -use chorus::gateway::Gateway; +use chorus::gateway::{Gateway, Shared}; +use chorus::types::Composite; use chorus::{ instance::{ChorusUser, Instance}, types::{ @@ -16,9 +15,9 @@ pub(crate) struct TestBundle { pub urls: UrlBundle, pub user: ChorusUser, pub instance: Instance, - pub guild: Arc>, - pub role: Arc>, - pub channel: Arc>, + pub guild: Shared, + pub role: Shared, + pub channel: Shared, } #[allow(unused)] @@ -119,9 +118,9 @@ pub(crate) async fn setup() -> TestBundle { urls, user, instance, - guild: Arc::new(RwLock::new(guild)), - role: Arc::new(RwLock::new(role)), - channel: Arc::new(RwLock::new(channel)), + guild: guild.to_shared(), + role: role.to_shared(), + channel: channel.to_shared(), } } From 0660e25bdb0f260c443fbf7520d2e1b95e01d2f7 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 21 Jan 2024 17:07:30 +0100 Subject: [PATCH 3/8] rustfmt --- examples/gateway_simple.rs | 4 ++-- src/gateway/heartbeat.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/gateway_simple.rs b/examples/gateway_simple.rs index affa850..7a0d807 100644 --- a/examples/gateway_simple.rs +++ b/examples/gateway_simple.rs @@ -31,8 +31,8 @@ async fn main() { identify.token = token; // Send off the event - gateway.send_identify(identify).await; - + gateway.send_identify(identify).await; + // Do something on the main thread so we don't quit loop { sleep(Duration::from_secs(3600)).await; diff --git a/src/gateway/heartbeat.rs b/src/gateway/heartbeat.rs index 8e37697..e6991f3 100644 --- a/src/gateway/heartbeat.rs +++ b/src/gateway/heartbeat.rs @@ -71,7 +71,7 @@ impl HeartbeatHandler { let mut last_heartbeat_timestamp: Instant = Instant::now(); let mut last_heartbeat_acknowledged = true; let mut last_seq_number: Option = None; - + loop { if kill_receive.try_recv().is_ok() { trace!("GW: Closing heartbeat task"); From 2a7cae30b8e74304a1dcdd6614c076996781a712 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 21 Jan 2024 17:07:54 +0100 Subject: [PATCH 4/8] Define public method `to_shared` for dyn Composite --- src/types/entities/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/types/entities/mod.rs b/src/types/entities/mod.rs index 8343628..8a06c35 100644 --- a/src/types/entities/mod.rs +++ b/src/types/entities/mod.rs @@ -23,6 +23,8 @@ pub use user_settings::*; pub use voice_state::*; pub use webhook::*; +use crate::gateway::Shared; + #[cfg(feature = "client")] use crate::gateway::Updateable; @@ -121,4 +123,11 @@ pub trait Composite { } vec } + + fn to_shared(self) -> Shared + where + Self: Sized, + { + Arc::new(RwLock::new(self)) + } } From ca58767372cc5143763fc9fb137ea813e21523ea Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 21 Jan 2024 17:10:24 +0100 Subject: [PATCH 5/8] Rename to_shared to into_shared --- src/types/entities/mod.rs | 2 +- tests/common/mod.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/types/entities/mod.rs b/src/types/entities/mod.rs index 8a06c35..3f075ce 100644 --- a/src/types/entities/mod.rs +++ b/src/types/entities/mod.rs @@ -124,7 +124,7 @@ pub trait Composite { vec } - fn to_shared(self) -> Shared + fn into_shared(self) -> Shared where Self: Sized, { diff --git a/tests/common/mod.rs b/tests/common/mod.rs index eae2b26..a267125 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -118,9 +118,9 @@ pub(crate) async fn setup() -> TestBundle { urls, user, instance, - guild: guild.to_shared(), - role: role.to_shared(), - channel: channel.to_shared(), + guild: guild.into_shared(), + role: role.into_shared(), + channel: channel.into_shared(), } } From 57214fd2fe3682feb85015cb93837b9633572f37 Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 21 Jan 2024 17:15:11 +0100 Subject: [PATCH 6/8] Add documentation for into_shared --- src/types/entities/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/types/entities/mod.rs b/src/types/entities/mod.rs index 3f075ce..7c914b1 100644 --- a/src/types/entities/mod.rs +++ b/src/types/entities/mod.rs @@ -124,6 +124,12 @@ pub trait Composite { vec } + /// Uses [`Shared`] to provide an ergonomic alternative to `Arc::new(RwLock::new(obj))`. + /// + /// [`Shared`] can then be observed using the [`Gateway`], turning the underlying + /// `dyn Composite` into a self-updating struct, which is a tracked variant of a chorus + /// entity struct, updating its' held information when new information concerning itself arrives + /// over the [`Gateway`] connection, reducing the need for expensive network-API calls. fn into_shared(self) -> Shared where Self: Sized, From a571a9e137be0ace826acd5d7e7bcfe1be9a2a4f Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 21 Jan 2024 20:13:00 +0100 Subject: [PATCH 7/8] Write documentation for observe --- src/gateway/handle.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gateway/handle.rs b/src/gateway/handle.rs index d44dfa2..bc64077 100644 --- a/src/gateway/handle.rs +++ b/src/gateway/handle.rs @@ -40,6 +40,15 @@ impl GatewayHandle { .unwrap(); } + /// Recursively observes a [`Shared`] object, by making sure all [`Composite `] fields within + /// that object and its children are being watched. + /// + /// Observing means, that if new information arrives about the observed object or its children, + /// the object automatically gets updated, without you needing to request new information about + /// the object in question from the API, which is expensive and can lead to rate limiting. + /// + /// The [`Shared`] object returned by this method points to a different object than the one + /// being supplied as a &self function argument. pub async fn observe>( &self, object: Shared, From 6637f14b18793f1b0bde67a65b2d052a152bf29d Mon Sep 17 00:00:00 2001 From: bitfl0wer Date: Sun, 21 Jan 2024 20:24:17 +0100 Subject: [PATCH 8/8] Replace Arc, Rwlock with Shared --- tests/gateway.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tests/gateway.rs b/tests/gateway.rs index 5bf5865..deb3129 100644 --- a/tests/gateway.rs +++ b/tests/gateway.rs @@ -1,10 +1,8 @@ mod common; -use std::sync::{Arc, RwLock}; - use chorus::errors::GatewayError; use chorus::gateway::*; -use chorus::types::{self, ChannelModifySchema, RoleCreateModifySchema, RoleObject}; +use chorus::types::{self, ChannelModifySchema, Composite, RoleCreateModifySchema, RoleObject}; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; #[cfg(target_arch = "wasm32")] @@ -97,11 +95,7 @@ async fn test_recursive_self_updating_structs() { .await .unwrap(); // Watch role; - bundle - .user - .gateway - .observe(Arc::new(RwLock::new(role.clone()))) - .await; + bundle.user.gateway.observe(role.into_shared()).await; // Update Guild and check for Guild let inner_guild = guild.read().unwrap().clone(); assert!(inner_guild.roles.is_some()); @@ -113,7 +107,7 @@ async fn test_recursive_self_updating_structs() { let role_inner = bundle .user .gateway - .observe_and_into_inner(Arc::new(RwLock::new(role.clone()))) + .observe_and_into_inner(role.into_shared()) .await; assert_eq!(role_inner.name, "yippieee"); // Check if the change propagated