SupportMail reescribe su sistema de sharding con un supervisor en Go

Fuentes: Rewriting SupportMail's sharding system

SupportMail, un bot de Discord orientado a modmail, ha sustituido su antiguo sistema de sharding —basado en una bifurcación de la librería galactic.ts ejecutada dentro del proceso de Bun— por un supervisor externo escrito en Go, un nuevo cluster harness y una separación formal entre la API REST del bot y la lógica del propio bot.

El sharding divide los servidores de Discord (guilds) entre varias conexiones gateway, agrupadas en clústeres que son procesos independientes. Discord obliga a fragmentar cuando un bot supera cierto número de servidores, y la asignación de cada guild a un shard se calcula con la fórmula (guildId >> 22) % totalShards, un hash determinista que cualquier componente puede resolver sin preguntar.

El detonante de la reescritura fue un fallo de instrumentación: al usar Bun.spawn, child_process y worker threads desde dentro del proceso del bot, los eventos de error publicados por diagnostics_channel se perdían en silencio, lo que rompía Sentry. Parchear galactic.ts no era viable porque sus clases Instance/Cluster están acopladas a Bun y porque el calendario de lanzamientos de Bun se había estancado, con la última versión publicada hacía más de dos meses y un PR abierto sin señales de fusión. Además, la mayor parte de lo que gestionaba el orquestador era lógica de coordinación: discord.js ya soporta múltiples shards en un único proceso, así que el valor añadido real estaba en la orquestación, no en el sharding en sí.

Otra razón para abandonarlo fue la reutilización: el autor también desarrolla Ticketon, que podría necesitar la misma infraestructura, y un gestor atado al proceso de un bot concreto obligaría a reescribirlo entero. Se valoró Rust como lenguaje, pero se eligió Go porque su modelo de concurrencia (goroutines y canales) encaja directamente con supervisar N procesos y centralizar su IPC, y porque la biblioteca estándar de Go bastó para construir el supervisor, el hub de IPC y el WebSocket de estado casi sin dependencias externas.

La decisión de diseño clave es separar operaciones estructurales (REGISTER, HEARTBEAT, QUIESCE, QUIESCED y DEPLOY) de operaciones de negocio: el manager sm-manager solo entiende las estructurales y reenvía sin inspeccionar el resto, lo que lo hace independiente del bot. Si un día otro bot —por ejemplo Ticketon— quisiera usar la misma infraestructura, bastaría con un archivo de configuración distinto, sin tocar el código del manager.