Class: DiscordRDA::ShardManager
- Inherits:
-
Object
- Object
- DiscordRDA::ShardManager
- Defined in:
- lib/discord_rda/connection/shard_manager.rb
Overview
Manages sharding for large Discord bots. Automatically calculates shard count and distributes guilds.
Constant Summary collapse
- GUILDS_PER_SHARD =
Maximum guilds per shard (Discord recommends 250, hard limit 2500)
1000
Instance Attribute Summary collapse
-
#config ⇒ Configuration
readonly
Configuration instance.
-
#logger ⇒ Logger
readonly
Logger instance.
-
#ready ⇒ Boolean
readonly
Whether all shards are ready.
-
#shard_count ⇒ Integer
readonly
Total number of shards.
-
#shards ⇒ Array<GatewayClient>
readonly
Active gateway clients.
-
#total_guilds ⇒ Integer
readonly
Total guilds across all shards.
Class Method Summary collapse
-
.shard_for_guild(guild_id, total_shards) ⇒ Integer
Get shard ID for a guild.
Instance Method Summary collapse
-
#calculate_shard_count(requested_shards, rest_client) ⇒ Integer
Calculate or retrieve shard count.
-
#fetch_session_info(rest_client) ⇒ Hash
Get session information from Discord.
-
#initialize(config, event_bus, logger, gateway_state: {}) ⇒ ShardManager
constructor
Initialize shard manager.
-
#reconnect_shard(shard_id) ⇒ void
Reconnect a specific shard.
-
#respawn(new_shard_count) ⇒ void
Spawn additional shards (hot scaling).
-
#shard(shard_id) ⇒ GatewayClient?
Get shard by ID.
-
#shard_ready?(shard_id) ⇒ Boolean
Check if shard is ready.
-
#start(shard_ids = nil) ⇒ void
Start all shards.
-
#status ⇒ Hash
Get status of all shards.
-
#stop ⇒ void
Stop all shards.
-
#update_guild_count(count) ⇒ void
Update total guild count.
Constructor Details
#initialize(config, event_bus, logger, gateway_state: {}) ⇒ ShardManager
Initialize shard manager
33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 33 def initialize(config, event_bus, logger, gateway_state: {}) @config = config @event_bus = event_bus @logger = logger @gateway_state = gateway_state || {} @shard_count = nil @shards = [] @total_guilds = nil @ready = false @mutex = Mutex.new end |
Instance Attribute Details
#config ⇒ Configuration (readonly)
Returns Configuration instance.
12 13 14 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 12 def config @config end |
#logger ⇒ Logger (readonly)
Returns Logger instance.
15 16 17 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 15 def logger @logger end |
#ready ⇒ Boolean (readonly)
Returns Whether all shards are ready.
27 28 29 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 27 def ready @ready end |
#shard_count ⇒ Integer (readonly)
Returns Total number of shards.
18 19 20 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 18 def shard_count @shard_count end |
#shards ⇒ Array<GatewayClient> (readonly)
Returns Active gateway clients.
21 22 23 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 21 def shards @shards end |
#total_guilds ⇒ Integer (readonly)
Returns Total guilds across all shards.
24 25 26 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 24 def total_guilds @total_guilds end |
Class Method Details
.shard_for_guild(guild_id, total_shards) ⇒ Integer
Get shard ID for a guild
68 69 70 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 68 def self.shard_for_guild(guild_id, total_shards) ((guild_id.to_i >> 22) % total_shards) end |
Instance Method Details
#calculate_shard_count(requested_shards, rest_client) ⇒ Integer
Calculate or retrieve shard count
49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 49 def calculate_shard_count(requested_shards, rest_client) if requested_shards == :auto # Fetch recommended shard count from Discord fetch_recommended_shards(rest_client) elsif requested_shards.is_a?(Array) && requested_shards.length == 1 && requested_shards[0] == :auto fetch_recommended_shards(rest_client) elsif requested_shards.is_a?(Array) && requested_shards.first.is_a?(Array) # Explicit shard ranges provided requested_shards.length else # Single shard or explicit count requested_shards.is_a?(Array) ? requested_shards[1] : 1 end end |
#fetch_session_info(rest_client) ⇒ Hash
Get session information from Discord
168 169 170 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 168 def fetch_session_info(rest_client) rest_client.get('/gateway/bot') end |
#reconnect_shard(shard_id) ⇒ void
This method returns an undefined value.
Reconnect a specific shard
139 140 141 142 143 144 145 146 147 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 139 def reconnect_shard(shard_id) shard = shard(shard_id) return unless shard @logger&.info('Reconnecting shard', shard: shard_id) shard.disconnect sleep(@config.initial_reconnect_delay) shard.connect end |
#respawn(new_shard_count) ⇒ void
This method returns an undefined value.
Spawn additional shards (hot scaling)
152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 152 def respawn(new_shard_count) return if new_shard_count <= @shard_count.to_i @logger&.info('Respawning with more shards', old: @shard_count, new: new_shard_count) # Start new shards ((@shard_count || 0)...new_shard_count).each do |shard_id| start_shard(shard_id, new_shard_count) end @shard_count = new_shard_count end |
#shard(shard_id) ⇒ GatewayClient?
Get shard by ID
100 101 102 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 100 def shard(shard_id) @shards.find { |s| s.instance_variable_get(:@shard_id) == shard_id } end |
#shard_ready?(shard_id) ⇒ Boolean
Check if shard is ready
125 126 127 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 125 def shard_ready?(shard_id) shard(shard_id)&.connected end |
#start(shard_ids = nil) ⇒ void
This method returns an undefined value.
Start all shards
75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 75 def start(shard_ids = nil) shard_count = @shard_count || 1 ids = shard_ids || (0...shard_count).to_a @logger&.info('Starting shards', count: ids.length, total: shard_count) ids.each do |shard_id| start_shard(shard_id, shard_count) end wait_for_ready end |
#status ⇒ Hash
Get status of all shards
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 106 def status { total_shards: @shard_count, active_shards: @shards.length, ready: @ready, guilds: @total_guilds, shard_statuses: @shards.map do |s| { id: s.instance_variable_get(:@shard_id), connected: s.connected, session: s.session_id } end } end |
#stop ⇒ void
This method returns an undefined value.
Stop all shards
90 91 92 93 94 95 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 90 def stop @logger&.info('Stopping all shards') @shards.each(&:disconnect) @shards.clear @ready = false end |
#update_guild_count(count) ⇒ void
This method returns an undefined value.
Update total guild count
132 133 134 |
# File 'lib/discord_rda/connection/shard_manager.rb', line 132 def update_guild_count(count) @total_guilds = count end |