diff --git a/src/utils/matrix.ts b/src/utils/matrix.ts index c80fa7d9..8c1a47e2 100644 --- a/src/utils/matrix.ts +++ b/src/utils/matrix.ts @@ -8,6 +8,7 @@ Please see LICENSE in the repository root for full details. import { IndexedDBStore } from "matrix-js-sdk/src/store/indexeddb"; import { MemoryStore } from "matrix-js-sdk/src/store/memory"; import { + calculateRetryBackoff, createClient, type ICreateClientOpts, Preset, @@ -17,6 +18,7 @@ import { ClientEvent } from "matrix-js-sdk/src/client"; import { type ISyncStateData, type SyncState } from "matrix-js-sdk/src/sync"; import { logger } from "matrix-js-sdk/src/logger"; import { secureRandomBase64Url } from "matrix-js-sdk/src/randomstring"; +import { sleep } from "matrix-js-sdk/src/utils"; import type { MatrixClient } from "matrix-js-sdk/src/client"; import type { Room } from "matrix-js-sdk/src/models/room"; @@ -336,3 +338,30 @@ export function getRelativeRoomUrl( : ""; return `/room/#${roomPart}?${generateUrlSearchParams(roomId, encryptionSystem, viaServers).toString()}`; } + +/** + * Perfom a network operation with retries on ConnectionError. + * If the error is not retryable, or the max number of retries is reached, the error is rethrown. + * Supports handling of matrix quotas. + */ +export async function doNetworkOperationWithRetry( + operation: () => Promise, +): Promise { + let currentRetryCount = 0; + + // eslint-disable-next-line no-constant-condition + while (true) { + try { + return await operation(); + } catch (e) { + currentRetryCount++; + const backoff = calculateRetryBackoff(e, currentRetryCount, true); + if (backoff < 0) { + // Max number of retries reached, or error is not retryable. rethrow the error + throw e; + } + // wait for the specified time and then retry the request + await sleep(backoff); + } + } +}