EDA.Gateway.ReadyTracker (EDA v0.3.0)

Copy Markdown View Source

Tracks guild loading progress after READY to distinguish startup loads from runtime joins.

When Discord sends READY, it includes guild stubs (unavailable: true). Full guild data arrives via subsequent GUILD_CREATE events. This GenServer tracks which guilds are still loading and fires SHARD_READY / ALL_SHARDS_READY events when loading completes.

Uses an ETS table (:eda_pending_guilds) for O(1) lookups in the hot path and :persistent_term for the global ready flag.

Summary

Functions

Blocks until all shards have finished loading their guilds.

Returns a specification to start this module under a supervisor.

Marks a guild as loaded (received its GUILD_CREATE).

Returns true if the guild is still loading (pending GUILD_CREATE).

Returns true if all shards have finished loading their guilds.

Registers pending guilds for a shard after receiving READY.

Starts the ReadyTracker.

Returns detailed status information about the loading state.

Functions

await_ready(timeout \\ 60000)

@spec await_ready(timeout()) :: :ok | {:error, :timeout}

Blocks until all shards have finished loading their guilds.

Returns :ok when the bot is fully ready, or {:error, :timeout} if the timeout expires. Uses OTP's native GenServer.call suspension — no scheduler is blocked.

If the bot is already ready, returns :ok immediately.

Examples

EDA.await_ready()
EDA.await_ready(30_000)

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

guild_loaded(guild_id)

@spec guild_loaded(String.t()) :: :ok

Marks a guild as loaded (received its GUILD_CREATE).

Called by EDA.Gateway.Events when a startup GUILD_CREATE arrives.

loading?(guild_id)

@spec loading?(String.t()) :: boolean()

Returns true if the guild is still loading (pending GUILD_CREATE).

Reads directly from ETS — no GenServer call, O(1).

ready?()

@spec ready?() :: boolean()

Returns true if all shards have finished loading their guilds.

Non-blocking — reads from :persistent_term (O(1)).

shard_ready(shard_id, guild_ids)

@spec shard_ready(non_neg_integer(), [String.t()]) :: :ok

Registers pending guilds for a shard after receiving READY.

Called by EDA.Gateway.Connection when a READY payload arrives.

start_link(opts \\ [])

Starts the ReadyTracker.

status()

@spec status() :: map()

Returns detailed status information about the loading state.

Return value

A map with keys:

  • :globally_ready — whether all shards are ready
  • :ready_shards — set of shard IDs that finished loading
  • :expected_shards — total number of shards expected
  • :pending_counts — map of shard_id => remaining guild count