O que o sharding resolve
O Discord exige sharding para bots presentes em mais de 2.500 guilds. Cada shard é uma conexão WebSocket separada, responsável por um subconjunto dessas guilds. Sem sharding, a conexão única vira gargalo e o Discord simplesmente deixa de aceitar a conexão quando o bot passa desse limite. Mesmo abaixo de 2.500 guilds, sharding pode melhorar a confiabilidade porque isola falhas em um shard, em vez de derrubar o bot inteiro.
O SpraxiumShardManager encapsula o ShardingManager do discord.js e adiciona logging de lifecycle, tratamento de erro para rate limit, suporte automático a processos filhos em TypeScript, handlers de shutdown limpo e uma tabela-resumo impressa depois que todos os shards ficam prontos. A configuração acontece via useSharding em main.ts, e o framework cuida do resto.
Quando o sharding está ativado, o processo principal, o processo pai, não conecta no gateway por conta própria. Em vez disso, ele sobe processos filhos, um por shard. Cada processo filho roda o bot completo, incluindo listeners, comandos e serviços. O pai apenas gerencia esses filhos e coleta o status deles.
Ativando o sharding
Chame useSharding no builder da aplicação em main.ts, pelo menos com um valor para totalShards. Definir 'auto' faz o Discord decidir a quantidade ideal de shards com base no número de guilds do bot e no valor recomendado retornado por /gateway/bot. Para bots pequenos ou ambiente de desenvolvimento, vale usar um número fixo como 1 ou 2.
import { SpraxiumFactory } from '@spraxium/core';
import { AppModule } from './app.module';
async function main() {
const app = await SpraxiumFactory.create({
token: process.env.DISCORD_TOKEN,
});
app.useModule(AppModule);
app.useSharding({ totalShards: 'auto' });
await app.listen();
}
main();Você também pode aplicar a configuração de sharding condicionalmente com base em um check de runtime. Isso é útil quando o mesmo arquivo de entrada precisa rodar em processo único no desenvolvimento e em modo sharded na produção.
import { SpraxiumFactory } from '@spraxium/core';
import { AppModule } from './app.module';
async function main() {
const app = await SpraxiumFactory.create({
token: process.env.DISCORD_TOKEN,
});
app.useModule(AppModule);
if (process.env.ENABLE_SHARDING === 'true') {
app.useSharding({ totalShards: 'auto' });
}
await app.listen();
}
main();Opções de shard
A interface ShardOptions aceita quatro campos. Só totalShards é obrigatório. Os padrões foram pensados para funcionar sem ajuste na maioria dos bots, respeitando o identify rate limit do Discord com um atraso seguro de 5,5 segundos entre spawns.
| Opção | Tipo | Padrão | Descrição |
|---|---|---|---|
| totalShards | Número ou auto | (obrigatório) | Quantidade de shards para subir, ou auto para deixar a decisão com o Discord. |
| shardList | Lista de números | todos os shards | Subconjunto de IDs de shard que devem ser iniciados. Útil para rodar shards específicos em máquinas específicas. |
| respawn | boolean | true | Define se um shard deve ser reiniciado automaticamente ao cair. |
| spawnDelay | number | 5500 | Tempo, em milissegundos, entre o spawn de um shard e outro, respeitando o identify rate limit. |
Ciclo de spawn
Quando o bot sobe com sharding ativado, o processo pai percorre uma sequência bem definida. Primeiro ele cria um ShardingManager do discord.js apontando para o seu arquivo de entrada. Depois sobe os processos filhos um por um, com o delay configurado. Cada filho conecta no gateway do Discord, dispara clientReady e reporta a quantidade de guilds de volta ao processo pai. Quando todos os shards ficam prontos, o pai imprime uma tabela-resumo.
O processo pai escuta três eventos em cada shard: disconnect, reconnecting e death. Desconexões e reconexões entram no log como aviso. Mortes entram como erro e, se respawn estiver ligado, o discord.js sobe automaticamente um processo substituto. O pai continua rodando enquanto pelo menos um shard continuar vivo.
Durante o spawn, a saída do terminal fica parecida com isto. Cada shard informa o próprio status e a quantidade de guilds quando fica pronto, seguido por uma linha-resumo com a tag do bot, o total de shards, o total de guilds e o tempo de startup.
[bot] spraxium v1.0.0 discord.js v14.x
[spawn] Sharding spawning 3 shards...
⬺ Shard 0 ready (1200 guilds)
⬺ Shard 1 ready (1150 guilds)
⬺ Shard 2 ready (980 guilds)
[ready] MyBot#1234 · 3 shards · 3330 total guilds · ready in 18200msDetectando processos filhos de shard
A função utilitária isShardChild retorna true quando o processo atual foi iniciado pelo ShardingManager. O discord.js injeta a variável de ambiente SHARDS em cada processo filho, e isShardChild verifica justamente a presença dessa variável. Isso é útil para pular setup que só deve rodar uma vez no processo pai, como imprimir banner ou registrar slash commands globais.
import { Injectable } from '@spraxium/core';
import { isShardChild } from '@spraxium/core';
@Injectable()
export class StartupService {
async onApplicationBoot() {
if (isShardChild()) return;
console.log('Running parent-only initialization');
}
}O framework usa isShardChild internamente para pular o banner de startup nos processos filhos, evitando saída duplicada em N shards, e também para suprimir a mensagem “Logged in as”, que do contrário apareceria N vezes.
Aviso para desenvolvimento
Quando o sharding está ativo no modo de desenvolvimento (NODE_ENV=development), o framework registra um aviso. Vários processos de shard deixam os restarts mais lentos, aumentam o uso de memória e elevam a chance de atingir rate limits do Discord quando você reinicia o bot com frequência. Em desenvolvimento, prefira uma única instância, seja deixando sharding desligado, seja definindo totalShards como 1.
import { SpraxiumFactory } from '@spraxium/core';
import { AppModule } from './app.module';
async function main() {
const app = await SpraxiumFactory.create({
token: process.env.DISCORD_TOKEN,
});
app.useModule(AppModule);
app.useSharding({
totalShards: process.env.NODE_ENV === 'production' ? 'auto' : 1,
});
await app.listen();
}
main();