Skip to content

Commit 37e79af

Browse files
fix: Properly catch cronjob errors during initialization (#3373)
This PR fixes two issues: Firstly, we were not catching errors thrown during the "daily checkin" of the `CronjobController`, this means that if one Snap failed we would not complete the initialization of the controller and no cronjobs would run. Secondly, we were running all the cronjobs sequentially during "daily check" which seems unintentional given that we don't need the result of the cronjob invocation.
1 parent 8ded935 commit 37e79af

File tree

3 files changed

+43
-14
lines changed

3 files changed

+43
-14
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"branches": 93.51,
3-
"functions": 97.36,
4-
"lines": 98.33,
5-
"statements": 98.17
3+
"functions": 98.14,
4+
"lines": 98.48,
5+
"statements": 98.31
66
}

packages/snaps-controllers/src/cronjob/CronjobController.test.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ describe('CronjobController', () => {
9191
cronjobController.destroy();
9292
});
9393

94-
it('executes cronjobs that were missed during daily check in', async () => {
94+
it('executes cronjobs that were missed during daily check in', () => {
9595
const rootMessenger = getRootCronjobControllerMessenger();
9696
const controllerMessenger =
9797
getRestrictedCronjobControllerMessenger(rootMessenger);
@@ -118,7 +118,7 @@ describe('CronjobController', () => {
118118
};
119119
});
120120

121-
await cronjobController.dailyCheckIn();
121+
cronjobController.dailyCheckIn();
122122

123123
jest.advanceTimersByTime(inMilliseconds(24, Duration.Hour));
124124

@@ -199,6 +199,38 @@ describe('CronjobController', () => {
199199
cronjobController2.destroy();
200200
});
201201

202+
it('catches errors during daily check in', () => {
203+
const rootMessenger = getRootCronjobControllerMessenger();
204+
const controllerMessenger =
205+
getRestrictedCronjobControllerMessenger(rootMessenger);
206+
207+
rootMessenger.registerActionHandler(
208+
'PermissionController:getPermissions',
209+
() => {
210+
return { [SnapEndowments.Cronjob]: getCronjobPermission() };
211+
},
212+
);
213+
214+
const handleRequest = jest.fn().mockRejectedValue('Snap failed to boot.');
215+
216+
rootMessenger.registerActionHandler(
217+
'SnapController:handleRequest',
218+
handleRequest,
219+
);
220+
221+
const cronjobController = new CronjobController({
222+
messenger: controllerMessenger,
223+
});
224+
225+
cronjobController.dailyCheckIn();
226+
227+
jest.advanceTimersByTime(inMilliseconds(24, Duration.Hour));
228+
229+
expect(handleRequest).toHaveBeenCalledTimes(2);
230+
231+
cronjobController.destroy();
232+
});
233+
202234
it('does not schedule cronjob that is too far in the future', () => {
203235
const expression = '59 23 29 2 *'; // At 11:59pm on February 29th
204236

packages/snaps-controllers/src/cronjob/CronjobController.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,7 @@ export class CronjobController extends BaseController<
196196
(...args) => this.getBackgroundEvents(...args),
197197
);
198198

199-
this.dailyCheckIn().catch((error) => {
200-
logError(error);
201-
});
199+
this.dailyCheckIn();
202200

203201
this.#rescheduleBackgroundEvents(Object.values(this.state.events));
204202
}
@@ -471,7 +469,7 @@ export class CronjobController extends BaseController<
471469
*
472470
* This is necessary for longer running jobs that execute with more than 24 hours between them.
473471
*/
474-
async dailyCheckIn() {
472+
dailyCheckIn() {
475473
const jobs = this.#getAllJobs();
476474

477475
for (const job of jobs) {
@@ -483,7 +481,9 @@ export class CronjobController extends BaseController<
483481
parsed.hasPrev() &&
484482
parsed.prev().getTime() > lastRun
485483
) {
486-
await this.#executeCronjob(job);
484+
this.#executeCronjob(job).catch((error) => {
485+
logError(error);
486+
});
487487
}
488488

489489
// Try scheduling, will fail if an existing scheduled job is found
@@ -492,10 +492,7 @@ export class CronjobController extends BaseController<
492492

493493
this.#dailyTimer = new Timer(DAILY_TIMEOUT);
494494
this.#dailyTimer.start(() => {
495-
this.dailyCheckIn().catch((error) => {
496-
// TODO: Decide how to handle errors.
497-
logError(error);
498-
});
495+
this.dailyCheckIn();
499496
});
500497
}
501498

0 commit comments

Comments
 (0)