A highly performant and customizable third-party redis cache for twilight.
A comprehensive example can be found in examples.
- Create a new config type that implements
CacheConfig
.- Create a new type for each associated type you're interested in caching.
- Each associated type must implement its corresponding required traits.
- For associated types you don't want to cache, use
Ignore
.
- Create a
RedisCache
instance vianew
ornew_with_pool
. - In your gateway event loop, pass a reference of the event to
RedisCache::update
.
In order for data to be stored in redis, it needs a type that redis understands.
An obvious choice here is to serialize the data into a collection of bytes and then store those bytes.
serde
is the most popular crate to handle serialization in combination with implementors such as serde-json
or bincode
.
Checking out this benchmark provides insight to a bunch of options.
Most efficient serde-related crates require strict rules for handling data, which twilight's types generally
don't satisfy so we won't be able to use crates such as bincode
, bare
, postcard
, etc.
Crates such as flexbuffer
, capnp
, or prost
are based on language-agnostic schemas which are
way too painful to setup and define so those are no options either.
Other crates fall short due to unfitness for production, immaturity, or just insufficient performance.
Among the remaining options, rkyv
shines the brightest not only because of its performance and rising popularity,
but also because of its key feature: zero-cost-deserialization.
rkyv
serializes data in such a way that the written bytes can be re-interpreted as "archived form" without any deserialization at all.
This means that whenever we fetch something from the cache, we generally don't need to perform any complex and costly deserialization procedure
in order to make sense of the bytes. We just re-interprete them as "archived data" and thus can read fields.
As such, redlight
provides cached data in form of a CachedArchive<T>
instance.
CachedArchive
is essentially just a wrapper around some bytes but it also implements Deref
with Target = Archived<T>
,
meaning that you can use it just like you would an archived T
.
-
Pros:
- Data is stored in redis and thus persistent, it can remain across reboots. With the
cold_resume
feature there's even a built-in way to resume previous gateway sessions. twilight-cache-inmemory
is required to own all its data, meaning it always needs to clone it out of incoming events.redlight
on the other hand just needs to serialize it which is done via reference.- The configuration offers a way to cache only the bits and fields that you're interested in instead of the whole thing.
redlight
provides redis' built-in expire feature, meaning you can configure cached entries to automatically be removed after a given time.- There are no ways to deadlock yourself whereas storing data inmemory via
dashmap
hands you a potential foot gun. - Since the underlying pool is accessible, you technically have full control over all stored data and don't need to rely on the provided API.
- Data is stored in redis and thus persistent, it can remain across reboots. With the
-
Contras:
redlight
fully depends on redis. If your connection is slow, so will be the cache.- All
redlight
cache interactions are async and fallible. - The configuration requires some setup. Types need to be defined, traits need to be implemented, and
rkyv
needs to be utilized which in itself might be a little dawning in the beginning. redlight
comes with a fair bit of unsafe code. Some required due torkyv
's unsafe methods, some just to optimize certain operations.
Flag | Description | Dependencies |
---|---|---|
default |
Enables the bb8 and validation flag |
|
bb8 |
Uses bb8 as underlying connection pool |
bb8-redis |
deadpool |
Uses deadpool as underlying connection pool |
deadpool-redis |
validation |
Always validate data when fetched from the cache. This adds a performance penalty but ensures that stored data always matches the defined types. | rkyv/validation |
cold_resume |
Enables the methods RedisCache::freeze and RedisCache::defrost to store and load discord gateway sessions. |
twilight-gateway |
metrics |
Starts a background task that updates metrics in an interval. Metrics will be recorded in the global recorder which should be set before creating a cache instance. | metrics |
Either the bb8
or deadpool
feature must be enabled.
License: ISC