fix docker stats interval
This commit is contained in:
@ -7,6 +7,74 @@ const clients = new Map();
|
|||||||
const staticEndpoints = ['log', 'website', 'map', 'my-link-cache', 'my-geyser-cache', 'my-sftp-cache', 'my-link', 'my-geyser-link', 'my-sftp'];
|
const staticEndpoints = ['log', 'website', 'map', 'my-link-cache', 'my-geyser-cache', 'my-sftp-cache', 'my-link', 'my-geyser-link', 'my-sftp'];
|
||||||
const dynamicEndpoints = ['hello', 'time', 'mod-list'];
|
const dynamicEndpoints = ['hello', 'time', 'mod-list'];
|
||||||
|
|
||||||
|
// Helper function to start Docker stats interval
|
||||||
|
function startDockerStatsInterval(ws, client, user, docker) {
|
||||||
|
if (!client.subscriptions.has('docker') || user === 'Unknown') {
|
||||||
|
console.log(`Skipping docker stats interval: ${user === 'Unknown' ? 'User unknown' : 'Not subscribed to docker'}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send initial stats immediately
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const initialStats = await getContainerStats(docker, user);
|
||||||
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ type: 'docker', data: { ...initialStats, user } }));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error sending initial docker stats for ${user}:`, error.message);
|
||||||
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ type: 'docker', error: `Failed to fetch initial stats: ${error.message}` }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Start interval for periodic stats
|
||||||
|
const intervalId = setInterval(async () => {
|
||||||
|
try {
|
||||||
|
if (ws.readyState !== ws.OPEN) {
|
||||||
|
console.warn(`WebSocket not open (state: ${ws.readyState}) for ${user}, clearing docker stats interval ${intervalId}`);
|
||||||
|
clearInterval(intervalId);
|
||||||
|
client.intervals = client.intervals.filter(id => id !== intervalId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const container = docker.getContainer(user);
|
||||||
|
const inspect = await container.inspect();
|
||||||
|
if (inspect.State.Status !== 'running') {
|
||||||
|
console.log(`Container ${user} not running, sending error`);
|
||||||
|
ws.send(JSON.stringify({ type: 'docker', error: `Container ${user} is not running` }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stats = await getContainerStats(docker, user);
|
||||||
|
if (stats.error) {
|
||||||
|
console.error(`Error fetching stats for ${user}: ${stats.error}`);
|
||||||
|
ws.send(JSON.stringify({ type: 'docker', error: stats.error }));
|
||||||
|
} else {
|
||||||
|
ws.send(JSON.stringify({ type: 'docker', data: { ...stats, user } }));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error in docker stats interval for ${user}:`, error.message);
|
||||||
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ type: 'docker', error: `Failed to fetch stats: ${error.message}` }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 1000); // 1-second interval
|
||||||
|
|
||||||
|
client.intervals.push(intervalId);
|
||||||
|
console.log(`Docker stats interval ID ${intervalId} added for ${user}`);
|
||||||
|
|
||||||
|
// Test interval to verify setInterval execution
|
||||||
|
const testIntervalId = setInterval(() => {
|
||||||
|
// console.log(`Test interval tick for ${user} at ${new Date().toISOString()}, Interval ID: ${testIntervalId}`);
|
||||||
|
}, 2000); // 2-second test interval
|
||||||
|
client.intervals.push(testIntervalId);
|
||||||
|
// console.log(`Test interval ID ${testIntervalId} added for ${user}`);
|
||||||
|
|
||||||
|
return intervalId;
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchAndSendUpdate(ws, endpoint, client, docker) {
|
async function fetchAndSendUpdate(ws, endpoint, client, docker) {
|
||||||
if (['mod-list', 'list-players'].includes(endpoint) && client.user !== 'Unknown') {
|
if (['mod-list', 'list-players'].includes(endpoint) && client.user !== 'Unknown') {
|
||||||
try {
|
try {
|
||||||
@ -81,9 +149,13 @@ async function fetchAndSendUpdate(ws, endpoint, client, docker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ws.send(JSON.stringify({ type: endpoint, data: response }));
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ type: endpoint, data: response }));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ws.send(JSON.stringify({ type: endpoint, error: response.error }));
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ type: endpoint, error: response.error }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,11 +165,14 @@ async function manageStatusChecks(ws, client, user, docker) {
|
|||||||
const inspect = await container.inspect();
|
const inspect = await container.inspect();
|
||||||
const isRunning = inspect.State.Status === 'running';
|
const isRunning = inspect.State.Status === 'running';
|
||||||
|
|
||||||
client.intervals.forEach(clearInterval);
|
// Clear only status check intervals to prevent duplicates
|
||||||
client.intervals = [];
|
|
||||||
['connectionStatusInterval', 'geyserStatusInterval', 'sftpStatusInterval', 'statusCheckMonitorInterval'].forEach((key) => {
|
['connectionStatusInterval', 'geyserStatusInterval', 'sftpStatusInterval', 'statusCheckMonitorInterval'].forEach((key) => {
|
||||||
if (client[key]) clearInterval(client[key]);
|
if (client[key]) {
|
||||||
client[key] = null;
|
console.log(`Clearing ${key} for ${user}`);
|
||||||
|
clearInterval(client[key]);
|
||||||
|
client[key] = null;
|
||||||
|
client.intervals = client.intervals.filter(id => id !== client[key]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isRunning || user === 'Unknown') {
|
if (!isRunning || user === 'Unknown') {
|
||||||
@ -165,16 +240,21 @@ async function manageStatusChecks(ws, client, user, docker) {
|
|||||||
console.log(`Container ${user} stopped, clearing ${statusType} interval`);
|
console.log(`Container ${user} stopped, clearing ${statusType} interval`);
|
||||||
clearInterval(client[intervalKey]);
|
clearInterval(client[intervalKey]);
|
||||||
client[intervalKey] = null;
|
client[intervalKey] = null;
|
||||||
|
client.intervals = client.intervals.filter(id => id !== client[intervalKey]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const data = client.cache[cacheKey];
|
const data = client.cache[cacheKey];
|
||||||
if (data && data.hostname && data.port) {
|
if (data && data.hostname && data.port) {
|
||||||
const status = await checkFn(data.hostname, data.port);
|
const status = await checkFn(data.hostname, data.port);
|
||||||
ws.send(JSON.stringify({ type: statusType, data: { isOnline: status.isOnline } }));
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ type: 'connection-status', data: { isOnline: status.isOnline } }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error in ${statusType} check for ${user}:`, error.message);
|
console.error(`Error in ${statusType} check for ${user}:`, error.message);
|
||||||
ws.send(JSON.stringify({ type: statusType, data: { isOnline: false, error: error.message } }));
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ type: statusType, data: { isOnline: false, error: error.message } }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, parseInt(intervalMs, 10));
|
}, parseInt(intervalMs, 10));
|
||||||
client.intervals.push(client[intervalKey]);
|
client.intervals.push(client[intervalKey]);
|
||||||
@ -183,7 +263,9 @@ async function manageStatusChecks(ws, client, user, docker) {
|
|||||||
if (data && data.hostname && data.port) {
|
if (data && data.hostname && data.port) {
|
||||||
console.log(`Performing initial ${statusType} check for ${user}`);
|
console.log(`Performing initial ${statusType} check for ${user}`);
|
||||||
const status = await checkFn(data.hostname, data.port);
|
const status = await checkFn(data.hostname, data.port);
|
||||||
ws.send(JSON.stringify({ type: statusType, data: { isOnline: status.isOnline } }));
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ type: statusType, data: { isOnline: status.isOnline } }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,14 +294,32 @@ export function handleWebSocket(ws, req, docker) {
|
|||||||
connectionStatusInterval: null,
|
connectionStatusInterval: null,
|
||||||
geyserStatusInterval: null,
|
geyserStatusInterval: null,
|
||||||
sftpStatusInterval: null,
|
sftpStatusInterval: null,
|
||||||
statusCheckMonitorInterval: null
|
statusCheckMonitorInterval: null,
|
||||||
|
lastUpdateUserTime: 0 // For debouncing updateUser
|
||||||
};
|
};
|
||||||
clients.set(ws, client);
|
clients.set(ws, client);
|
||||||
console.log('WebSocket client registered with API key');
|
console.log('WebSocket client registered with API key');
|
||||||
|
|
||||||
|
// Heartbeat to keep WebSocket alive
|
||||||
|
const heartbeatInterval = setInterval(() => {
|
||||||
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.ping();
|
||||||
|
console.log(`Sent ping to client for user ${client.user || 'unknown'}`);
|
||||||
|
} else {
|
||||||
|
console.log(`WebSocket not open (state: ${ws.readyState}), stopping heartbeat for user ${client.user || 'unknown'}`);
|
||||||
|
clearInterval(heartbeatInterval);
|
||||||
|
}
|
||||||
|
}, 30000);
|
||||||
|
|
||||||
|
ws.on('pong', () => {
|
||||||
|
console.log(`Received pong from client for user ${client.user || 'unknown'}`);
|
||||||
|
});
|
||||||
|
|
||||||
ws.on('message', async (message) => {
|
ws.on('message', async (message) => {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(message.toString());
|
const data = JSON.parse(message.toString());
|
||||||
|
console.log('WebSocket message received:', data.type);
|
||||||
|
|
||||||
if (data.type === 'subscribe') {
|
if (data.type === 'subscribe') {
|
||||||
data.endpoints.forEach(endpoint => {
|
data.endpoints.forEach(endpoint => {
|
||||||
client.subscriptions.add(endpoint);
|
client.subscriptions.add(endpoint);
|
||||||
@ -242,45 +342,8 @@ export function handleWebSocket(ws, req, docker) {
|
|||||||
console.log(`User identified: ${user}`);
|
console.log(`User identified: ${user}`);
|
||||||
ws.send(JSON.stringify({ type: 'hello', data: hello }));
|
ws.send(JSON.stringify({ type: 'hello', data: hello }));
|
||||||
|
|
||||||
if (client.subscriptions.has('docker') && user !== 'Unknown') {
|
// Start Docker stats interval
|
||||||
try {
|
startDockerStatsInterval(ws, client, user, docker);
|
||||||
const container = docker.getContainer(user);
|
|
||||||
const inspect = await container.inspect();
|
|
||||||
if (inspect.State.Status === 'running') {
|
|
||||||
console.log(`Starting docker stats interval for ${user}`);
|
|
||||||
client.intervals.push(setInterval(async () => {
|
|
||||||
try {
|
|
||||||
console.log(`Fetching docker stats for ${user}`);
|
|
||||||
const stats = await getContainerStats(docker, user);
|
|
||||||
if (stats.error) {
|
|
||||||
console.error(`Error fetching stats for ${user}: ${stats.error}`);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', error: stats.error }));
|
|
||||||
} else {
|
|
||||||
console.log(`Sending docker stats for ${user}:`, stats);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', data: { ...stats, user } }));
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error in docker stats interval for ${user}:`, error.message);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', error: `Failed to fetch stats: ${error.message}` }));
|
|
||||||
}
|
|
||||||
}, parseInt(process.env.DOCKER_STATS_INTERVAL_MS, 10)));
|
|
||||||
|
|
||||||
// Send initial stats immediately
|
|
||||||
console.log(`Sending initial docker stats for ${user}`);
|
|
||||||
const initialStats = await getContainerStats(docker, user);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', data: { ...initialStats, user } }));
|
|
||||||
} else {
|
|
||||||
console.log(`Container ${user} is not running, skipping docker stats interval`);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', error: `Container ${user} is not running` }));
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error checking container status for docker stats for ${user}:`, error.message);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', error: `Failed to check container status: ${error.message}` }));
|
|
||||||
}
|
|
||||||
} else if (user === 'Unknown') {
|
|
||||||
console.warn('Cannot start docker stats interval: User is Unknown');
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', error: 'User not identified' }));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client.subscriptions.has('docker-logs') && user !== 'Unknown') {
|
if (client.subscriptions.has('docker-logs') && user !== 'Unknown') {
|
||||||
console.log(`Starting docker logs stream for ${user}`);
|
console.log(`Starting docker logs stream for ${user}`);
|
||||||
@ -353,52 +416,29 @@ export function handleWebSocket(ws, req, docker) {
|
|||||||
ws.send(JSON.stringify({ type: 'hello', error: 'Invalid hello response' }));
|
ws.send(JSON.stringify({ type: 'hello', error: 'Invalid hello response' }));
|
||||||
}
|
}
|
||||||
} else if (data.type === 'updateUser') {
|
} else if (data.type === 'updateUser') {
|
||||||
|
// Debounce updateUser to prevent rapid successive calls
|
||||||
|
const now = Date.now();
|
||||||
|
if (now - client.lastUpdateUserTime < 1000) {
|
||||||
|
console.log(`Debouncing updateUser for ${data.user}, last update: ${client.lastUpdateUserTime}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
client.lastUpdateUserTime = now;
|
||||||
|
|
||||||
client.user = data.user;
|
client.user = data.user;
|
||||||
console.log(`Updated user to: ${client.user}`);
|
console.log(`Updated user to: ${client.user}`);
|
||||||
if (client.user !== 'Unknown') {
|
if (client.user !== 'Unknown') {
|
||||||
client.intervals.forEach(clearInterval);
|
// Clear only specific intervals, preserve others
|
||||||
client.intervals = [];
|
|
||||||
['connectionStatusInterval', 'geyserStatusInterval', 'sftpStatusInterval', 'statusCheckMonitorInterval'].forEach((key) => {
|
['connectionStatusInterval', 'geyserStatusInterval', 'sftpStatusInterval', 'statusCheckMonitorInterval'].forEach((key) => {
|
||||||
if (client[key]) clearInterval(client[key]);
|
if (client[key]) {
|
||||||
client[key] = null;
|
console.log(`Clearing ${key} for ${client.user}`);
|
||||||
|
clearInterval(client[key]);
|
||||||
|
client[key] = null;
|
||||||
|
client.intervals = client.intervals.filter(id => id !== client[key]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (client.subscriptions.has('docker')) {
|
// Start Docker stats interval for new user
|
||||||
try {
|
startDockerStatsInterval(ws, client, client.user, docker);
|
||||||
const container = docker.getContainer(client.user);
|
|
||||||
const inspect = await container.inspect();
|
|
||||||
if (inspect.State.Status === 'running') {
|
|
||||||
console.log(`Starting docker stats interval for new user ${client.user}`);
|
|
||||||
client.intervals.push(setInterval(async () => {
|
|
||||||
try {
|
|
||||||
console.log(`Fetching docker stats for ${client.user}`);
|
|
||||||
const stats = await getContainerStats(docker, client.user);
|
|
||||||
if (stats.error) {
|
|
||||||
console.error(`Error fetching stats for ${client.user}: ${stats.error}`);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', error: stats.error }));
|
|
||||||
} else {
|
|
||||||
console.log(`Sending docker stats for ${client.user}:`, stats);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', data: { ...stats, user: client.user } }));
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error in docker stats interval for ${client.user}:`, error.message);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', error: `Failed to fetch stats: ${error.message}` }));
|
|
||||||
}
|
|
||||||
}, parseInt(process.env.DOCKER_STATS_INTERVAL_MS, 10)));
|
|
||||||
|
|
||||||
// Send initial stats immediately
|
|
||||||
console.log(`Sending initial docker stats for ${client.user}`);
|
|
||||||
const initialStats = await getContainerStats(docker, client.user);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', data: { ...initialStats, user: client.user } }));
|
|
||||||
} else {
|
|
||||||
console.log(`Container ${client.user} is not running, skipping docker stats interval`);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', error: `Container ${client.user} is not running` }));
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error checking container status for docker stats for ${client.user}:`, error.message);
|
|
||||||
ws.send(JSON.stringify({ type: 'docker', error: `Failed to check container status: ${error.message}` }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client.subscriptions.has('list-players')) {
|
if (client.subscriptions.has('list-players')) {
|
||||||
try {
|
try {
|
||||||
@ -444,7 +484,9 @@ export function handleWebSocket(ws, req, docker) {
|
|||||||
} else {
|
} else {
|
||||||
response = await apiRequest(endpoint, client.apiKey, method, body);
|
response = await apiRequest(endpoint, client.apiKey, method, body);
|
||||||
}
|
}
|
||||||
ws.send(JSON.stringify({ requestId, ...response }));
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ requestId, ...response }));
|
||||||
|
}
|
||||||
if (['my-link', 'my-geyser-link', 'my-sftp'].includes(endpoint) && !response.error) {
|
if (['my-link', 'my-geyser-link', 'my-sftp'].includes(endpoint) && !response.error) {
|
||||||
await fetchAndSendUpdate(ws, endpoint, client, docker);
|
await fetchAndSendUpdate(ws, endpoint, client, docker);
|
||||||
if (endpoint === 'my-link') {
|
if (endpoint === 'my-link') {
|
||||||
@ -536,7 +578,9 @@ export function handleWebSocket(ws, req, docker) {
|
|||||||
ws.send(JSON.stringify({ type: 'list-players', data: playerListResponse }));
|
ws.send(JSON.stringify({ type: 'list-players', data: playerListResponse }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ws.send(JSON.stringify({ requestId, ...response }));
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ requestId, ...response }));
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error processing ${data.type} for ${player}:`, error.message);
|
console.error(`Error processing ${data.type} for ${player}:`, error.message);
|
||||||
ws.send(JSON.stringify({ requestId, error: `Failed to process command: ${error.message}` }));
|
ws.send(JSON.stringify({ requestId, error: `Failed to process command: ${error.message}` }));
|
||||||
@ -559,7 +603,9 @@ export function handleWebSocket(ws, req, docker) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const response = await apiRequest('/tell', client.apiKey, 'POST', { username: player, message });
|
const response = await apiRequest('/tell', client.apiKey, 'POST', { username: player, message });
|
||||||
ws.send(JSON.stringify({ requestId, ...response }));
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ requestId, ...response }));
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error sending message to ${player}:`, error.message);
|
console.error(`Error sending message to ${player}:`, error.message);
|
||||||
ws.send(JSON.stringify({ requestId, error: `Failed to send message: ${error.message}` }));
|
ws.send(JSON.stringify({ requestId, error: `Failed to send message: ${error.message}` }));
|
||||||
@ -582,7 +628,9 @@ export function handleWebSocket(ws, req, docker) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const response = await apiRequest('/give', client.apiKey, 'POST', { username: player, item, amount });
|
const response = await apiRequest('/give', client.apiKey, 'POST', { username: player, item, amount });
|
||||||
ws.send(JSON.stringify({ requestId, ...response }));
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ requestId, ...response }));
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error giving item to ${player}:`, error.message);
|
console.error(`Error giving item to ${player}:`, error.message);
|
||||||
ws.send(JSON.stringify({ requestId, error: `Failed to give item: ${error.message}` }));
|
ws.send(JSON.stringify({ requestId, error: `Failed to give item: ${error.message}` }));
|
||||||
@ -600,7 +648,9 @@ export function handleWebSocket(ws, req, docker) {
|
|||||||
try {
|
try {
|
||||||
const stats = await getContainerStats(docker, client.user);
|
const stats = await getContainerStats(docker, client.user);
|
||||||
console.log(`Sending refreshed docker stats for ${client.user}:`, stats);
|
console.log(`Sending refreshed docker stats for ${client.user}:`, stats);
|
||||||
ws.send(JSON.stringify({ type: 'docker', data: { ...stats, user: client.user } }));
|
if (ws.readyState === ws.OPEN) {
|
||||||
|
ws.send(JSON.stringify({ type: 'docker', data: { ...stats, user: client.user } }));
|
||||||
|
}
|
||||||
const container = docker.getContainer(client.user);
|
const container = docker.getContainer(client.user);
|
||||||
const inspect = await container.inspect();
|
const inspect = await container.inspect();
|
||||||
if (inspect.State.Status === 'running') {
|
if (inspect.State.Status === 'running') {
|
||||||
@ -648,20 +698,29 @@ export function handleWebSocket(ws, req, docker) {
|
|||||||
ws.on('close', () => {
|
ws.on('close', () => {
|
||||||
try {
|
try {
|
||||||
const client = clients.get(ws);
|
const client = clients.get(ws);
|
||||||
client.intervals.forEach(clearInterval);
|
client.intervals.forEach(intervalId => {
|
||||||
|
console.log(`Clearing interval ID ${intervalId} for client ${client.user || 'unknown'}`);
|
||||||
|
clearInterval(intervalId);
|
||||||
|
});
|
||||||
|
client.intervals = [];
|
||||||
if (client.logStream) {
|
if (client.logStream) {
|
||||||
client.logStream.destroy();
|
client.logStream.destroy();
|
||||||
client.logStream = null;
|
client.logStream = null;
|
||||||
}
|
}
|
||||||
['connectionStatusInterval', 'geyserStatusInterval', 'sftpStatusInterval', 'statusCheckMonitorInterval'].forEach((key) => {
|
['connectionStatusInterval', 'geyserStatusInterval', 'sftpStatusInterval', 'statusCheckMonitorInterval'].forEach((key) => {
|
||||||
if (client[key]) clearInterval(client[key]);
|
if (client[key]) {
|
||||||
|
console.log(`Clearing ${key} for client ${client.user || 'unknown'}`);
|
||||||
|
clearInterval(client[key]);
|
||||||
|
client[key] = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
clearInterval(heartbeatInterval);
|
||||||
clients.delete(ws);
|
clients.delete(ws);
|
||||||
console.log('WebSocket client disconnected');
|
console.log(`WebSocket client disconnected for user ${client.user || 'unknown'}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error on WebSocket close:', error.message);
|
console.error('Error on WebSocket close:', error.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.on('error', (error) => console.error('WebSocket error:', error.message));
|
ws.on('error', (error) => console.error(`WebSocket error for user ${client.user || 'unknown'}:`, error.message));
|
||||||
}
|
}
|
Reference in New Issue
Block a user