0.8.0-alpha1
Pre-releasenostrum 0.8.0-alpha1
Welcome to nostrum 0.8.0, codenamed "ignition on".
This release introduces full support for distributed caching and state, and
simplifies the existing cache behaviours by using a single shared interface for
reading the cache using Erlang's QLC module. Simply put, instead of having to
implement callbacks for every combination of functions that nostrum exposes (and
will expose) to the cache, a pluggable cache only needs to implement the
c:query_handle/0
callback. To fulfill this move, a few smaller breaking
changes have been performed. It is expected that these will be the last bigger
breaking changes done before the proper 1.0 release (at which point we will
follow semantic versioning).
Note that cache distribution was not the only missing piece to allow
distributing nostrum across multiple nodes (albeit the largest one). Gateway
event handling must be updated to prevent duplicate gateway connections,
proper distribution of shards over nodes must be implemented, and some other
improvements in regards to gateway connections with many shards must be
implemented, including support for persistent resume seq tokens.
Breaking changes
- The current family of functions to read from the
MemberCache
have been
replaced.- Functions affected:
MemberCache.get/1
->MemberCache.fold/3-4
MemberCache.get_with_users/1
->MemberCache.fold_with_users/3-4
MemberCache.by_user/1
->MemberCache.fold_by_user/3-4
- These changes were performed to support caches that need to perform some
form of resource acquisition and release: ETS needs to callsafe_fixtable
for safe traversal and Mnesia needs to wrap calls in:mnesia.activity
.
- Functions affected:
- The following error returns have been renamed to a more generic version:
:channel_not_found
->:not_found
:presence_not_found
->:not_found
:id_not_found
->:not_found
:id_not_found_on_guild_lookup
->:not_found
:channel_not_found
->:not_found
- The
ChannelCache
will no longer look up channels in theGuildCache
if they
were not found in the channel cache itself. A convenience function to fetch a
channel from a guild (they are stored together) can be introduced to
GuildCache
if needed. PresenceCache.get(user_id, guild_id)
is nowPresenceCache.get(guild_id, user_id)
, the same forPresenceCache.get!/2
.- The reason behind this is that all "nested" caches use this form already,
and having the arguments reversed may be confusing.
- The reason behind this is that all "nested" caches use this form already,
Deprecations
The following functions have been deprecated and will be removed in either
nostrum 0.9 or 1.0:
GuildCache.all/0
GuildCache.select_by/1
GuildCache.select/2
Features
- Heavily improved support for querying the cache, via Erlang's QLC. This allows
you to express strong queries in native Erlang list comprehension syntax
without having to enumerate the entire cache by yourself, with the added bonus
that it can automatically, at compile time, optimize your query to use indices
and other improved traversal mechanisms on the backend you're using. For
instance, the Mnesia member cache places an index on theguild_id
field:
queries involving this field are automatically optimized at compile time to
utilize the index to provide for fast lookups. As an example, the following
query is used in nosedrum as part of the member converter:find_by(RequestedGuildId, Name, Discriminator, MemberCache, UserCache) -> qlc:q([Member || {{GuildId, MemberId}, Member} <- MemberCache:query_handle(), GuildId =:= RequestedGuildId, {UserId, User} <- UserCache:query_handle(), MemberId =:= UserId, map_get(username, User) =:= Name, map_get(discriminator, User) =:= Discriminator]).
- Support specifying a shard range to start.
- Previously, you could either start a set number of shards, or tell nostrum
to use the amount that Discord asked you to use. - A new third option is introduced, which expects a tuple in the form
{lowest, highest, total}
, where nostrum will startlowest..highest
shards and inform Discord you havetotal
shards in total. - This is useful for bots that have outgrown a single server and need to split
their shards across multiple servers. However, see the changes below as
well.
- Previously, you could either start a set number of shards, or tell nostrum
- Distributed caching.
- All
Nostrum.Cache
modules now have an Mnesia-based cache adapter that
allows you to replicate and distribute the data across hosts, with the full
power of Mnesia. - Larger bots can fragment their cache tables into smaller replicated cache
tables and can thus distribute their bot without having to implement their
own distributed caching system.
- All
- Distributed state.
- As with distributed caching, Nostrum's internal state now also ships with
Mnesia-based distributed adapters.
- As with distributed caching, Nostrum's internal state now also ships with
- Do not require pluggable caches to implement multiple supervisor callbacks.
Implementingchild_spec
is sufficient.
Fixes
- Requeue requests that ran into a "retry later" up to 50 times.
- This is enough to prevent any legitimate requests from being dropped, whilst
still guarding against somebody going haywire on the ratelimiter.
- This is enough to prevent any legitimate requests from being dropped, whilst
- Prevent a crash when
retry_after
was 0.
Documentation
- Create documentation on how to use nostrum in a multi-node cluster.
- Restructure the Pages tab to be more inline with which features you want to
use. - Move pluggable cache modules down on the API reference list to not take up
space from the regular cache APIs.- As this feature won't be needed by most bots, we don't need it to clutter up
space for everybody.
- As this feature won't be needed by most bots, we don't need it to clutter up
- Embed the consumer example into the
Nostrum.Consumer
moduledoc. - Add an "Internal modules" section on the API documentation for modules that
are highly unlikely to be used by the regular user, but are still documented
for completeness.
Internal changes
- Add caching benchmarks.
- Add propaganda assets to the VCS tree.