Merge pull request 'fix(outbox): two tabs no longer overwrite each other's queue (#268)' (#430) from fix/outbox-multi-tab into lotus
CI / Build & Quality Checks (push) Successful in 1m57s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 7s
CI / Trigger Desktop Build (push) Canceled after 0s
CI / Playwright smoke (e2e) (push) Canceled after 0s
CI / Build & Quality Checks (push) Successful in 1m57s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 7s
CI / Trigger Desktop Build (push) Canceled after 0s
CI / Playwright smoke (e2e) (push) Canceled after 0s
This commit was merged in pull request #430.
This commit is contained in:
@@ -94,10 +94,15 @@ export function OutboxFeature() {
|
|||||||
OFFLINE.has(mx.getSyncState()) ||
|
OFFLINE.has(mx.getSyncState()) ||
|
||||||
(typeof navigator !== 'undefined' && navigator.onLine === false);
|
(typeof navigator !== 'undefined' && navigator.onLine === false);
|
||||||
|
|
||||||
const persist = (next: OutboxEntry[]) => {
|
// [Gitea #268] Read-modify-write: another tab may have queued or cleared
|
||||||
if (next === entries) return;
|
// entries since we last looked, and saving our own copy over the key
|
||||||
|
// would drop theirs. Entries are added/removed by txnId, so applying our
|
||||||
|
// change to the stored list merges cleanly.
|
||||||
|
const persist = (update: (list: OutboxEntry[]) => OutboxEntry[]) => {
|
||||||
|
const stored = loadOutbox(userId);
|
||||||
|
const next = update(stored);
|
||||||
entries = next;
|
entries = next;
|
||||||
saveOutbox(userId, entries);
|
if (next !== stored) saveOutbox(userId, next);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,8 +128,8 @@ export function OutboxFeature() {
|
|||||||
if (!shouldKeepInOutbox(event.getType(), event.getContent())) return;
|
if (!shouldKeepInOutbox(event.getType(), event.getContent())) return;
|
||||||
live.set(txnId, { event, room });
|
live.set(txnId, { event, room });
|
||||||
if (event.status === EventStatus.NOT_SENT) scheduleBlipRetry(event);
|
if (event.status === EventStatus.NOT_SENT) scheduleBlipRetry(event);
|
||||||
persist(
|
persist((list) =>
|
||||||
withEntry(entries, {
|
withEntry(list, {
|
||||||
txnId,
|
txnId,
|
||||||
roomId: room.roomId,
|
roomId: room.roomId,
|
||||||
threadId: event.threadRootId ?? null,
|
threadId: event.threadRootId ?? null,
|
||||||
@@ -138,7 +143,7 @@ export function OutboxFeature() {
|
|||||||
// SENT, CANCELLED, or the remote echo replaced it (status null).
|
// SENT, CANCELLED, or the remote echo replaced it (status null).
|
||||||
live.delete(txnId);
|
live.delete(txnId);
|
||||||
autoRetries.delete(txnId);
|
autoRetries.delete(txnId);
|
||||||
persist(withoutEntry(entries, txnId));
|
persist((list) => withoutEntry(list, txnId));
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Re-send network failures, oldest first; a room stops at its first failure. */
|
/** Re-send network failures, oldest first; a room stops at its first failure. */
|
||||||
@@ -191,7 +196,7 @@ export function OutboxFeature() {
|
|||||||
return !!room && isDelivered(room, entry.txnId);
|
return !!room && isDelivered(room, entry.txnId);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
plan.drop.forEach((entry) => persist(withoutEntry(entries, entry.txnId)));
|
plan.drop.forEach((entry) => persist((list) => withoutEntry(list, entry.txnId)));
|
||||||
plan.restore.forEach((entry) => {
|
plan.restore.forEach((entry) => {
|
||||||
const room = mx.getRoom(entry.roomId);
|
const room = mx.getRoom(entry.roomId);
|
||||||
if (!room || live.has(entry.txnId)) return;
|
if (!room || live.has(entry.txnId)) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user