Update retry behavior for backed-up attachments
This commit is contained in:
parent
ac89fe894a
commit
a7e22b14b3
5 changed files with 50 additions and 2 deletions
|
@ -96,8 +96,14 @@ const DEFAULT_RETRY_CONFIG = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const BACKUP_RETRY_CONFIG = {
|
const BACKUP_RETRY_CONFIG = {
|
||||||
...DEFAULT_RETRY_CONFIG,
|
// Always retry if we think the item may end up being backed up
|
||||||
maxAttempts: Infinity,
|
maxAttempts: Infinity,
|
||||||
|
backoffConfig: {
|
||||||
|
// 30 seconds, 5 minutes, 50 minutes, 500 minutes (~8.3hrs), (max) 3 days
|
||||||
|
multiplier: 10,
|
||||||
|
firstBackoffs: [30 * durations.SECOND],
|
||||||
|
maxBackoffTime: 3 * durations.DAY,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type RunDownloadAttachmentJobOptions = {
|
type RunDownloadAttachmentJobOptions = {
|
||||||
|
@ -224,7 +230,10 @@ export class AttachmentDownloadManager extends JobManager<CoreAttachmentDownload
|
||||||
limit,
|
limit,
|
||||||
prioritizeMessageIds: [...this.#visibleTimelineMessages],
|
prioritizeMessageIds: [...this.#visibleTimelineMessages],
|
||||||
sources: window.storage.get('backupMediaDownloadPaused')
|
sources: window.storage.get('backupMediaDownloadPaused')
|
||||||
? [AttachmentDownloadSource.STANDARD]
|
? [
|
||||||
|
AttachmentDownloadSource.STANDARD,
|
||||||
|
AttachmentDownloadSource.BACKFILL,
|
||||||
|
]
|
||||||
: undefined,
|
: undefined,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1100,6 +1100,7 @@ type WritableInterface = {
|
||||||
saveAttachmentDownloadJob: (job: AttachmentDownloadJobType) => void;
|
saveAttachmentDownloadJob: (job: AttachmentDownloadJobType) => void;
|
||||||
saveAttachmentDownloadJobs: (jobs: Array<AttachmentDownloadJobType>) => void;
|
saveAttachmentDownloadJobs: (jobs: Array<AttachmentDownloadJobType>) => void;
|
||||||
resetAttachmentDownloadActive: () => void;
|
resetAttachmentDownloadActive: () => void;
|
||||||
|
resetBackupAttachmentDownloadJobsRetryAfter: () => void;
|
||||||
removeAttachmentDownloadJob: (job: AttachmentDownloadJobType) => void;
|
removeAttachmentDownloadJob: (job: AttachmentDownloadJobType) => void;
|
||||||
removeAttachmentDownloadJobsForMessage: (messageId: string) => void;
|
removeAttachmentDownloadJobsForMessage: (messageId: string) => void;
|
||||||
removeAllBackupAttachmentDownloadJobs: () => void;
|
removeAllBackupAttachmentDownloadJobs: () => void;
|
||||||
|
|
|
@ -599,6 +599,7 @@ export const DataWriter: ServerWritableInterface = {
|
||||||
saveAttachmentDownloadJob,
|
saveAttachmentDownloadJob,
|
||||||
saveAttachmentDownloadJobs,
|
saveAttachmentDownloadJobs,
|
||||||
resetAttachmentDownloadActive,
|
resetAttachmentDownloadActive,
|
||||||
|
resetBackupAttachmentDownloadJobsRetryAfter,
|
||||||
removeAttachmentDownloadJob,
|
removeAttachmentDownloadJob,
|
||||||
removeAttachmentDownloadJobsForMessage,
|
removeAttachmentDownloadJobsForMessage,
|
||||||
removeAllBackupAttachmentDownloadJobs,
|
removeAllBackupAttachmentDownloadJobs,
|
||||||
|
@ -5746,6 +5747,16 @@ function resetAttachmentDownloadActive(db: WritableDB): void {
|
||||||
).run();
|
).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetBackupAttachmentDownloadJobsRetryAfter(db: WritableDB): void {
|
||||||
|
db.prepare(
|
||||||
|
`
|
||||||
|
UPDATE attachment_downloads
|
||||||
|
SET retryAfter = NULL
|
||||||
|
WHERE originalSource = 'backup_import'
|
||||||
|
`
|
||||||
|
).run();
|
||||||
|
}
|
||||||
|
|
||||||
function removeAttachmentDownloadJob(
|
function removeAttachmentDownloadJob(
|
||||||
db: WritableDB,
|
db: WritableDB,
|
||||||
job: Pick<
|
job: Pick<
|
||||||
|
|
|
@ -502,6 +502,31 @@ describe('AttachmentDownloadManager/JobManager', () => {
|
||||||
jobs[2],
|
jobs[2],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('retries backup job immediately if retryAfters are reset', async () => {
|
||||||
|
strictAssert(downloadManager, 'must exist');
|
||||||
|
const jobs = await addJobs(1, {
|
||||||
|
source: AttachmentDownloadSource.BACKUP_IMPORT,
|
||||||
|
});
|
||||||
|
const jobAttempts = getPromisesForAttempts(jobs[0], 2);
|
||||||
|
|
||||||
|
runJob.callsFake(async () => {
|
||||||
|
return new Promise<{ status: 'finished' | 'retry' }>(resolve => {
|
||||||
|
Promise.resolve().then(() => {
|
||||||
|
resolve({ status: 'retry' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await downloadManager?.start();
|
||||||
|
await jobAttempts[0].completed;
|
||||||
|
assertRunJobCalledWith([jobs[0]]);
|
||||||
|
|
||||||
|
await DataWriter.resetBackupAttachmentDownloadJobsRetryAfter();
|
||||||
|
await downloadManager.start();
|
||||||
|
|
||||||
|
await jobAttempts[1].completed;
|
||||||
|
});
|
||||||
describe('will drop jobs from non-media backup imports that are old', () => {
|
describe('will drop jobs from non-media backup imports that are old', () => {
|
||||||
it('will not queue attachments older than 90 days (2 * message queue time)', async () => {
|
it('will not queue attachments older than 90 days (2 * message queue time)', async () => {
|
||||||
hasMediaBackups.returns(false);
|
hasMediaBackups.returns(false);
|
||||||
|
|
|
@ -20,6 +20,8 @@ export async function pauseBackupMediaDownload(): Promise<void> {
|
||||||
|
|
||||||
export async function resumeBackupMediaDownload(): Promise<void> {
|
export async function resumeBackupMediaDownload(): Promise<void> {
|
||||||
log.info('Resuming media download');
|
log.info('Resuming media download');
|
||||||
|
// Reset the retry-afters so that all jobs will be immediately retried
|
||||||
|
await DataWriter.resetBackupAttachmentDownloadJobsRetryAfter();
|
||||||
return startBackupMediaDownload();
|
return startBackupMediaDownload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue