Nostrum Documentation

repository·master·Indexed 20 days ago

https://github.com/kraigie/nostrum

An Elixir library for interacting with the Discord API. It features a REST implementation, automatic local data caching, and support for multi-node distribution and live bot migration. Key capabilities include implementing the Nostrum.Consumer behaviour, manual sharding via Nostrum.Shard.Supervisor, Zstd gateway compression, and high availability using OTP distributed applications.

Tokens
18.3K
Snippets
58
Records
90
Agent score
72%

What's inside Nostrum

  1. Interface with Erlang via Nostrum

    master
    Nostrum provides modules to interface directly with Erlang when necessary. This is primarily used to leverage the QLC (Query Logically Compiled) query compiler and its associated optimizations within the Nostrum environment.
  2. Understand the purpose of Nostrum benchmarks

    master
    The benchmarks/ directory contains microbenchmarks designed to validate the performance of Nostrum components, with a primary focus on its cache implementations. These benchmarks are intended to push the caching backends to their limits to identify potential performance bottlenecks or issues under heavy load.
  3. Handle Application Takeover Events

    master

    When running in a distributed high-availability setup, your application's def start function receives a type argument that indicates how the node was started:

    • {:failover, source_node}: The node was started because the source_node failed.
    • {:takeover, source_node}: The node is taking over from the source_node (typically used when a failed node restarts).

    You can use these types to trigger specific logic, such as re-registering commands or re-initializing state.

  4. How Nostrum handles API abstractions and helpers

    master

    Nostrum provides high-level helpers for certain Discord API endpoints to simplify common tasks. For example, while the standard Discord API limits message retrieval to 100 messages per request, the Nostrum.Api.Channel.messages/3 helper automatically handles pagination to retrieve any requested number of messages.

    Method names in the Nostrum.Api submodules are designed to match Discord's official documentation closely to make it easier to cross-reference endpoints.

    # Example of a helper abstraction (conceptual)
    Nostrum.Api.Channel.messages(channel_id, limit, options)
  5. How encryption modes affect performance

    master

    Different encryption modes have different performance characteristics based on your hardware and implementation:

    • :aes256_gcm (Default): Leverages Erlang's :crypto module and is highly efficient on CPUs with AES hardware acceleration. This is the recommended default.
    • xchacha20_poly1305: Uses the :crypto module's chacha20_poly1305 AEAD cipher. This may perform better than AES on hardware that lacks AES acceleration.
    • xsalsa20_poly1305: The Salsa20/XSalsa20 cipher is implemented in Elixir (with Poly1305 handled by :crypto), making these modes generally the slowest.
  6. How different cache implementations work in Nostrum

    master

    Nostrum provides several caching strategies depending on your bot's scale and requirements:

    ETS Caching (Default)

    • Usage: No configuration required; it is the default.
    • Pros: Fast and light on memory.
    • Cons: Does not support distribution or secondary indexing. Custom queries may result in full table scans.
    • Best for: Smaller bots.

    Mnesia Caching

    • Usage: Suggested for larger bots requiring cache distribution, fragmentation, or secondary indexing.
    • Requirements:
      • mnesia must be available and installed with OTP (may not be available on Nerves).
      • Mnesia must be started ahead of Nostrum.
    • Features: Tables are created automatically at startup. You can use the table/0 function to retrieve the table name for schema operations like adding replicas or fragmentation.
    • Consistency: Access is performed in sync_transaction mode.

    NoOp Caching

    • Usage: Use the NoOp adapters when you do not want to cache specific data from Discord at all.
  7. Configure audio timeout and burst settings

    master

    Audio Timeout

    When invoking Nostrum.Voice.play/4, the player has an initial window to generate audio before timing out.

    • Default: 20_000 ms (20 seconds).
    • Post-start: Once audio begins transmitting, the timeout drops to 500 ms.
    • Use Case: If you are playing large files with significant seek times (e.g., via :ytdl), you may need to increase the timeout. If you need faster error detection for small files, you can decrease it.

    Audio Frames Per Burst

    Nostrum collects opus frames and sends them in a "burst" to reduce overhead.

    • Default: :audio_frames_per_burst is 10 (equivalent to 200ms of audio).
    • Important: If you attempt to play audio shorter than 200ms, it will time out because it is waiting to collect 10 frames. To play very short clips, set :audio_frames_per_burst to a lower value, such as 1.
  8. Manage internal state via Nostrum.Store

    master
    Nostrum's mandatory internal state is handled by modules located in the Nostrum.Store namespace. Unlike caches, which can be swapped for a NoOp implementation, internal state is required for the library to operate and follows a similar pluggable pattern to the caching system.
  9. Understand cache invalidation and expiration in Nostrum

    master

    Nostrum's cache invalidation behavior depends on the implementation:

    • General Behavior: Most caches are maintained in response to Gateway events (e.g., deleting a guild and its members when leaving a guild). Nostrum does not regularly prune caches or associate expiration times with entries.
    • Custom Implementations: If you implement a cache backend that persists to disk, you are responsible for managing expiration and pruning.
    • Exception (Nostrum.Cache.MessageCache.Mnesia): This specific implementation includes automatic management:
      • It has a default size limit of 10,000 messages.
      • When the limit is reached, it automatically removes the 100 oldest messages.
      • It deletes all cached messages for a channel when that channel is deleted.
  10. How ratelimiting works in Nostrum

    master

    Ratelimiting is managed internally by Nostrum to ensure compliance with Discord's limits. To benefit from automatic ratelimit handling, you must use one of the following:

    1. The specific methods provided in the Nostrum.Api submodules.
    2. The generic Nostrum.Api.request/4 function.

    All requests are funneled through the Nostrum.Api.Ratelimiter state machine, which ensures that requests are handled correctly whether they are called synchronously or asynchronously.

  11. How event handling works in Nostrum

    master

    Nostrum handles interactions from Discord via a websocket connection by dispatching events to consumers. When an event occurs (e.g., a message is created or a channel is deleted), Nostrum dispatches that event to:

    1. The primary consumer configured via Nostrum.Bot.bot_options/0.
    2. Any processes listening via Nostrum.ConsumerGroup.

    Events are dispatched to these consumers after they have been ingested into the cache. Nostrum.ConsumerGroup allows for dynamic subscriptions at runtime, which can function across different nodes in a cluster.

  12. Understand the difference between Caches and State in Nostrum

    master

    Nostrum manages data through two distinct mechanisms:

    1. Caches: Optional layers used to provide your bot with fresh, accessible data. By default, these use Erlang's ETS tables. You can replace these with custom implementations (e.g., for external caching or distributed nodes).
    2. State: Mandatory internal state required for Nostrum to function properly. This is managed via modules under Nostrum.Store and cannot be disabled via a NoOp implementation like caches can.