Cancel in-flight attachment downloads on suspend/resume
This commit is contained in:
parent
5dfdde998b
commit
fbdfaf3962
2 changed files with 44 additions and 1 deletions
|
@ -1733,12 +1733,14 @@ export async function startApp(): Promise<void> {
|
||||||
|
|
||||||
window.Whisper.events.on('powerMonitorSuspend', () => {
|
window.Whisper.events.on('powerMonitorSuspend', () => {
|
||||||
log.info('powerMonitor: suspend');
|
log.info('powerMonitor: suspend');
|
||||||
|
server?.cancelInflightRequests('powerMonitorSuspend');
|
||||||
suspendTasksWithTimeout();
|
suspendTasksWithTimeout();
|
||||||
});
|
});
|
||||||
|
|
||||||
window.Whisper.events.on('powerMonitorResume', () => {
|
window.Whisper.events.on('powerMonitorResume', () => {
|
||||||
log.info('powerMonitor: resume');
|
log.info('powerMonitor: resume');
|
||||||
server?.checkSockets();
|
server?.checkSockets();
|
||||||
|
server?.cancelInflightRequests('powerMonitorResume');
|
||||||
resumeTasksWithTimeout();
|
resumeTasksWithTimeout();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -815,6 +815,7 @@ export type ConfirmCodeOptionsType = Readonly<{
|
||||||
export type WebAPIType = {
|
export type WebAPIType = {
|
||||||
startRegistration(): unknown;
|
startRegistration(): unknown;
|
||||||
finishRegistration(baton: unknown): void;
|
finishRegistration(baton: unknown): void;
|
||||||
|
cancelInflightRequests: (reason: string) => void;
|
||||||
cdsLookup: (options: CdsLookupOptionsType) => Promise<CDSResponseType>;
|
cdsLookup: (options: CdsLookupOptionsType) => Promise<CDSResponseType>;
|
||||||
confirmCode: (
|
confirmCode: (
|
||||||
options: ConfirmCodeOptionsType
|
options: ConfirmCodeOptionsType
|
||||||
|
@ -1042,6 +1043,8 @@ export type TopLevelType = {
|
||||||
initialize: (options: InitializeOptionsType) => WebAPIConnectType;
|
initialize: (options: InitializeOptionsType) => WebAPIConnectType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type InflightCallback = (error: Error) => unknown;
|
||||||
|
|
||||||
// We first set up the data that won't change during this session of the app
|
// We first set up the data that won't change during this session of the app
|
||||||
export function initialize({
|
export function initialize({
|
||||||
url,
|
url,
|
||||||
|
@ -1152,6 +1155,29 @@ export function initialize({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const inflightRequests = new Set<(error: Error) => unknown>();
|
||||||
|
function registerInflightRequest(request: InflightCallback) {
|
||||||
|
inflightRequests.add(request);
|
||||||
|
}
|
||||||
|
function unregisterInFlightRequest(request: InflightCallback) {
|
||||||
|
inflightRequests.delete(request);
|
||||||
|
}
|
||||||
|
function cancelInflightRequests(reason: string) {
|
||||||
|
const logId = `cancelInflightRequests/${reason}`;
|
||||||
|
log.warn(`${logId}: Cancelling ${inflightRequests.size} requests`);
|
||||||
|
for (const request of inflightRequests) {
|
||||||
|
try {
|
||||||
|
request(new Error(`${logId}: Cancelled!`));
|
||||||
|
} catch (error: unknown) {
|
||||||
|
log.error(
|
||||||
|
`${logId}: Failed to cancel request: ${toLogFormat(error)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inflightRequests.clear();
|
||||||
|
log.warn(`${logId}: Done`);
|
||||||
|
}
|
||||||
|
|
||||||
let fetchForLinkPreviews: linkPreviewFetch.FetchFn;
|
let fetchForLinkPreviews: linkPreviewFetch.FetchFn;
|
||||||
if (proxyUrl) {
|
if (proxyUrl) {
|
||||||
const agent = new ProxyAgent(proxyUrl);
|
const agent = new ProxyAgent(proxyUrl);
|
||||||
|
@ -1163,6 +1189,7 @@ export function initialize({
|
||||||
// Thanks, function hoisting!
|
// Thanks, function hoisting!
|
||||||
return {
|
return {
|
||||||
authenticate,
|
authenticate,
|
||||||
|
cancelInflightRequests,
|
||||||
cdsLookup,
|
cdsLookup,
|
||||||
checkAccountExistence,
|
checkAccountExistence,
|
||||||
checkSockets,
|
checkSockets,
|
||||||
|
@ -2391,11 +2418,25 @@ export function initialize({
|
||||||
abortSignal: abortController.signal,
|
abortSignal: abortController.signal,
|
||||||
});
|
});
|
||||||
|
|
||||||
return getStreamWithTimeout(stream, {
|
const streamPromise = getStreamWithTimeout(stream, {
|
||||||
name: `getAttachment(${cdnKey})`,
|
name: `getAttachment(${cdnKey})`,
|
||||||
timeout: GET_ATTACHMENT_CHUNK_TIMEOUT,
|
timeout: GET_ATTACHMENT_CHUNK_TIMEOUT,
|
||||||
abortController,
|
abortController,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add callback to central store that would reject a promise
|
||||||
|
const { promise: cancelPromise, reject } = explodePromise<Uint8Array>();
|
||||||
|
const inflightRequest = (error: Error) => {
|
||||||
|
reject(error);
|
||||||
|
abortController.abort();
|
||||||
|
};
|
||||||
|
registerInflightRequest(inflightRequest);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Promise.race([streamPromise, cancelPromise]);
|
||||||
|
} finally {
|
||||||
|
unregisterInFlightRequest(inflightRequest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type PutAttachmentResponseType = ServerAttachmentType & {
|
type PutAttachmentResponseType = ServerAttachmentType & {
|
||||||
|
|
Loading…
Add table
Reference in a new issue