Close: guard channel delete with pendingDelete so a restart can't orphan it
The button and slash close paths deleted the channel via a bare setTimeout that never set the pendingDelete flag, so a restart in the 5s grace window orphaned the channel (closed in DB, still present in Discord) with no recovery — only the auto-close path used the flag correctly. Extract scheduleTicketChannelDelete() in services/tickets.js: a grace-delayed, queue-routed (enqueueDelete) delete that clears pendingDelete on success. All three close paths now use it. Button/slash set pendingDelete:true and keep discordThreadId populated so resumePendingDeletes() recovers the delete on the next boot. The button path previously nulled discordThreadId before the delete, which made the channel unrecoverable.
This commit is contained in:
@@ -15,7 +15,7 @@ const { logTicketEvent, logError } = require('../../services/debugLog');
|
||||
const { moveThreadToFolder } = require('../../services/gmailLabels');
|
||||
const { pendingCloses } = require('../pendingCloses');
|
||||
const { findTicketForChannel } = require('../sharedHelpers');
|
||||
const { attemptCloseTransition } = require('../../services/tickets');
|
||||
const { attemptCloseTransition, scheduleTicketChannelDelete } = require('../../services/tickets');
|
||||
const { buildTranscriptText, formatDateForTranscript, renderTranscriptHeader } = require('../../services/transcript');
|
||||
const { recordAction } = require('../../services/staffStats');
|
||||
|
||||
@@ -75,7 +75,9 @@ async function finalizeForceClose(channelRef, clientRef, _TicketModel, _recordAc
|
||||
if (!freshTicket || freshTicket.status === 'closed') return;
|
||||
|
||||
try {
|
||||
const { transitioned, ticket: closedTicket } = await attemptCloseTransition(freshTicket.gmailThreadId, {}, { welcomeMessageId: '' }, T);
|
||||
// pendingDelete (with discordThreadId left set) lets resumePendingDeletes()
|
||||
// recover the channel delete if a restart interrupts the grace window.
|
||||
const { transitioned, ticket: closedTicket } = await attemptCloseTransition(freshTicket.gmailThreadId, { pendingDelete: true }, { welcomeMessageId: '' }, T);
|
||||
if (transitioned) {
|
||||
record(closerId ?? 'system', 'close', {
|
||||
ticket: closedTicket,
|
||||
@@ -97,11 +99,9 @@ async function finalizeForceClose(channelRef, clientRef, _TicketModel, _recordAc
|
||||
console.error('Transcript error (force-close):', tErr)
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
channelRef.delete('Ticket force-closed').catch(e =>
|
||||
console.error('Failed to delete channel:', e)
|
||||
);
|
||||
}, 5000);
|
||||
// Queue-routed, pendingDelete-guarded delete (shared with auto-close + button
|
||||
// close) so a mid-close restart can't orphan the channel.
|
||||
scheduleTicketChannelDelete(channelRef, freshTicket.gmailThreadId);
|
||||
} catch (err) {
|
||||
console.error('Force close error:', err);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user