CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-net-dv8tion--jda

Java Discord API - A comprehensive Java library for building Discord bots and applications

Pending
Overview
Eval results
Files

sharding.mddocs/

Sharding System

Multi-shard bot support for scaling beyond Discord's gateway limits with centralized management and cross-shard operations for large-scale Discord applications.

Capabilities

Shard Manager

Centralized management interface for multiple JDA shards with unified operations and monitoring.

/**
 * The ShardManager is a higher level abstraction for managing multiple shards.
 * It provides a unified interface for operating across multiple JDA instances.
 */
interface ShardManager {
    /** Get all JDA shards */
    List<JDA> getShards();
    
    /** Get JDA shards with specific status */
    List<JDA> getShards(JDA.Status status);
    
    /** Get specific shard by ID */
    JDA getShardById(int shardId);
    
    /** Get shard cache view */
    ShardCacheView getShardCache();
    
    /** Get shard that contains specific guild */
    JDA getShardFor(long guildId);
    JDA getShardFor(String guildId);
    
    /** Start specific shard */
    void start(int shardId);
    
    /** Restart specific shard */
    void restart(int shardId);
    
    /** Shutdown specific shard */
    void shutdown(int shardId);
    
    /** Shutdown all shards */
    void shutdown();
    
    /** Get average gateway ping across all shards */
    double getAverageGatewayPing();
    
    /** Get average shard status */
    JDA.Status getStatus();
    
    /** Set status across all shards */
    void setStatus(OnlineStatus status);
    
    /** Set activity across all shards */
    void setActivity(Activity activity);
    
    /** Set idle status across all shards */
    void setIdle(boolean idle);
    
    /** Set presence across all shards */
    void setPresence(OnlineStatus status, Activity activity, boolean idle);
    
    /** Get unified guild cache across all shards */
    SnowflakeCacheView<Guild> getGuildCache();
    
    /** Get guild by ID from any shard */
    Guild getGuildById(long guildId);
    Guild getGuildById(String guildId);
    
    /** Get guilds by name from all shards */
    List<Guild> getGuildsByName(String name, boolean ignoreCase);
    
    /** Get mutual guilds for user across all shards */
    List<Guild> getMutualGuilds(User user);
    
    /** Get unified user cache across all shards */
    SnowflakeCacheView<User> getUserCache();
    
    /** Get user by ID from any shard */
    User getUserById(long userId);
    User getUserById(String userId);
    
    /** Get users by name from all shards */
    List<User> getUsersByName(String name, boolean ignoreCase);
    
    /** Get total guild count across all shards */
    long getGuildTotal();
    
    /** Get total user count across all shards */
    long getUserTotal();
    
    /** Add event listeners to all shards */
    void addEventListener(Object... listeners);
    
    /** Remove event listeners from all shards */
    void removeEventListener(Object... listeners);
    
    /** Get registered event listeners */
    List<Object> getRegisteredListeners();
    
    /** Retrieve user from any shard */
    RestAction<User> retrieveUserById(long userId);
    RestAction<User> retrieveUserById(String userId);
    
    /** Get statistics for all shards */
    ShardStatistics getShardStatistics();
}

Usage Examples:

import net.dv8tion.jda.api.sharding.ShardManager;
import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder;

// Create shard manager
ShardManager shardManager = DefaultShardManagerBuilder.createDefault("BOT_TOKEN")
    .setShardsTotal(4)
    .addEventListeners(new MyEventListener())
    .setStatus(OnlineStatus.ONLINE)
    .setActivity(Activity.playing("on multiple shards"))
    .build();

// Wait for all shards to be ready
List<JDA> shards = shardManager.getShards();
for (JDA shard : shards) {
    try {
        shard.awaitReady();
        System.out.println("Shard " + shard.getShardInfo().getShardId() + " is ready");
    } catch (InterruptedException e) {
        System.err.println("Interrupted while waiting for shard to be ready");
    }
}

// Get statistics
long totalGuilds = shardManager.getGuildTotal();
long totalUsers = shardManager.getUserTotal();
double avgPing = shardManager.getAverageGatewayPing();

System.out.println("Total guilds: " + totalGuilds);
System.out.println("Total users: " + totalUsers);
System.out.println("Average ping: " + avgPing + "ms");

// Find guild across all shards
Guild targetGuild = shardManager.getGuildById("123456789");
if (targetGuild != null) {
    JDA shard = shardManager.getShardFor(targetGuild.getIdLong());
    System.out.println("Guild found on shard " + shard.getShardInfo().getShardId());
}

// Set presence across all shards
shardManager.setPresence(OnlineStatus.DO_NOT_DISTURB, 
    Activity.watching(totalGuilds + " servers"), false);

// Restart specific shard
shardManager.restart(2);

// Shutdown all shards
shardManager.shutdown();

Shard Manager Builder

Builder pattern for creating and configuring shard managers with comprehensive options.

/**
 * Builder for creating ShardManager instances with various configuration options.
 */
class DefaultShardManagerBuilder {
    /** Create with default settings */
    static DefaultShardManagerBuilder createDefault(String token);
    
    /** Create with minimal cache settings */
    static DefaultShardManagerBuilder createLight(String token);
    
    /** Create with custom intent settings */
    static DefaultShardManagerBuilder create(String token, GatewayIntent intent, GatewayIntent... intents);
    static DefaultShardManagerBuilder create(String token, Collection<GatewayIntent> intents);
    
    /** Set bot token */
    DefaultShardManagerBuilder setToken(String token);
    
    /** Set total number of shards */
    DefaultShardManagerBuilder setShardsTotal(int shardsTotal);
    
    /** Set specific shard range to manage */
    DefaultShardManagerBuilder setShards(int minShardId, int maxShardId);
    DefaultShardManagerBuilder setShards(int... shardIds);
    
    /** Enable specific gateway intents */
    DefaultShardManagerBuilder enableIntents(GatewayIntent... intents);
    DefaultShardManagerBuilder enableIntents(Collection<GatewayIntent> intents);
    
    /** Disable specific gateway intents */
    DefaultShardManagerBuilder disableIntents(GatewayIntent... intents);
    DefaultShardManagerBuilder disableIntents(Collection<GatewayIntent> intents);
    
    /** Set enabled intents */
    DefaultShardManagerBuilder setEnabledIntents(Collection<GatewayIntent> intents);
    
    /** Enable cache flags */
    DefaultShardManagerBuilder enableCache(CacheFlag... flags);
    DefaultShardManagerBuilder enableCache(Collection<CacheFlag> flags);
    
    /** Disable cache flags */
    DefaultShardManagerBuilder disableCache(CacheFlag... flags);
    DefaultShardManagerBuilder disableCache(Collection<CacheFlag> flags);
    
    /** Set member cache policy */
    DefaultShardManagerBuilder setMemberCachePolicy(MemberCachePolicy policy);
    
    /** Set chunking filter */
    DefaultShardManagerBuilder setChunkingFilter(ChunkingFilter filter);
    
    /** Set event manager */
    DefaultShardManagerBuilder setEventManagerProvider(IntFunction<IEventManager> eventManagerProvider);
    
    /** Add event listeners to all shards */
    DefaultShardManagerBuilder addEventListeners(Object... listeners);
    DefaultShardManagerBuilder addEventListenerProviders(IntFunction<Object>... providers);
    
    /** Remove event listeners */
    DefaultShardManagerBuilder removeEventListeners(Object... listeners);
    DefaultShardManagerBuilder removeEventListenerProviders(IntFunction<Object>... providers);
    
    /** Set initial status */
    DefaultShardManagerBuilder setStatus(OnlineStatus status);
    
    /** Set initial activity */
    DefaultShardManagerBuilder setActivity(Activity activity);
    
    /** Set idle status */
    DefaultShardManagerBuilder setIdle(boolean idle);
    
    /** Set HTTP client builder */
    DefaultShardManagerBuilder setHttpClientBuilder(OkHttpClient.Builder builder);
    
    /** Set HTTP client */
    DefaultShardManagerBuilder setHttpClient(OkHttpClient client);
    
    /** Set WebSocket factory */
    DefaultShardManagerBuilder setWebsocketFactory(WebSocketFactory factory);
    
    /** Set rate limit scheduler */
    DefaultShardManagerBuilder setRateLimitScheduler(ScheduledExecutorService scheduler, boolean shutdown);
    
    /** Set callback pool */
    DefaultShardManagerBuilder setCallbackPool(ExecutorService executor, boolean shutdown);
    
    /** Set event pool */
    DefaultShardManagerBuilder setEventPool(ExecutorService executor, boolean shutdown);
    
    /** Set audio pool */
    DefaultShardManagerBuilder setAudioPool(ScheduledExecutorService executor, boolean shutdown);
    
    /** Set session controller */
    DefaultShardManagerBuilder setSessionController(SessionController controller);
    
    /** Set voice dispatch interceptor */
    DefaultShardManagerBuilder setVoiceDispatchInterceptor(VoiceDispatchInterceptor interceptor);
    
    /** Set shard listeners */
    DefaultShardManagerBuilder setShardListenerProvider(IntFunction<ShardListener> provider);
    
    /** Set thread factory */
    DefaultShardManagerBuilder setThreadFactory(ThreadFactory threadFactory);
    
    /** Set compression type */
    DefaultShardManagerBuilder setCompression(Compression compression);
    
    /** Set gateway encoding */
    DefaultShardManagerBuilder setEncoding(GatewayEncoding encoding);
    
    /** Set large threshold */
    DefaultShardManagerBuilder setLargeThreshold(int threshold);
    
    /** Set maximum reconnect delay */
    DefaultShardManagerBuilder setMaxReconnectDelay(int maxReconnectDelay);
    
    /** Set maximum buffer size */
    DefaultShardManagerBuilder setMaxBufferSize(int bufferSize);
    
    /** Enable/disable config flags */
    DefaultShardManagerBuilder setFlag(ConfigFlag flag, boolean enable);
    
    /** Set context map */
    DefaultShardManagerBuilder setContextMap(ConcurrentMap<String, String> map);
    
    /** Build the shard manager */
    ShardManager build() throws LoginException;
}

Usage Examples:

// Basic shard manager setup
ShardManager basicShardManager = DefaultShardManagerBuilder.createDefault("BOT_TOKEN")
    .setShardsTotal(2)
    .build();

// Advanced shard manager configuration
ShardManager advancedShardManager = DefaultShardManagerBuilder.createDefault("BOT_TOKEN")
    .setShardsTotal(8)
    .setShards(0, 3) // Only manage shards 0-3
    .enableIntents(GatewayIntent.GUILD_MEMBERS, GatewayIntent.GUILD_PRESENCES)
    .setMemberCachePolicy(MemberCachePolicy.VOICE.or(MemberCachePolicy.OWNER))
    .setChunkingFilter(ChunkingFilter.NONE)
    .disableCache(CacheFlag.ACTIVITY, CacheFlag.CLIENT_STATUS)
    .addEventListeners(new MyShardedEventListener())
    .setStatus(OnlineStatus.ONLINE)
    .setActivity(Activity.playing("across " + 8 + " shards"))
    .setLargeThreshold(250)
    .build();

// Custom shard configuration per shard
ShardManager customShardManager = DefaultShardManagerBuilder.createDefault("BOT_TOKEN")
    .setShardsTotal(4)
    .addEventListenerProviders(shardId -> {
        // Different listeners per shard
        if (shardId == 0) {
            return new PrimaryShardListener();
        } else {
            return new SecondaryShardListener();
        }
    })
    .setEventManagerProvider(shardId -> {
        // Custom event manager per shard
        return new CustomEventManager("Shard-" + shardId);
    })
    .build();

// Light shard manager for memory efficiency
ShardManager lightShardManager = DefaultShardManagerBuilder.createLight("BOT_TOKEN", 
        EnumSet.of(GatewayIntent.GUILD_MESSAGES, GatewayIntent.MESSAGE_CONTENT))
    .setShardsTotal(4)
    .setMemberCachePolicy(MemberCachePolicy.NONE)
    .disableCache(CacheFlag.VOICE_STATE, CacheFlag.EMOJI, CacheFlag.STICKER)
    .build();

Shard Statistics and Monitoring

Comprehensive monitoring and statistics for shard performance and health.

/**
 * Interface for monitoring individual shard events and lifecycle.
 */
interface ShardListener {
    /** Called when shard comes online */
    void onShardReady(int shardId);
    
    /** Called when shard disconnects */
    void onShardDisconnect(int shardId, CloseCode closeCode, OffsetDateTime disconnectTime, boolean resumable);
    
    /** Called when shard resumes connection */
    void onShardResume(int shardId);
    
    /** Called when shard reconnects */
    void onShardReconnect(int shardId);
    
    /** Called when shard shuts down */
    void onShardShutdown(int shardId, OffsetDateTime shutdownTime);
}

/**
 * Cache view for accessing shards.
 */
interface ShardCacheView extends CacheView<JDA> {
    /** Get shard by ID */
    JDA getElementById(int shardId);
    
    /** Get all shards with specific status */
    List<JDA> getElementsByStatus(JDA.Status status);
    
    /** Get shard statistics */
    default ShardStatistics getStatistics() {
        return new ShardStatistics(asList());
    }
}

/**
 * Statistics and metrics for shard performance.
 */
class ShardStatistics {
    /** Get total number of shards */
    int getTotalShards();
    
    /** Get number of shards with specific status */
    int getShardCount(JDA.Status status);
    
    /** Get number of connected shards */
    int getConnectedShards();
    
    /** Get average gateway ping across all shards */
    double getAverageGatewayPing();
    
    /** Get minimum gateway ping */
    long getMinGatewayPing();
    
    /** Get maximum gateway ping */
    long getMaxGatewayPing();
    
    /** Get total guild count across all shards */
    long getTotalGuilds();
    
    /** Get total user count across all shards */
    long getTotalUsers();
    
    /** Get total cached entities count */
    long getTotalCachedEntities();
    
    /** Get memory usage per shard */
    Map<Integer, Long> getMemoryUsagePerShard();
    
    /** Get uptime per shard */
    Map<Integer, Duration> getUptimePerShard();
    
    /** Get guild distribution per shard */
    Map<Integer, Integer> getGuildDistribution();
    
    /** Get shard load balancing metrics */
    ShardLoadMetrics getLoadMetrics();
}

Usage Examples:

// Custom shard listener for monitoring
public class ShardMonitor implements ShardListener {
    private final TextChannel logChannel;
    private final Map<Integer, OffsetDateTime> shardStartTimes = new HashMap<>();
    
    public ShardMonitor(TextChannel logChannel) {
        this.logChannel = logChannel;
    }
    
    @Override
    public void onShardReady(int shardId) {
        shardStartTimes.put(shardId, OffsetDateTime.now());
        logChannel.sendMessage("✅ Shard " + shardId + " is ready").queue();
        
        // Log shard info
        JDA shard = shardManager.getShardById(shardId);
        if (shard != null) {
            String info = String.format("Shard %d: %d guilds, %d users, %dms ping",
                shardId,
                shard.getGuildCache().size(),
                shard.getUserCache().size(),
                shard.getGatewayPing());
            logChannel.sendMessage(info).queue();
        }
    }
    
    @Override
    public void onShardDisconnect(int shardId, CloseCode closeCode, OffsetDateTime disconnectTime, boolean resumable) {
        String status = resumable ? "⚠️ Disconnected (resumable)" : "❌ Disconnected (non-resumable)";
        String message = String.format("%s Shard %d: %s (%d)", 
            status, shardId, closeCode.getMeaning(), closeCode.getCode());
        logChannel.sendMessage(message).queue();
    }
    
    @Override
    public void onShardResume(int shardId) {
        logChannel.sendMessage("🔄 Shard " + shardId + " resumed").queue();
    }
    
    @Override
    public void onShardReconnect(int shardId) {
        logChannel.sendMessage("🔄 Shard " + shardId + " reconnected").queue();
    }
    
    @Override
    public void onShardShutdown(int shardId, OffsetDateTime shutdownTime) {
        Duration uptime = Duration.between(shardStartTimes.get(shardId), shutdownTime);
        String message = String.format("🛑 Shard %d shutdown after %d minutes uptime",
            shardId, uptime.toMinutes());
        logChannel.sendMessage(message).queue();
        shardStartTimes.remove(shardId);
    }
}

// Set up monitoring
ShardMonitor monitor = new ShardMonitor(logChannel);
ShardManager shardManager = DefaultShardManagerBuilder.createDefault("BOT_TOKEN")
    .setShardsTotal(4)
    .setShardListenerProvider(shardId -> monitor)
    .build();

// Regular statistics reporting
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
    ShardStatistics stats = shardManager.getShardStatistics();
    
    EmbedBuilder embed = new EmbedBuilder()
        .setTitle("Shard Statistics")
        .addField("Total Shards", String.valueOf(stats.getTotalShards()), true)
        .addField("Connected", String.valueOf(stats.getConnectedShards()), true)
        .addField("Average Ping", String.format("%.1fms", stats.getAverageGatewayPing()), true)
        .addField("Total Guilds", String.valueOf(stats.getTotalGuilds()), true)
        .addField("Total Users", String.valueOf(stats.getTotalUsers()), true)
        .addField("Memory Usage", formatMemoryUsage(stats.getMemoryUsagePerShard()), false)
        .setTimestamp(Instant.now())
        .setColor(Color.BLUE);
    
    logChannel.sendMessageEmbeds(embed.build()).queue();
}, 0, 1, TimeUnit.HOURS);

// Helper method for memory formatting
private String formatMemoryUsage(Map<Integer, Long> memoryUsage) {
    return memoryUsage.entrySet().stream()
        .map(entry -> String.format("Shard %d: %dMB", entry.getKey(), entry.getValue() / 1024 / 1024))
        .collect(Collectors.joining("\n"));
}

Cross-Shard Operations

Utility methods and patterns for operations that span multiple shards.

/**
 * Utility class for cross-shard operations.
 */
class ShardUtils {
    /** Execute operation on all shards */
    static <T> List<CompletableFuture<T>> executeOnAllShards(
        ShardManager shardManager, 
        Function<JDA, CompletableFuture<T>> operation);
    
    /** Execute operation on specific shards */
    static <T> List<CompletableFuture<T>> executeOnShards(
        ShardManager shardManager,
        Collection<Integer> shardIds,
        Function<JDA, CompletableFuture<T>> operation);
    
    /** Find optimal shard for operation */
    static JDA findOptimalShard(ShardManager shardManager, Predicate<JDA> criteria);
    
    /** Get total count across all shards */
    static long getTotalCount(ShardManager shardManager, Function<JDA, Long> counter);
    
    /** Distribute load across shards */
    static <T> Map<Integer, List<T>> distributeLoad(
        ShardManager shardManager,
        List<T> items,
        Function<T, Long> hashFunction);
}

Usage Examples:

// Cross-shard guild search
public CompletableFuture<List<Guild>> findGuildsByName(String name) {
    List<CompletableFuture<List<Guild>>> futures = ShardUtils.executeOnAllShards(
        shardManager,
        shard -> CompletableFuture.supplyAsync(() -> 
            shard.getGuildsByName(name, true))
    );
    
    return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
        .thenApply(v -> futures.stream()
            .flatMap(future -> future.join().stream())
            .collect(Collectors.toList()));
}

// Cross-shard message broadcasting
public void broadcastMessage(String message) {
    shardManager.getShards().parallelStream().forEach(shard -> {
        shard.getGuilds().stream()
            .map(Guild::getDefaultChannel)
            .filter(Objects::nonNull)
            .forEach(channel -> {
                channel.sendMessage(message).queue(
                    success -> {},
                    error -> System.err.println("Failed to send to " + channel.getGuild().getName())
                );
            });
    });
}

// Load balancing for processing
public void processGuildsBalanced(List<String> guildIds) {
    Map<Integer, List<String>> distribution = ShardUtils.distributeLoad(
        shardManager,
        guildIds,
        guildId -> Long.parseLong(guildId)
    );
    
    distribution.forEach((shardId, guildList) -> {
        JDA shard = shardManager.getShardById(shardId);
        CompletableFuture.runAsync(() -> {
            guildList.forEach(guildId -> {
                Guild guild = shard.getGuildById(guildId);
                if (guild != null) {
                    processGuild(guild);
                }
            });
        });
    });
}

// Cross-shard statistics collection
public ShardHealthReport generateHealthReport() {
    Map<Integer, CompletableFuture<ShardHealth>> healthFutures = 
        shardManager.getShards().stream()
            .collect(Collectors.toMap(
                shard -> shard.getShardInfo().getShardId(),
                this::collectShardHealth
            ));
    
    // Wait for all health checks to complete
    CompletableFuture.allOf(healthFutures.values().toArray(new CompletableFuture[0])).join();
    
    Map<Integer, ShardHealth> healthMap = healthFutures.entrySet().stream()
        .collect(Collectors.toMap(
            Map.Entry::getKey,
            entry -> entry.getValue().join()
        ));
    
    return new ShardHealthReport(healthMap);
}

private CompletableFuture<ShardHealth> collectShardHealth(JDA shard) {
    return CompletableFuture.supplyAsync(() -> {
        return ShardHealth.builder()
            .shardId(shard.getShardInfo().getShardId())
            .status(shard.getStatus())
            .ping(shard.getGatewayPing())
            .guildCount(shard.getGuildCache().size())
            .userCount(shard.getUserCache().size())
            .uptime(Duration.between(shard.getTimeCreated(), Instant.now()))
            .build();
    });
}

Types

// Shard information
class ShardInfo {
    /** Get shard ID (0-based) */
    int getShardId();
    
    /** Get total shard count */
    int getShardTotal();
    
    /** Get string representation (id/total) */
    String getShardString();
}

// Session controller for coordinating shard logins
interface SessionController {
    /** Get gateway information */
    CompletableFuture<SessionController.Gateway> getGateway();
    
    /** Request session identifier */
    SessionController.SessionConnectNode appendSession(SessionController.SessionConnectNode node);
    
    /** Remove session from queue */
    void removeSession(SessionController.SessionConnectNode node);
    
    /** Get remaining session starts */
    int getRemainingStarts();
    
    /** Get session start limit reset time */
    long getSessionStartLimitResetTime();
}

// Chunking filter for member loading
enum ChunkingFilter {
    ALL, NONE;
    
    /** Create filter that includes specific guilds */
    static ChunkingFilter include(long... guildIds);
    
    /** Create filter that excludes specific guilds */
    static ChunkingFilter exclude(long... guildIds);
    
    /** Filter guilds */
    boolean filter(long guildId);
}

// Member cache policy
enum MemberCachePolicy {
    ALL, OWNER, VOICE, ONLINE, PENDING, NONE;
    
    /** Combine policies with OR logic */
    MemberCachePolicy or(MemberCachePolicy policy);
    
    /** Combine policies with AND logic */
    MemberCachePolicy and(MemberCachePolicy policy);
    
    /** Create policy for specific users */
    static MemberCachePolicy of(Collection<User> users);
    
    /** Check if member should be cached */
    boolean cacheMember(Member member);
}

// Compression types
enum Compression {
    NONE, ZLIB
}

// Gateway encoding
enum GatewayEncoding {
    JSON, ETF
}

// Config flags for JDA behavior
enum ConfigFlag {
    SHUTDOWN_HOOK, BULK_DELETE_SPLITTING, AUTO_RECONNECT, 
    BUFFER_POOL, LAZY_LOADING, MEMBER_CACHE_CHUNKING,
    USE_SHUTDOWN_NOW;
    
    /** Get default config flags */
    static EnumSet<ConfigFlag> getDefault();
}

Install with Tessl CLI

npx tessl i tessl/maven-net-dv8tion--jda

docs

audio.md

core-management.md

entities.md

events.md

index.md

interactions.md

messaging.md

restactions.md

sharding.md

tile.json