forked from twilight-rs/twilight
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(cache_in_memory)!: In-memory cache with generic types (twilight-…
…rs#2179) Adds support for using custom structs for cached representation of Discord API data via generics on `InMemoryCache` and a set of traits for cached data that is required for caching functionality. The `DefaultInMemoryCache` type alias is added for an implementation with the default types provided by the cache crate. Migration is very straightforward, replacing `InMemoryCache` with `DefaultInMemoryCache` in code is sufficient. This could potentially reduce memory usage drastically when structs are optimized properly by implementors. Signed-off-by: Jens Reidel <adrian@travitia.xyz> Co-authored-by: Valdemar Erk <valdemar@erk.dev>
- Loading branch information
Showing
50 changed files
with
1,964 additions
and
654 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
//! This example demonstrates the usage of [`InMemoryCache`] with custom cached | ||
//! types. The actual fields stored here are kept to a minimum for the sake of | ||
//! simplicity, in reality you may want to store a lot more information. | ||
use std::env; | ||
use twilight_gateway::{Event, EventTypeFlags, Intents, Shard, ShardId, StreamExt as _}; | ||
use twilight_http::Client; | ||
|
||
mod models; | ||
|
||
#[tokio::main] | ||
async fn main() -> anyhow::Result<()> { | ||
tracing_subscriber::fmt::init(); | ||
|
||
let event_types = EventTypeFlags::MESSAGE_CREATE | ||
| EventTypeFlags::GUILD_CREATE | ||
| EventTypeFlags::GUILD_UPDATE | ||
| EventTypeFlags::GUILD_DELETE | ||
| EventTypeFlags::MEMBER_ADD | ||
| EventTypeFlags::MEMBER_REMOVE; | ||
|
||
let mut shard = Shard::new( | ||
ShardId::ONE, | ||
env::var("DISCORD_TOKEN")?, | ||
Intents::GUILDS | ||
| Intents::GUILD_MEMBERS | ||
| Intents::GUILD_MESSAGES | ||
| Intents::MESSAGE_CONTENT, | ||
); | ||
|
||
let client = Client::new(env::var("DISCORD_TOKEN")?); | ||
|
||
let cache = models::CustomInMemoryCache::new(); | ||
|
||
while let Some(item) = shard.next_event(event_types).await { | ||
let Ok(event) = item else { | ||
tracing::warn!(source = ?item.unwrap_err(), "error receiving event"); | ||
|
||
continue; | ||
}; | ||
|
||
cache.update(&event); | ||
|
||
if let Event::MessageCreate(msg) = event { | ||
if !msg.content.starts_with("!guild-info") { | ||
continue; | ||
} | ||
|
||
let Some(guild_id) = msg.guild_id else { | ||
continue; | ||
}; | ||
|
||
let Some(guild) = cache.guild(guild_id) else { | ||
continue; | ||
}; | ||
|
||
let text = format!( | ||
"The owner of this server is <@{}>. The guild currently has {} members.", | ||
guild.owner_id, | ||
guild | ||
.member_count | ||
.map_or(String::from("N/A"), |c| c.to_string()), | ||
); | ||
|
||
client.create_message(msg.channel_id).content(&text).await?; | ||
} | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
use twilight_cache_inmemory::CacheableChannel; | ||
use twilight_model::{ | ||
channel::{permission_overwrite::PermissionOverwrite, Channel, ChannelType}, | ||
id::{ | ||
marker::{ChannelMarker, GuildMarker}, | ||
Id, | ||
}, | ||
util::Timestamp, | ||
}; | ||
|
||
#[derive(Clone, Debug, PartialEq)] | ||
pub struct MinimalCachedChannel { | ||
pub id: Id<ChannelMarker>, | ||
pub guild_id: Option<Id<GuildMarker>>, | ||
pub kind: ChannelType, | ||
pub parent_id: Option<Id<ChannelMarker>>, | ||
} | ||
|
||
impl From<Channel> for MinimalCachedChannel { | ||
fn from(channel: Channel) -> Self { | ||
Self { | ||
id: channel.id, | ||
guild_id: channel.guild_id, | ||
kind: channel.kind, | ||
parent_id: channel.parent_id, | ||
} | ||
} | ||
} | ||
|
||
impl PartialEq<Channel> for MinimalCachedChannel { | ||
fn eq(&self, other: &Channel) -> bool { | ||
self.id == other.id | ||
&& self.guild_id == other.guild_id | ||
&& self.kind == other.kind | ||
&& self.parent_id == other.parent_id | ||
} | ||
} | ||
|
||
impl CacheableChannel for MinimalCachedChannel { | ||
fn guild_id(&self) -> Option<Id<GuildMarker>> { | ||
self.guild_id | ||
} | ||
|
||
fn id(&self) -> Id<ChannelMarker> { | ||
self.id | ||
} | ||
|
||
fn kind(&self) -> ChannelType { | ||
self.kind | ||
} | ||
|
||
fn parent_id(&self) -> Option<Id<ChannelMarker>> { | ||
self.parent_id | ||
} | ||
|
||
fn permission_overwrites(&self) -> Option<&[PermissionOverwrite]> { | ||
None | ||
} | ||
|
||
fn set_last_pin_timestamp(&mut self, _timestamp: Option<Timestamp>) { | ||
// We don't store this information, so this is a no-op | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
use twilight_cache_inmemory::CacheableCurrentUser; | ||
use twilight_model::{ | ||
id::{marker::UserMarker, Id}, | ||
user::CurrentUser, | ||
}; | ||
|
||
#[derive(Clone, Debug, PartialEq)] | ||
pub struct MinimalCachedCurrentUser { | ||
pub id: Id<UserMarker>, | ||
} | ||
|
||
impl From<CurrentUser> for MinimalCachedCurrentUser { | ||
fn from(value: CurrentUser) -> Self { | ||
Self { id: value.id } | ||
} | ||
} | ||
|
||
impl PartialEq<CurrentUser> for MinimalCachedCurrentUser { | ||
fn eq(&self, other: &CurrentUser) -> bool { | ||
self.id == other.id | ||
} | ||
} | ||
|
||
impl CacheableCurrentUser for MinimalCachedCurrentUser { | ||
fn id(&self) -> Id<UserMarker> { | ||
self.id | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use twilight_cache_inmemory::CacheableEmoji; | ||
use twilight_model::{ | ||
guild::Emoji, | ||
id::{marker::EmojiMarker, Id}, | ||
}; | ||
|
||
#[derive(Clone, Debug, PartialEq)] | ||
pub struct MinimalCachedEmoji { | ||
pub id: Id<EmojiMarker>, | ||
} | ||
|
||
impl From<Emoji> for MinimalCachedEmoji { | ||
fn from(value: Emoji) -> Self { | ||
Self { id: value.id } | ||
} | ||
} | ||
|
||
impl PartialEq<Emoji> for MinimalCachedEmoji { | ||
fn eq(&self, other: &Emoji) -> bool { | ||
self.id == other.id | ||
} | ||
} | ||
|
||
impl CacheableEmoji for MinimalCachedEmoji {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
use twilight_cache_inmemory::CacheableGuild; | ||
use twilight_model::{ | ||
gateway::payload::incoming::GuildUpdate, | ||
guild::Guild, | ||
id::{ | ||
marker::{GuildMarker, UserMarker}, | ||
Id, | ||
}, | ||
}; | ||
|
||
#[derive(Clone, Debug, PartialEq)] | ||
pub struct MinimalCachedGuild { | ||
pub id: Id<GuildMarker>, | ||
pub owner_id: Id<UserMarker>, | ||
pub member_count: Option<u64>, | ||
} | ||
|
||
impl From<Guild> for MinimalCachedGuild { | ||
fn from(guild: Guild) -> Self { | ||
Self { | ||
id: guild.id, | ||
owner_id: guild.owner_id, | ||
member_count: guild.member_count, | ||
} | ||
} | ||
} | ||
|
||
impl PartialEq<Guild> for MinimalCachedGuild { | ||
fn eq(&self, other: &Guild) -> bool { | ||
self.id == other.id | ||
&& self.owner_id == other.owner_id | ||
&& self.member_count == other.member_count | ||
} | ||
} | ||
|
||
impl CacheableGuild for MinimalCachedGuild { | ||
fn id(&self) -> Id<GuildMarker> { | ||
self.id | ||
} | ||
|
||
fn owner_id(&self) -> Id<UserMarker> { | ||
self.owner_id | ||
} | ||
|
||
fn set_unavailable(&mut self, _unavailable: bool) { | ||
// We don't store this information, so this is a no-op | ||
} | ||
|
||
fn update_with_guild_update(&mut self, guild_update: &GuildUpdate) { | ||
self.id = guild_update.id; | ||
self.owner_id = guild_update.owner_id; | ||
self.member_count = guild_update.member_count; | ||
} | ||
|
||
fn increase_member_count(&mut self, amount: u64) { | ||
if let Some(count) = self.member_count.as_mut() { | ||
*count += amount; | ||
} | ||
} | ||
|
||
fn decrease_member_count(&mut self, amount: u64) { | ||
if let Some(count) = self.member_count.as_mut() { | ||
*count -= amount; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use twilight_cache_inmemory::CacheableGuildIntegration; | ||
use twilight_model::{ | ||
guild::GuildIntegration, | ||
id::{marker::IntegrationMarker, Id}, | ||
}; | ||
|
||
#[derive(Clone, Debug, PartialEq)] | ||
pub struct MinimalCachedGuildIntegration { | ||
pub id: Id<IntegrationMarker>, | ||
} | ||
|
||
impl From<GuildIntegration> for MinimalCachedGuildIntegration { | ||
fn from(integration: GuildIntegration) -> Self { | ||
Self { id: integration.id } | ||
} | ||
} | ||
|
||
impl PartialEq<GuildIntegration> for MinimalCachedGuildIntegration { | ||
fn eq(&self, other: &GuildIntegration) -> bool { | ||
self.id == other.id | ||
} | ||
} | ||
|
||
impl CacheableGuildIntegration for MinimalCachedGuildIntegration {} |
Oops, something went wrong.