Add 10-minute retry for failed server syncs
When hourly sync encounters servers that fail (e.g., mid-restart): - Logs the failure count - Schedules automatic retry in 10 minutes - Retry only targets previously failed servers - Clears error state on successful retry Fixes issue where servers in daily restart would stay in error state until manual intervention. Chronicler #69
This commit is contained in:
@@ -2,6 +2,8 @@ const cron = require('node-cron');
|
|||||||
const { triggerImmediateSync } = require('./immediate');
|
const { triggerImmediateSync } = require('./immediate');
|
||||||
const { processExpiredGracePeriods } = require('./graceExpiration');
|
const { processExpiredGracePeriods } = require('./graceExpiration');
|
||||||
|
|
||||||
|
let retryTimeout = null;
|
||||||
|
|
||||||
function initCron() {
|
function initCron() {
|
||||||
// Hourly whitelist reconciliation
|
// Hourly whitelist reconciliation
|
||||||
cron.schedule('0 * * * *', async () => {
|
cron.schedule('0 * * * *', async () => {
|
||||||
@@ -12,7 +14,29 @@ function initCron() {
|
|||||||
|
|
||||||
// 2. Whitelist reconciliation
|
// 2. Whitelist reconciliation
|
||||||
console.log("Starting whitelist reconciliation...");
|
console.log("Starting whitelist reconciliation...");
|
||||||
await triggerImmediateSync();
|
const { failCount } = await triggerImmediateSync();
|
||||||
|
|
||||||
|
// 3. Schedule retry if there were failures
|
||||||
|
if (failCount > 0) {
|
||||||
|
console.log(`⏳ ${failCount} servers failed. Scheduling retry in 10 minutes...`);
|
||||||
|
|
||||||
|
// Clear any existing retry timeout
|
||||||
|
if (retryTimeout) {
|
||||||
|
clearTimeout(retryTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retry failed servers after 10 minutes
|
||||||
|
retryTimeout = setTimeout(async () => {
|
||||||
|
console.log("🔄 Running retry sync for failed servers...");
|
||||||
|
const { failCount: retryFailCount } = await triggerImmediateSync(true);
|
||||||
|
|
||||||
|
if (retryFailCount > 0) {
|
||||||
|
console.log(`⚠️ ${retryFailCount} servers still failing after retry.`);
|
||||||
|
} else {
|
||||||
|
console.log("✅ All previously failed servers now synced successfully.");
|
||||||
|
}
|
||||||
|
}, 10 * 60 * 1000); // 10 minutes
|
||||||
|
}
|
||||||
|
|
||||||
console.log("✅ Hourly sync jobs complete");
|
console.log("✅ Hourly sync jobs complete");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ const { getMinecraftServers } = require('../panel/discovery');
|
|||||||
const { writeWhitelistFile } = require('../panel/files');
|
const { writeWhitelistFile } = require('../panel/files');
|
||||||
const { reloadWhitelistCommand } = require('../panel/commands');
|
const { reloadWhitelistCommand } = require('../panel/commands');
|
||||||
|
|
||||||
async function triggerImmediateSync() {
|
async function triggerImmediateSync(retryOnly = false) {
|
||||||
console.log("--- Starting Whitelist Sync ---");
|
console.log(retryOnly ? "--- Starting Retry Sync (failed servers only) ---" : "--- Starting Whitelist Sync ---");
|
||||||
try {
|
try {
|
||||||
// 1. Fetch Players (Now includes 'lifetime' for the Trinity)
|
// 1. Fetch Players (Now includes 'lifetime' for the Trinity)
|
||||||
const { rows: players, rowCount: playerCount } = await db.query(
|
const { rows: players, rowCount: playerCount } = await db.query(
|
||||||
@@ -16,12 +16,27 @@ async function triggerImmediateSync() {
|
|||||||
console.log(`[Sync] Retrieved ${playerCount} active players from database.`);
|
console.log(`[Sync] Retrieved ${playerCount} active players from database.`);
|
||||||
|
|
||||||
// 2. Fetch Servers
|
// 2. Fetch Servers
|
||||||
const servers = await getMinecraftServers();
|
let servers = await getMinecraftServers();
|
||||||
console.log(`[Sync] Discovered ${servers.length} target servers.`);
|
|
||||||
|
// If retry mode, only sync servers that previously failed
|
||||||
|
if (retryOnly) {
|
||||||
|
const { rows: failedServers } = await db.query(
|
||||||
|
`SELECT server_identifier FROM server_sync_log WHERE is_online = false`
|
||||||
|
);
|
||||||
|
const failedIds = failedServers.map(s => s.server_identifier);
|
||||||
|
servers = servers.filter(s => failedIds.includes(s.identifier));
|
||||||
|
console.log(`[Sync] Retrying ${servers.length} previously failed servers.`);
|
||||||
|
} else {
|
||||||
|
console.log(`[Sync] Discovered ${servers.length} target servers.`);
|
||||||
|
}
|
||||||
|
|
||||||
if (servers.length === 0) {
|
if (servers.length === 0) {
|
||||||
console.warn("[Sync] WARN: 0 servers discovered. Check MINECRAFT_NEST_IDS in .env.");
|
if (retryOnly) {
|
||||||
return;
|
console.log("[Sync] No failed servers to retry.");
|
||||||
|
} else {
|
||||||
|
console.warn("[Sync] WARN: 0 servers discovered. Check MINECRAFT_NEST_IDS in .env.");
|
||||||
|
}
|
||||||
|
return { successCount: 0, failCount: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Process Servers Sequentially
|
// 3. Process Servers Sequentially
|
||||||
@@ -34,10 +49,13 @@ async function triggerImmediateSync() {
|
|||||||
await reloadWhitelistCommand(server.identifier);
|
await reloadWhitelistCommand(server.identifier);
|
||||||
|
|
||||||
await db.query(
|
await db.query(
|
||||||
"INSERT INTO server_sync_log (server_identifier, last_successful_sync, is_online) VALUES ($1, NOW(), true) ON CONFLICT (server_identifier) DO UPDATE SET last_successful_sync = NOW(), is_online = true",
|
"INSERT INTO server_sync_log (server_identifier, last_successful_sync, is_online, last_error) VALUES ($1, NOW(), true, NULL) ON CONFLICT (server_identifier) DO UPDATE SET last_successful_sync = NOW(), is_online = true, last_error = NULL",
|
||||||
[server.identifier]
|
[server.identifier]
|
||||||
);
|
);
|
||||||
successCount++;
|
successCount++;
|
||||||
|
if (retryOnly) {
|
||||||
|
console.log(`[Sync] ✅ Retry succeeded for ${server.name}`);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`[Sync] ❌ Failed for server ${server.name} (${server.identifier}):`, err.message);
|
console.error(`[Sync] ❌ Failed for server ${server.name} (${server.identifier}):`, err.message);
|
||||||
await db.query(
|
await db.query(
|
||||||
@@ -50,8 +68,10 @@ async function triggerImmediateSync() {
|
|||||||
|
|
||||||
console.log(`[Sync] Complete. Success: ${successCount}, Failed: ${failCount}`);
|
console.log(`[Sync] Complete. Success: ${successCount}, Failed: ${failCount}`);
|
||||||
console.log("-------------------------------");
|
console.log("-------------------------------");
|
||||||
|
return { successCount, failCount };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[Sync] Critical failure during execution:", error);
|
console.error("[Sync] Critical failure during execution:", error);
|
||||||
|
return { successCount: 0, failCount: 0 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user