How to handle multiple slash commands simultaenously?

When multiple people run slash commands on my bot, it always makes the commands fail until the current process is completed. How do I make it so people can use multiple commands at the same time?
31 Replies
d.js toolkit
d.js toolkit4w ago
- What's your exact discord.js npm list discord.js and node node -v version? - Not a discord.js issue? Check out #other-js-ts. - Consider reading #how-to-get-help to improve your question! - Explain what exactly your issue is. - Post the full error stack trace, not just the top part! - Show your code! - Issue solved? Press the button!
Dcom 🎈
Dcom 🎈OP4w ago
discord.js 18
Amgelo
Amgelo4w ago
you must be in the future because latest version is v14 this is only your code for deploying commands the relevant code would be the one that handles it
Dcom 🎈
Dcom 🎈OP4w ago
oh one sec v20.16.0 are you sure the latest version is 14?
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
Amgelo
Amgelo4w ago
that's your node version not your djs version
Amgelo
Amgelo4w ago
correct
Amgelo
Amgelo4w ago
your node version isn't the same as your djs version you're in v14 then what about this
Dcom 🎈
Dcom 🎈OP4w ago
here's another one also
Dcom 🎈
Dcom 🎈OP4w ago
when someone runs /xbox and someone runs /profile, the bot doesn't show both, it only shows xbox once it's loaded in. Seems like it can't handle multiple commands at a time. Same goes for slash commands that do other things. For example, this one
const { Pool } = require('pg'); // PostgreSQL client for database operations

// Set up a PostgreSQL connection pool with SSL
const pool = new Pool({
connectionString: process.env.DATABASE_URL, // Ensure you're using your connection string from an env variable
ssl: {
rejectUnauthorized: false, // Required for some remote databases like Heroku
},
});

const organizerUserIDs = [
"1099081303963476032",
"144942127355265024",
"943917480789803069",
"395397368872304642",
"678727362229305344",
];

module.exports = {
name: 'levi',
description: 'Add or remove points for a player by setting the exact number of points.',
async execute(interaction) {
// Check if the user is authorized
if (!organizerUserIDs.includes(interaction.user.id)) {
return interaction.reply({ content: 'You are not authorized to use this command.', ephemeral: true });
}

// Get user input (discord_id and points)
const discordId = interaction.options.getString('discord_id'); // Discord ID of the player
const points = interaction.options.getInteger('points'); // Exact points value to set

if (!discordId || points === null) {
return interaction.reply({ content: 'Please provide both a valid Discord ID and the number of points to set.', ephemeral: true });
}

// SQL query to update the player's points to the exact number
const query = `
UPDATE players
SET points = $1
WHERE discord_id = $2;
`;

const values = [points, discordId];

try {
// Execute the database query
const result = await pool.query(query, values);

if (result.rowCount === 0) {
return interaction.reply({ content: `No player found with Discord ID ${discordId}.`, ephemeral: true });
}

// Send confirmation message
await interaction.reply({
content: `Successfully updated the points for Discord ID ${discordId} to ${points}.`,
ephemeral: true,
});
} catch (err) {
console.error('Database error:', err);

// Send error message
await interaction.reply({ content: 'There was an error updating the player points.', ephemeral: true });
}
},
};
const { Pool } = require('pg'); // PostgreSQL client for database operations

// Set up a PostgreSQL connection pool with SSL
const pool = new Pool({
connectionString: process.env.DATABASE_URL, // Ensure you're using your connection string from an env variable
ssl: {
rejectUnauthorized: false, // Required for some remote databases like Heroku
},
});

const organizerUserIDs = [
"1099081303963476032",
"144942127355265024",
"943917480789803069",
"395397368872304642",
"678727362229305344",
];

module.exports = {
name: 'levi',
description: 'Add or remove points for a player by setting the exact number of points.',
async execute(interaction) {
// Check if the user is authorized
if (!organizerUserIDs.includes(interaction.user.id)) {
return interaction.reply({ content: 'You are not authorized to use this command.', ephemeral: true });
}

// Get user input (discord_id and points)
const discordId = interaction.options.getString('discord_id'); // Discord ID of the player
const points = interaction.options.getInteger('points'); // Exact points value to set

if (!discordId || points === null) {
return interaction.reply({ content: 'Please provide both a valid Discord ID and the number of points to set.', ephemeral: true });
}

// SQL query to update the player's points to the exact number
const query = `
UPDATE players
SET points = $1
WHERE discord_id = $2;
`;

const values = [points, discordId];

try {
// Execute the database query
const result = await pool.query(query, values);

if (result.rowCount === 0) {
return interaction.reply({ content: `No player found with Discord ID ${discordId}.`, ephemeral: true });
}

// Send confirmation message
await interaction.reply({
content: `Successfully updated the points for Discord ID ${discordId} to ${points}.`,
ephemeral: true,
});
} catch (err) {
console.error('Database error:', err);

// Send error message
await interaction.reply({ content: 'There was an error updating the player points.', ephemeral: true });
}
},
};
I can't run this while someone in the server has used another slash command. I have to wait for the command to fully process before I can run it. Otherwise, it times out. No console errors though, so i'm confused.
Amgelo
Amgelo4w ago
what about the code that listens to interactionCreate and routes interactions to your commands?
Dcom 🎈
Dcom 🎈OP4w ago
client.on("interactionCreate", async (interaction) => {
if (!interaction.isCommand()) return;

const commandName = interaction.commandName;
const userId = interaction.user.id;

const command = client.commands.get(commandName);
if (!command) return;

try {
await command.execute(interaction, pool, logChannelId, userId); // Pass necessary parameters to the command
console.log(`Command executed: ${commandName}`);
} catch (error) {
handleError(error, `interactionCreate - ${commandName}`);
await interaction.reply({
content: "There was an error while executing this command!",
ephemeral: true,
});
}
});
client.on("interactionCreate", async (interaction) => {
if (!interaction.isCommand()) return;

const commandName = interaction.commandName;
const userId = interaction.user.id;

const command = client.commands.get(commandName);
if (!command) return;

try {
await command.execute(interaction, pool, logChannelId, userId); // Pass necessary parameters to the command
console.log(`Command executed: ${commandName}`);
} catch (error) {
handleError(error, `interactionCreate - ${commandName}`);
await interaction.reply({
content: "There was an error while executing this command!",
ephemeral: true,
});
}
});
Amgelo
Amgelo4w ago
what is your pool variable? because my first thought is that your db is the one blocking you
Dcom 🎈
Dcom 🎈OP4w ago
const { Pool } = require("pg");
require("dotenv").config();

// Initialize the PostgreSQL connection pool
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});

pool
.connect()
.then(() => {
console.log("Connected to PostgreSQL database!");
})
.catch((err) => handleError(err, "PostgreSQL Connection"));
const { Pool } = require("pg");
require("dotenv").config();

// Initialize the PostgreSQL connection pool
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});

pool
.connect()
.then(() => {
console.log("Connected to PostgreSQL database!");
})
.catch((err) => handleError(err, "PostgreSQL Connection"));
here's the full bot.js file
const fs = require("fs");
const path = require("path");
const {
Client,
GatewayIntentBits,
Collection,
EmbedBuilder,
} = require("discord.js");
const dotenv = require("dotenv");
dotenv.config();
const { Pool } = require("pg");

// Logging setup
const logFile = fs.createWriteStream("./bot.log", { flags: "a" });
const logChannelId = "1299771372058443776"; // Logging channel ID

// Centralized error handler with logging
function handleError(error, context) {
console.error(`Error in ${context}:`, error);
logFile.write(
`[${new Date().toISOString()}] Error in ${context}: ${error}\n`,
);
}

// Initialize the PostgreSQL connection pool
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});

pool
.connect()
.then(() => {
console.log("Connected to PostgreSQL database!");
logFile.write(
`[${new Date().toISOString()}] Connected to PostgreSQL database!\n`,
);
})
.catch((err) => handleError(err, "PostgreSQL Connection"));

// Initialize the Discord.js client
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildVoiceStates,
],
});
console.log(`Initialized Discord.js Client`);

// Log successful login
client.once("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
logFile.write(
`[${new Date().toISOString()}] Logged in as ${client.user.tag}!\n`,
);
});

// Load commands from the commands directory
client.commands = new Collection();
const commandFiles = fs
.readdirSync("./commands")
.filter((file) => file.endsWith(".js"));

for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}

// Handle interactions (Slash commands)
client.on("interactionCreate", async (interaction) => {
if (!interaction.isCommand()) return;

const commandName = interaction.commandName;
const userId = interaction.user.id;

const command = client.commands.get(commandName);
if (!command) return;

try {
await command.execute(interaction, pool, logChannelId, userId); // Pass necessary parameters to the command
console.log(`Command executed: ${commandName}`);
} catch (error) {
handleError(error, `interactionCreate - ${commandName}`);
await interaction.reply({
content: "There was an error while executing this command!",
ephemeral: true,
});
}
});

// Error handling
process.on("uncaughtExceptionMonitor", (error) => {
console.error("Uncaught exception monitor:", error);
});

process.on("unhandledRejection", (error) => {
console.error("Unhandled promise rejection:", error);
});

process.on("uncaughtException", (error) => {
console.error("Uncaught exception:", error);
});

// Graceful shutdown process
process.on("SIGINT", async () => {
console.log("Bot is shutting down...");
await pool.end(); // Close the database connection
client.destroy(); // Disconnect the bot from Discord
process.exit(0);
});

// Login the bot
client.login(process.env.BOT_TOKEN);
const fs = require("fs");
const path = require("path");
const {
Client,
GatewayIntentBits,
Collection,
EmbedBuilder,
} = require("discord.js");
const dotenv = require("dotenv");
dotenv.config();
const { Pool } = require("pg");

// Logging setup
const logFile = fs.createWriteStream("./bot.log", { flags: "a" });
const logChannelId = "1299771372058443776"; // Logging channel ID

// Centralized error handler with logging
function handleError(error, context) {
console.error(`Error in ${context}:`, error);
logFile.write(
`[${new Date().toISOString()}] Error in ${context}: ${error}\n`,
);
}

// Initialize the PostgreSQL connection pool
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});

pool
.connect()
.then(() => {
console.log("Connected to PostgreSQL database!");
logFile.write(
`[${new Date().toISOString()}] Connected to PostgreSQL database!\n`,
);
})
.catch((err) => handleError(err, "PostgreSQL Connection"));

// Initialize the Discord.js client
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildVoiceStates,
],
});
console.log(`Initialized Discord.js Client`);

// Log successful login
client.once("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
logFile.write(
`[${new Date().toISOString()}] Logged in as ${client.user.tag}!\n`,
);
});

// Load commands from the commands directory
client.commands = new Collection();
const commandFiles = fs
.readdirSync("./commands")
.filter((file) => file.endsWith(".js"));

for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}

// Handle interactions (Slash commands)
client.on("interactionCreate", async (interaction) => {
if (!interaction.isCommand()) return;

const commandName = interaction.commandName;
const userId = interaction.user.id;

const command = client.commands.get(commandName);
if (!command) return;

try {
await command.execute(interaction, pool, logChannelId, userId); // Pass necessary parameters to the command
console.log(`Command executed: ${commandName}`);
} catch (error) {
handleError(error, `interactionCreate - ${commandName}`);
await interaction.reply({
content: "There was an error while executing this command!",
ephemeral: true,
});
}
});

// Error handling
process.on("uncaughtExceptionMonitor", (error) => {
console.error("Uncaught exception monitor:", error);
});

process.on("unhandledRejection", (error) => {
console.error("Unhandled promise rejection:", error);
});

process.on("uncaughtException", (error) => {
console.error("Uncaught exception:", error);
});

// Graceful shutdown process
process.on("SIGINT", async () => {
console.log("Bot is shutting down...");
await pool.end(); // Close the database connection
client.destroy(); // Disconnect the bot from Discord
process.exit(0);
});

// Login the bot
client.login(process.env.BOT_TOKEN);
Amgelo
Amgelo4w ago
check this
Dcom 🎈
Dcom 🎈OP4w ago
Ohhh If you don't release the client your application will leak them and eventually your pool will be empty forever and all future requests to check out a client from the pool will wait forever. So that's why it's not working.
Amgelo
Amgelo4w ago
though it looks like you use pool.query() directly not a client from it
Dcom 🎈
Dcom 🎈OP4w ago
Hmm, so if I follow the instructions in that link, it will allow simultaenous commands?
Amgelo
Amgelo4w ago
it confused me because your parameters are called dbClient but they're actually a pool now I'm not sure if you're affected by that why do you make another pool here though?
Dcom 🎈
Dcom 🎈OP4w ago
aren't I supposed to?
Amgelo
Amgelo4w ago
you're supossed to only have one pool the whole purpose of the pool is to be re-used so it can manage clients efficiently across all the program's objects that need access to the db
Dcom 🎈
Dcom 🎈OP4w ago
Ah I see, that's good to know. How am I doing so far otherwise? total bot has 55,000 lines of code, spent 3 months, 12 hours+ a day Myself and 2 other devs worked on it.
Amgelo
Amgelo4w ago
tbh it doesn't look like a djs issue, and I'm not quite sure what the problem could be when you use the command while another one is "in progress", does it at least defer?
Erick
Erick4w ago
it may be from your database, i had these problems too when i was using mongodb and my bot was handling a lot of commands per second from users
Dcom 🎈
Dcom 🎈OP4w ago
i hope not, postgre gives me a headache no, it just says "this interaction has failed"
Want results from more Discord servers?
Add your server