From 90804491d6c4140cbd77afcd05908b7dc64d253b Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 31 Jan 2023 12:01:14 +1100 Subject: [PATCH] feat: add job result enum with success, retry and permanent fail --- ts/components/leftpane/ActionsPanel.tsx | 18 +--- ts/node/sql.ts | 1 - ts/session/profile_manager/ProfileManager.ts | 31 +++---- .../utils/job_runners/JobDeserialization.ts | 4 +- ts/session/utils/job_runners/JobRunner.ts | 42 +++------ ts/session/utils/job_runners/PersistedJob.ts | 24 +++-- .../job_runners/jobs/AvatarDownloadJob.ts | 89 +++++++++++++++---- .../job_runners/jobs/ConfigurationSyncJob.ts | 15 ++-- .../unit/utils/job_runner/FakeSleepForJob.ts | 21 ++--- .../unit/utils/job_runner/JobRunner_test.ts | 31 ++----- 10 files changed, 140 insertions(+), 136 deletions(-) diff --git a/ts/components/leftpane/ActionsPanel.tsx b/ts/components/leftpane/ActionsPanel.tsx index 1bb547ee3..c03160023 100644 --- a/ts/components/leftpane/ActionsPanel.tsx +++ b/ts/components/leftpane/ActionsPanel.tsx @@ -48,7 +48,6 @@ import { initializeLibSessionUtilWrappers } from '../../session/utils/libsession import { isDarkTheme } from '../../state/selectors/theme'; import { ThemeStateType } from '../../themes/constants/colors'; import { switchThemeTo } from '../../themes/switchTheme'; -import { AvatarDownloadJob } from '../../session/utils/job_runners/jobs/AvatarDownloadJob'; import { runners } from '../../session/utils/job_runners/JobRunner'; const Section = (props: { type: SectionType }) => { @@ -64,20 +63,6 @@ const Section = (props: { type: SectionType }) => { const handleClick = async () => { /* tslint:disable:no-void-expression */ if (type === SectionType.Profile) { - const us = UserUtils.getOurPubKeyStrFromCache(); - const ourConvo = getConversationController().get(us); - - const job = new AvatarDownloadJob({ - conversationId: us, - currentRetry: 0, - delayBetweenRetries: 3000, - maxAttempts: 3, - profileKeyHex: ourConvo.get('profileKey') || null, - profilePictureUrl: ourConvo.get('avatarPointer') || null, - }); - await runners.avatarDownloadRunner.loadJobsFromDb(); - runners.avatarDownloadRunner.startProcessing(); - await runners.avatarDownloadRunner.addJob(job); dispatch(editProfileModal({})); } else if (type === SectionType.ColorMode) { const currentTheme = String(window.Events.getThemeSetting()); @@ -214,6 +199,9 @@ const doAppStartUp = async () => { // this generates the key to encrypt attachments locally await Data.generateAttachmentKeyIfEmpty(); + await runners.avatarDownloadRunner.loadJobsFromDb(); + runners.avatarDownloadRunner.startProcessing(); + // trigger a sync message if needed for our other devices void triggerSyncIfNeeded(); void getSwarmPollingInstance().start(); diff --git a/ts/node/sql.ts b/ts/node/sql.ts index 8481be09e..4e10e7bef 100644 --- a/ts/node/sql.ts +++ b/ts/node/sql.ts @@ -410,7 +410,6 @@ function getConversationCount() { // tslint:disable-next-line: max-func-body-length function saveConversation(data: ConversationAttributes, instance?: BetterSqlite3.Database) { const formatted = assertValidConversationAttributes(data); - console.warn('formatted', formatted); const { id, diff --git a/ts/session/profile_manager/ProfileManager.ts b/ts/session/profile_manager/ProfileManager.ts index e428d557f..b585a4241 100644 --- a/ts/session/profile_manager/ProfileManager.ts +++ b/ts/session/profile_manager/ProfileManager.ts @@ -2,11 +2,7 @@ import { to_hex } from 'libsodium-wrappers-sumo'; import { isEmpty } from 'lodash'; import { getConversationController } from '../conversations'; import { UserUtils } from '../utils'; -import { runners } from '../utils/job_runners/JobRunner'; -import { - AvatarDownloadJob, - shouldAddAvatarDownloadJob, -} from '../utils/job_runners/jobs/AvatarDownloadJob'; +import { AvatarDownload } from '../utils/job_runners/jobs/AvatarDownloadJob'; /** * This can be used to update our conversation display name with the given name right away, and plan an AvatarDownloadJob to retrieve the new avatar if needed to download it @@ -16,18 +12,14 @@ async function updateOurProfileSync( profileUrl: string | null, profileKey: Uint8Array | null ) { - const ourConvo = getConversationController().get(UserUtils.getOurPubKeyStrFromCache()); + const us = UserUtils.getOurPubKeyStrFromCache(); + const ourConvo = getConversationController().get(us); if (!ourConvo?.id) { - window?.log?.warn('[profileupdate] Cannot update our profile with empty convoid'); + window?.log?.warn('[profileupdate] Cannot update our profile without convo associated'); return; } - return updateProfileOfContact( - UserUtils.getOurPubKeyStrFromCache(), - displayName, - profileUrl, - profileKey - ); + return updateProfileOfContact(us, displayName, profileUrl, profileKey); } /** @@ -56,15 +48,12 @@ async function updateProfileOfContact( // add an avatar download job only if needed const profileKeyHex = !profileKey || isEmpty(profileKey) ? null : to_hex(profileKey); - if (shouldAddAvatarDownloadJob({ pubkey, profileUrl, profileKeyHex })) { - const avatarDownloadJob = new AvatarDownloadJob({ - conversationId: pubkey, - profileKeyHex, - profilePictureUrl: profileUrl || null, - }); - await runners.avatarDownloadRunner.addJob(avatarDownloadJob); - } + await AvatarDownload.addAvatarDownloadJobIfNeeded({ + profileKeyHex, + profileUrl, + pubkey, + }); } export const ProfileManager = { diff --git a/ts/session/utils/job_runners/JobDeserialization.ts b/ts/session/utils/job_runners/JobDeserialization.ts index ed991b578..c7bb79049 100644 --- a/ts/session/utils/job_runners/JobDeserialization.ts +++ b/ts/session/utils/job_runners/JobDeserialization.ts @@ -3,7 +3,7 @@ import { FakeSleepForJob, FakeSleepForMultiJob, } from '../../../test/session/unit/utils/job_runner/FakeSleepForJob'; -import { AvatarDownloadJob } from './jobs/AvatarDownloadJob'; +import { AvatarDownload } from './jobs/AvatarDownloadJob'; import { ConfigurationSyncJob } from './jobs/ConfigurationSyncJob'; import { PersistedJob, TypeOfPersistedData } from './PersistedJob'; @@ -19,7 +19,7 @@ export function persistedJobFromData( return (new ConfigurationSyncJob(data) as unknown) as PersistedJob; case 'AvatarDownloadJobType': - return (new AvatarDownloadJob(data) as unknown) as PersistedJob; + return (new AvatarDownload.AvatarDownloadJob(data) as unknown) as PersistedJob; case 'FakeSleepForJobType': return (new FakeSleepForJob(data) as unknown) as PersistedJob; case 'FakeSleepForJobMultiType': diff --git a/ts/session/utils/job_runners/JobRunner.ts b/ts/session/utils/job_runners/JobRunner.ts index aa7838143..9c27d0318 100644 --- a/ts/session/utils/job_runners/JobRunner.ts +++ b/ts/session/utils/job_runners/JobRunner.ts @@ -6,6 +6,7 @@ import { AvatarDownloadPersistedData, ConfigurationSyncPersistedData, PersistedJob, + RunJobResult, TypeOfPersistedData, } from './PersistedJob'; @@ -19,13 +20,6 @@ export type StartProcessingResult = 'job_in_progress' | 'job_deferred' | 'job_st export type AddJobResult = 'job_deferred' | 'job_started'; -export type JobEventListener = { - onJobSuccess: (job: TypeOfPersistedData) => void; - onJobDeferred: (job: TypeOfPersistedData) => void; - onJobError: (job: TypeOfPersistedData) => void; - onJobStarted: (job: TypeOfPersistedData) => void; -}; - /** * This class is used to plan jobs and make sure they are retried until the success. * By having a specific type, we can find the logic to be run by that type of job. @@ -43,11 +37,9 @@ export class PersistedJobRunner { private readonly jobRunnerType: JobRunnerType; private nextJobStartTimer: NodeJS.Timeout | null = null; private currentJob: PersistedJob | null = null; - private readonly jobEventsListener: JobEventListener | null; - constructor(jobRunnerType: JobRunnerType, jobEventsListener: JobEventListener | null) { + constructor(jobRunnerType: JobRunnerType, _jobEventsListener: null) { this.jobRunnerType = jobRunnerType; - this.jobEventsListener = jobEventsListener; window?.log?.warn(`new runner of type ${jobRunnerType} built`); } @@ -96,10 +88,8 @@ export class PersistedJobRunner { .map(k => k.serializeJob()); const addJobChecks = job.addJobCheck(serializedNonRunningJobs); - if (addJobChecks === 'skipAsJobTypeAlreadyPresent') { - window.log.warn( - `job runner has already a job with type:"${job.persistedData.jobType}" planned so not adding another one` - ); + if (addJobChecks === 'skipAddSameJobPresent') { + window.log.warn(`addjobCheck returned "${addJobChecks}" so not adding it`); return 'type_exists'; } @@ -288,6 +278,7 @@ export class PersistedJobRunner { this.planNextJob(); return; } + let success: RunJobResult | null = null; try { if (this.currentJob) { @@ -295,11 +286,9 @@ export class PersistedJobRunner { } this.currentJob = nextJob; - this.jobEventsListener?.onJobStarted(this.currentJob.serializeJob()); - - const success = await this.currentJob.runJob(); + success = await this.currentJob.runJob(); - if (!success) { + if (success !== RunJobResult.Success) { throw new Error(`job ${nextJob.persistedData.identifier} failed`); } @@ -307,30 +296,23 @@ export class PersistedJobRunner { this.deleteJobsByIdentifier([this.currentJob.persistedData.identifier]); await this.writeJobsToDB(); } catch (e) { - if (nextJob.persistedData.currentRetry >= nextJob.persistedData.maxAttempts - 1) { + if ( + success === RunJobResult.PermanentFailure || + nextJob.persistedData.currentRetry >= nextJob.persistedData.maxAttempts - 1 + ) { // we cannot restart this job anymore. Remove the entry completely this.deleteJobsByIdentifier([nextJob.persistedData.identifier]); - if (this.jobEventsListener && this.currentJob) { - this.jobEventsListener.onJobError(this.currentJob.serializeJob()); - } } else { nextJob.persistedData.currentRetry = nextJob.persistedData.currentRetry + 1; // that job can be restarted. Plan a retry later with the already defined retry nextJob.persistedData.nextAttemptTimestamp = Date.now() + nextJob.persistedData.delayBetweenRetries; - if (this.jobEventsListener && this.currentJob) { - this.jobEventsListener.onJobDeferred(this.currentJob.serializeJob()); - } } // in any case, either we removed a job or changed one of the timestamp. // so sort the list again, and persist it this.sortJobsList(); await this.writeJobsToDB(); } finally { - if (this.jobEventsListener && this.currentJob) { - this.jobEventsListener.onJobSuccess(this.currentJob.serializeJob()); - } - this.currentJob = null; // start the next job if there is any to be started now, or just plan the wakeup of our runner for the right time. @@ -341,7 +323,7 @@ export class PersistedJobRunner { private assertIsInitialized() { if (!this.isInit) { throw new Error( - 'persisted job runner was not initlized yet. Call initWithData with what you have persisted first' + 'persisted job runner was not initlized yet. Call loadJobsFromDb with what you have persisted first' ); } } diff --git a/ts/session/utils/job_runners/PersistedJob.ts b/ts/session/utils/job_runners/PersistedJob.ts index b9f3350c6..1faa0f0d8 100644 --- a/ts/session/utils/job_runners/PersistedJob.ts +++ b/ts/session/utils/job_runners/PersistedJob.ts @@ -43,6 +43,18 @@ export type TypeOfPersistedData = | FakeSleepJobData | FakeSleepForMultiJobData; +export type AddJobCheckReturn = + | 'skipAddSameJobPresent' + | 'removeJobsFromQueue' + | 'sameJobDataAlreadyInQueue' + | null; + +export enum RunJobResult { + Success = 1, + RetryJobIfPossible = 2, + PermanentFailure = 3, +} + /** * This class can be used to save and run jobs from the database. * Every child class must take the minimum amount of arguments, and make sure they are unlikely to change. @@ -55,7 +67,7 @@ export type TypeOfPersistedData = export abstract class PersistedJob { public persistedData: T; - private runningPromise: Promise | null = null; + private runningPromise: Promise | null = null; public constructor(data: T) { if (data.maxAttempts < 1) { @@ -109,13 +121,11 @@ export abstract class PersistedJob { public abstract nonRunningJobsToRemove(jobs: Array): Array; - public abstract addJobCheck( - jobs: Array - ): 'skipAsJobTypeAlreadyPresent' | 'removeJobsFromQueue' | null; + public abstract addJobCheck(jobs: Array): AddJobCheckReturn; - public addJobCheckSameTypePresent(jobs: Array): 'skipAsJobTypeAlreadyPresent' | null { + public addJobCheckSameTypePresent(jobs: Array): 'skipAddSameJobPresent' | null { return jobs.some(j => j.jobType === this.persistedData.jobType) - ? 'skipAsJobTypeAlreadyPresent' + ? 'skipAddSameJobPresent' : null; } @@ -126,7 +136,7 @@ export abstract class PersistedJob { * * Note: you should check the this.isAborted() to know if you should cancel the current processing of your logic. */ - protected abstract run(): Promise; + protected abstract run(): Promise; protected serializeBase(): T { return cloneDeep(this.persistedData); diff --git a/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts b/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts index 7fa074011..74c43be68 100644 --- a/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts +++ b/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts @@ -1,4 +1,4 @@ -import { isEmpty, isEqual, isNumber } from 'lodash'; +import { isEmpty, isEqual, isNumber, isString } from 'lodash'; import { v4 } from 'uuid'; import { UserUtils } from '../..'; import { downloadAttachment } from '../../../../receiver/attachments'; @@ -8,7 +8,13 @@ import { autoScaleForIncomingAvatar } from '../../../../util/attachmentsUtil'; import { decryptProfile } from '../../../../util/crypto/profileEncrypter'; import { getConversationController } from '../../../conversations'; import { fromHexToArray } from '../../String'; -import { AvatarDownloadPersistedData, PersistedJob } from '../PersistedJob'; +import { runners } from '../JobRunner'; +import { + AddJobCheckReturn, + AvatarDownloadPersistedData, + PersistedJob, + RunJobResult, +} from '../PersistedJob'; const defaultMsBetweenRetries = 10000; const defaultMaxAttemps = 3; @@ -16,7 +22,7 @@ const defaultMaxAttemps = 3; /** * Returns true if given those details we should add an Avatar Download Job to the list of jobs to run */ -export function shouldAddAvatarDownloadJob({ +function shouldAddAvatarDownloadJob({ profileKeyHex, profileUrl, pubkey, @@ -36,22 +42,47 @@ export function shouldAddAvatarDownloadJob({ window.log.warn('shouldAddAvatarDownloadJob can only be used for private convos currently'); return false; } - if (profileUrl && !isEmpty(profileKeyHex)) { - const prevPointer = conversation.get('avatarPointer'); - const needsUpdate = !prevPointer || !isEqual(prevPointer, profileUrl); + const prevPointer = conversation.get('avatarPointer'); - return needsUpdate; + if (!isEmpty(profileUrl) && !isEmpty(profileKeyHex) && !isEqual(prevPointer, profileUrl)) { + return true; } return false; } +async function addAvatarDownloadJobIfNeeded({ + profileKeyHex, + profileUrl, + pubkey, +}: { + pubkey: string; + profileUrl: string | null | undefined; + profileKeyHex: string | null | undefined; +}) { + if (profileKeyHex && shouldAddAvatarDownloadJob({ pubkey, profileUrl, profileKeyHex })) { + const avatarDownloadJob = new AvatarDownloadJob({ + conversationId: pubkey, + profileKeyHex, + profilePictureUrl: profileUrl || null, + }); + window.log.debug( + `addAvatarDownloadJobIfNeeded: adding job download for ${pubkey}:${profileUrl}:${profileKeyHex} ` + ); + await runners.avatarDownloadRunner.addJob(avatarDownloadJob); + } else { + window.log.debug( + `addAvatarDownloadJobIfNeeded: no download required for ${pubkey}:${profileUrl}:${profileKeyHex} ` + ); + } +} + /** * This job can be used to add the downloading of the avatar of a conversation to the list of jobs to be run. * The conversationId is used as identifier so we can only have a single job per conversation. * When the jobRunners starts this job, the job first checks if a download is required or not (avatarPointer changed and wasn't already downloaded). * If yes, it downloads the new avatar, decrypt it and store it before updating the conversation with the new url,profilekey and local file storage. */ -export class AvatarDownloadJob extends PersistedJob { +class AvatarDownloadJob extends PersistedJob { constructor({ conversationId, nextAttemptTimestamp, @@ -86,7 +117,7 @@ export class AvatarDownloadJob extends PersistedJob } // tslint:disable-next-line: cyclomatic-complexity - public async run(): Promise { + public async run(): Promise { const convoId = this.persistedData.conversationId; window.log.warn( @@ -95,7 +126,7 @@ export class AvatarDownloadJob extends PersistedJob if (!this.persistedData.identifier || !convoId) { // return true so we do not retry this task. - return true; + return RunJobResult.PermanentFailure; } let conversation = getConversationController().get(convoId); @@ -103,11 +134,11 @@ export class AvatarDownloadJob extends PersistedJob // return true so we do not retry this task. window.log.warn('AvatarDownloadJob did not corresponding conversation'); - return true; + return RunJobResult.PermanentFailure; } if (!conversation.isPrivate()) { window.log.warn('AvatarDownloadJob can only be used for private convos currently'); - return true; + return RunJobResult.PermanentFailure; } let changes = false; @@ -120,7 +151,7 @@ export class AvatarDownloadJob extends PersistedJob // return true so we do not retry this task. window.log.warn('AvatarDownloadJob shouldAddAvatarDownloadJob said no'); - return true; + return RunJobResult.PermanentFailure; } if (this.persistedData.profilePictureUrl && this.persistedData.profileKeyHex) { @@ -162,16 +193,23 @@ export class AvatarDownloadJob extends PersistedJob ({ path } = upgraded); } catch (e) { window?.log?.error(`[profileupdate] Could not decrypt profile image: ${e}`); + return RunJobResult.RetryJobIfPossible; // so we retry this job } conversation.set({ avatarInProfile: path || undefined }); changes = true; } catch (e) { + if (isString(e.message) && (e.message as string).includes('404')) { + window.log.warn( + `[profileupdate] Failed to download attachment at ${this.persistedData.profilePictureUrl}. We got 404 error: "${e.message}"` + ); + return RunJobResult.PermanentFailure; + } window.log.warn( `[profileupdate] Failed to download attachment at ${this.persistedData.profilePictureUrl}. Maybe it expired? ${e.message}` ); - // do not return here, we still want to update the display name even if the avatar failed to download + return RunJobResult.RetryJobIfPossible; } } } else { @@ -210,7 +248,7 @@ export class AvatarDownloadJob extends PersistedJob } // return true so this job is marked as a success - return true; + return RunJobResult.Success; } public serializeJob(): AvatarDownloadPersistedData { @@ -222,12 +260,27 @@ export class AvatarDownloadJob extends PersistedJob return jobs.filter(j => j.conversationId === this.persistedData.conversationId); } - public addJobCheck( - jobs: Array - ): 'skipAsJobTypeAlreadyPresent' | 'removeJobsFromQueue' | null { + public addJobCheck(jobs: Array): AddJobCheckReturn { + // avoid adding the same job if the exact same one is already planned + const hasSameJob = jobs.some(j => { + return ( + j.conversationId === this.persistedData.conversationId && + j.profileKeyHex === this.persistedData.profileKeyHex && + j.profilePictureUrl === this.persistedData.profilePictureUrl + ); + }); + + if (hasSameJob) { + return 'skipAddSameJobPresent'; + } if (this.nonRunningJobsToRemove(jobs).length) { return 'removeJobsFromQueue'; } return null; } } + +export const AvatarDownload = { + AvatarDownloadJob, + addAvatarDownloadJobIfNeeded, +}; diff --git a/ts/session/utils/job_runners/jobs/ConfigurationSyncJob.ts b/ts/session/utils/job_runners/jobs/ConfigurationSyncJob.ts index cb5b8778d..0757db304 100644 --- a/ts/session/utils/job_runners/jobs/ConfigurationSyncJob.ts +++ b/ts/session/utils/job_runners/jobs/ConfigurationSyncJob.ts @@ -1,6 +1,11 @@ import { v4 } from 'uuid'; import { sleepFor } from '../../Promise'; -import { ConfigurationSyncPersistedData, PersistedJob } from '../PersistedJob'; +import { + AddJobCheckReturn, + ConfigurationSyncPersistedData, + PersistedJob, + RunJobResult, +} from '../PersistedJob'; const defaultMsBetweenRetries = 3000; @@ -22,7 +27,7 @@ export class ConfigurationSyncJob extends PersistedJob { // blablha do everything from the notion page, and if success, return true. window.log.warn( `running job ${this.persistedData.jobType} with id:"${this.persistedData.identifier}" ` @@ -33,7 +38,7 @@ export class ConfigurationSyncJob extends PersistedJob - ): 'skipAsJobTypeAlreadyPresent' | 'removeJobsFromQueue' | null { + public addJobCheck(jobs: Array): AddJobCheckReturn { return this.addJobCheckSameTypePresent(jobs); } diff --git a/ts/test/session/unit/utils/job_runner/FakeSleepForJob.ts b/ts/test/session/unit/utils/job_runner/FakeSleepForJob.ts index cedab8f53..a3263d100 100644 --- a/ts/test/session/unit/utils/job_runner/FakeSleepForJob.ts +++ b/ts/test/session/unit/utils/job_runner/FakeSleepForJob.ts @@ -2,9 +2,11 @@ import { isNumber } from 'lodash'; import { v4 } from 'uuid'; import { sleepFor } from '../../../../../session/utils/Promise'; import { + AddJobCheckReturn, FakeSleepForMultiJobData, FakeSleepJobData, PersistedJob, + RunJobResult, } from '../../../../../session/utils/job_runners/PersistedJob'; export class FakeSleepForMultiJob extends PersistedJob { @@ -34,7 +36,7 @@ export class FakeSleepForMultiJob extends PersistedJob } } - public async run() { + public async run(): Promise { window.log.warn( `running job ${this.persistedData.jobType} with id:"${this.persistedData.identifier}". sleeping for ${this.persistedData.sleepDuration} & returning ${this.persistedData.returnResult} ` ); @@ -42,7 +44,10 @@ export class FakeSleepForMultiJob extends PersistedJob window.log.warn( `${this.persistedData.jobType} with id:"${this.persistedData.identifier}" done. returning success ` ); - return this.persistedData.returnResult; + if (this.persistedData.returnResult) { + return RunJobResult.Success; + } + return RunJobResult.RetryJobIfPossible; } public serializeJob(): FakeSleepForMultiJobData { @@ -52,9 +57,7 @@ export class FakeSleepForMultiJob extends PersistedJob /** * For the fakesleep for multi, we want to allow as many job as we want, so this returns null */ - public addJobCheck( - _jobs: Array - ): 'skipAsJobTypeAlreadyPresent' | 'removeJobsFromQueue' | null { + public addJobCheck(_jobs: Array): AddJobCheckReturn { return null; } @@ -89,7 +92,7 @@ export class FakeSleepForJob extends PersistedJob { } } - public async run() { + public async run(): Promise { window.log.warn( `running job ${this.persistedData.jobType} with id:"${this.persistedData.identifier}" ` ); @@ -97,16 +100,14 @@ export class FakeSleepForJob extends PersistedJob { window.log.warn( `${this.persistedData.jobType} with id:"${this.persistedData.identifier}" done. returning failed ` ); - return false; + return RunJobResult.RetryJobIfPossible; } public serializeJob(): FakeSleepJobData { return super.serializeBase(); } - public addJobCheck( - jobs: Array - ): 'skipAsJobTypeAlreadyPresent' | 'removeJobsFromQueue' | null { + public addJobCheck(jobs: Array): AddJobCheckReturn { return this.addJobCheckSameTypePresent(jobs); } diff --git a/ts/test/session/unit/utils/job_runner/JobRunner_test.ts b/ts/test/session/unit/utils/job_runner/JobRunner_test.ts index 4592596d5..9060e0639 100644 --- a/ts/test/session/unit/utils/job_runner/JobRunner_test.ts +++ b/ts/test/session/unit/utils/job_runner/JobRunner_test.ts @@ -2,15 +2,11 @@ import { expect } from 'chai'; import _, { isUndefined } from 'lodash'; import Sinon from 'sinon'; import { v4 } from 'uuid'; -import { - JobEventListener, - PersistedJobRunner, -} from '../../../../../session/utils/job_runners/JobRunner'; +import { PersistedJobRunner } from '../../../../../session/utils/job_runners/JobRunner'; import { FakeSleepForJob, FakeSleepForMultiJob } from './FakeSleepForJob'; import { FakeSleepForMultiJobData, FakeSleepJobData, - TypeOfPersistedData, } from '../../../../../session/utils/job_runners/PersistedJob'; import { sleepFor } from '../../../../../session/utils/Promise'; import { stubData } from '../../../../test-utils/utils'; @@ -55,31 +51,13 @@ describe('JobRunner', () => { let clock: Sinon.SinonFakeTimers; let runner: PersistedJobRunner; let runnerMulti: PersistedJobRunner; - let jobEventsListener: JobEventListener; beforeEach(() => { getItemById = stubData('getItemById'); stubData('createOrUpdateItem'); clock = Sinon.useFakeTimers({ shouldAdvanceTime: true }); - jobEventsListener = { - onJobDeferred: (_job: TypeOfPersistedData) => { - // window.log.warn('listener got deferred for job ', job); - }, - onJobSuccess: (_job: TypeOfPersistedData) => { - // window.log.warn('listener got success for job ', job); - }, - onJobError: (_job: TypeOfPersistedData) => { - // window.log.warn('listener got error for job ', job); - }, - onJobStarted: (_job: TypeOfPersistedData) => { - // window.log.warn('listener got started for job ', job); - }, - }; - runner = new PersistedJobRunner('FakeSleepForJob', jobEventsListener); - runnerMulti = new PersistedJobRunner( - 'FakeSleepForMultiJob', - jobEventsListener - ); + runner = new PersistedJobRunner('FakeSleepForJob', null); + runnerMulti = new PersistedJobRunner('FakeSleepForMultiJob', null); }); afterEach(() => { @@ -95,8 +73,9 @@ describe('JobRunner', () => { id: '', value: JSON.stringify([]), }); + const job = getFakeSleepForJob(123); - await runner.loadJobsFromDb(); + await runner.addJob(job); throw new Error('PLOP'); // the line above should throw something else } catch (e) { expect(e.message).to.not.eq('PLOP');