fix: look a send up soon after its response got lost, also with the server still there

This commit is contained in:
Linus Rath
2026-11-03 06:40:45 +01:00
parent 3060c60778
commit f2356cdfc7
3 changed files with 13 additions and 0 deletions
+7
View File
@@ -234,6 +234,13 @@ describe('the outbox', () => {
// Not tried again on its own.
await flushQueue('acc', cut as unknown as JMAPClient, { notify: vi.fn(), allowed: () => true });
expect(cut.sendEmail).toHaveBeenCalledTimes(1);
// With the server still there, nothing else would start the lookup.
const entry = (await readQueue('acc')).outbox[0];
await store.area('acc', 'outbox.update', { id: entry.id, status: 'waiting' });
const retryLater = vi.fn();
await flushQueue('acc', cut as unknown as JMAPClient, { notify: vi.fn(), allowed: () => true, retryLater });
expect(retryLater).toHaveBeenCalledTimes(1);
});
it('sends nothing once the organisation forbids offline mode', async () => {
+3
View File
@@ -52,6 +52,8 @@ export interface FlushDeps {
stricterNow?: (entry: OutboxEntry) => boolean;
/** A held send went out (an undo window still open). */
onScheduled?: (entry: OutboxEntry, result: SendEmailResult) => void;
/** A send's connection broke though the server may be fine: look it up again soon. */
retryLater?: () => void;
}
/** A send is taken for at most this long before a closed tab's send counts as uncertain. */
@@ -272,6 +274,7 @@ async function flushLocked(account: string, client: JMAPClient, deps: FlushDeps)
if (isNetworkFailure(error) || (error instanceof Error && error.name === 'SendUnconfirmedError')) {
// It may have reached the server: looked up before it goes again.
await updateOutboxEntry(entry, { status: 'uncertain' });
deps.retryLater?.();
return;
}
const text = error instanceof Error ? error.message : String(error);
+3
View File
@@ -534,6 +534,8 @@ export function scheduleFlushAll(delayMs = 1_000): void {
/** How long after a failed policy fetch the outbox asks again. */
const POLICY_RETRY_MS = 60_000;
/** A lost response with the server still there: nothing else would start the lookup. */
const LOOKUP_AGAIN_MS = 30_000;
/** A send held by the server for undo, from the outbox: the undo toast as after any send. */
function offerUndo(entry: OutboxEntry, result: SendEmailResult): void {
@@ -578,6 +580,7 @@ export async function flushAll(): Promise<void> {
allowed: () => offlineAllowed(account),
stricterNow,
onScheduled: offerUndo,
retryLater: () => scheduleFlushAll(LOOKUP_AGAIN_MS),
}).catch(() => {});
}
await refreshQueueState();