diff --git a/packages/snaps-controllers/src/cronjob/CronjobController.test.ts b/packages/snaps-controllers/src/cronjob/CronjobController.test.ts index 767b72b04b..80b58d4827 100644 --- a/packages/snaps-controllers/src/cronjob/CronjobController.test.ts +++ b/packages/snaps-controllers/src/cronjob/CronjobController.test.ts @@ -443,6 +443,54 @@ describe('CronjobController', () => { cronjobController.destroy(); }); + it('handles scheduled event close to current time gracefully', () => { + const rootMessenger = getRootCronjobControllerMessenger(); + const controllerMessenger = + getRestrictedCronjobControllerMessenger(rootMessenger); + + const cronjobController = new CronjobController({ + messenger: controllerMessenger, + state: { + events: { + foo: { + id: 'foo', + recurring: false, + date: '2022-01-01T00:00:01.000Z', + schedule: '2022-01-01T00:00:01.000Z', + scheduledAt: new Date().toISOString(), + snapId: MOCK_SNAP_ID, + request: { + method: 'handleEvent', + params: ['p1'], + }, + }, + }, + }, + }); + + rootMessenger.subscribe('CronjobController:stateChange', () => { + jest.advanceTimersByTime(inMilliseconds(2, Duration.Second)); + }); + + cronjobController.init(); + + expect(rootMessenger.call).toHaveBeenNthCalledWith( + 1, + 'SnapController:handleRequest', + { + snapId: MOCK_SNAP_ID, + origin: METAMASK_ORIGIN, + handler: HandlerType.OnCronjob, + request: { + method: 'handleEvent', + params: ['p1'], + }, + }, + ); + + cronjobController.destroy(); + }); + it('handles the `snapInstalled` event', () => { const rootMessenger = getRootCronjobControllerMessenger(); const controllerMessenger = diff --git a/packages/snaps-controllers/src/cronjob/CronjobController.ts b/packages/snaps-controllers/src/cronjob/CronjobController.ts index f967a33e6f..15c9a97c8b 100644 --- a/packages/snaps-controllers/src/cronjob/CronjobController.ts +++ b/packages/snaps-controllers/src/cronjob/CronjobController.ts @@ -415,6 +415,13 @@ export class CronjobController extends BaseController< return; } + // When an event is supposed to be scheduled close to the current time + // we may end up needing to execute immediately instead. + if (ms <= 0) { + this.#execute(event); + return; + } + const timer = new Timer(ms); timer.start(() => { this.#execute(event);