This commit is contained in:
indifferentketchup
2026-04-09 09:49:19 -05:00
parent a4fb82620a
commit 7fff9192b4
8 changed files with 115 additions and 75 deletions

View File

@@ -6,8 +6,9 @@
const RENAME_WINDOW_MS = 9 * 60 * 1000;
const RENAME_LIMIT = 2;
const { logWarn } = require('../services/debugLog');
// Per-channel state: { count, windowStart, queue: [{newName, resolve, reject}], processing }
// Per-channel state: { count, windowStart, queue: [{newName, started}], processing }
const renameState = new Map();
function getOrInitState(channelId) {
@@ -35,18 +36,17 @@ function processQueue(channel, state) {
state.processing = false;
// New window
if (state.queue.length > 3) {
const { logWarn } = require('../services/debugLog');
logWarn('renameQueue', `Channel ${channel.name} has ${state.queue.length} renames queued`).catch(() => {});
}
const item = state.queue.shift();
if (!item) return;
item.started = true;
state.count = 1;
state.windowStart = Date.now();
try {
await executeRename(channel, item.newName);
item.resolve();
} catch (err) {
item.reject(err);
logWarn('renameQueue', `Queued rename failed for ${channel.name}: ${err.message || err}`).catch(() => {});
}
// Continue processing remaining queue items
processQueue(channel, state);
@@ -55,29 +55,42 @@ function processQueue(channel, state) {
}
function enqueueRename(channel, newName) {
return new Promise((resolve, reject) => {
const state = getOrInitState(channel.id);
const now = Date.now();
const state = getOrInitState(channel.id);
const now = Date.now();
// Window expired — reset
if (now - state.windowStart >= RENAME_WINDOW_MS) {
state.count = 1;
state.windowStart = now;
executeRename(channel, newName).then(resolve).catch(reject);
return;
}
// Window expired — reset
if (now - state.windowStart >= RENAME_WINDOW_MS) {
state.count = 1;
state.windowStart = now;
executeRename(channel, newName).catch((err) => {
logWarn('renameQueue', `Immediate rename failed for ${channel.name}: ${err.message || err}`).catch(() => {});
});
return Promise.resolve();
}
// Within window and under limit
if (state.count < RENAME_LIMIT) {
state.count++;
executeRename(channel, newName).then(resolve).catch(reject);
return;
}
// Within window and under limit
if (state.count < RENAME_LIMIT) {
state.count++;
executeRename(channel, newName).catch((err) => {
logWarn('renameQueue', `Immediate rename failed for ${channel.name}: ${err.message || err}`).catch(() => {});
});
return Promise.resolve();
}
// At limit — queue it
state.queue.push({ newName, resolve, reject });
processQueue(channel, state);
});
// At limit — queue it
const queueSize = state.queue.length + 1;
const queuedItem = { newName, started: false };
state.queue.push(queuedItem);
// Only notify if this rename is still waiting after ~2s.
setTimeout(() => {
if (queuedItem.started) return;
const estMinutes = Math.max(1, Math.ceil((queueSize * RENAME_WINDOW_MS) / 60000));
channel.send(`⏳ Channel will be renamed in ~${estMinutes} minute${estMinutes === 1 ? '' : 's'}.`).catch(() => {});
}, 2000);
processQueue(channel, state);
return Promise.resolve();
}
function enqueueMove(channel, categoryId) {

View File

@@ -613,7 +613,9 @@ async function reconcileDeletedTicketChannels(client) {
console.error(`reconcileDeletedTicketChannels error for ${ticket.gmailThreadId}:`, err);
}
}
logAutomation('Reconcile run', null, `checked: ${checked}, reconciled: ${reconciled}`).catch(() => {});
if (reconciled > 0) {
logAutomation('Reconcile run', null, `checked: ${checked}, reconciled: ${reconciled}`).catch(() => {});
}
return { checked, reconciled };
}