Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit 043e5bf

Browse files
committed
Remove transitive dependency on moment-timezone (-5MB install size)
Switch `node-cron` to `cron-schedule`
1 parent 67494da commit 043e5bf

File tree

8 files changed

+101
-174
lines changed

8 files changed

+101
-174
lines changed

package-lock.json

Lines changed: 15 additions & 88 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/miniflare/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@
7272
},
7373
"peerDependencies": {
7474
"@miniflare/storage-redis": "2.0.0-next.3",
75-
"ioredis": "^4.27.9",
76-
"node-cron": "^3.0.0"
75+
"cron-schedule": "^3.0.4",
76+
"ioredis": "^4.27.9"
7777
},
7878
"peerDependenciesMeta": {
7979
"@miniflare/storage-redis": {

packages/miniflare/test/api.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,14 @@ test.serial("Miniflare: startScheduler: starts CRON scheduler", async (t) => {
154154
// Wait for plugins to load, this includes CRON validation
155155
await mf.getPlugins();
156156

157-
const cron = await import("node-cron");
158-
const originalSchedule = cron.default.schedule;
159-
t.teardown(() => (cron.default.schedule = originalSchedule));
160-
cron.default.schedule = (expression, func) => {
161-
t.is(expression, "* * * * *");
157+
const { TimerBasedCronScheduler } = await import("cron-schedule");
158+
const originalSetInterval = TimerBasedCronScheduler.setInterval;
159+
t.teardown(() => (TimerBasedCronScheduler.setInterval = originalSetInterval));
160+
TimerBasedCronScheduler.setInterval = (expression, func) => {
161+
t.is(expression.toString(), "* * * * *");
162162
// Immediately invoke the task because we're impatient
163163
func();
164-
return { destroy: () => t.fail() } as any;
164+
return 0 as any;
165165
};
166166
await mf.startScheduler();
167167
});

packages/scheduler/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@
3838
"dependencies": {
3939
"@miniflare/core": "2.0.0-next.3",
4040
"@miniflare/shared": "2.0.0-next.3",
41-
"node-cron": "^3.0.0"
41+
"cron-schedule": "^3.0.4"
4242
},
4343
"devDependencies": {
44-
"@miniflare/shared-test": "2.0.0-next.3",
45-
"@types/node-cron": "^2.0.4"
44+
"@miniflare/shared-test": "2.0.0-next.3"
4645
}
4746
}

packages/scheduler/src/index.ts

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@ import {
44
ReloadEvent,
55
logResponse,
66
} from "@miniflare/core";
7-
import type { ScheduledTask } from "node-cron";
7+
import type { Cron, ITimerHandle } from "cron-schedule";
88
import { SchedulerPlugin } from "./plugin";
99

1010
export * from "./plugin";
1111

12+
export interface CronScheduler {
13+
setInterval(cron: Cron, task: () => any): ITimerHandle;
14+
clearTimeoutOrInterval(handle: ITimerHandle): void;
15+
}
16+
1217
export type SchedulerPluginSignatures = CorePluginSignatures & {
1318
SchedulerPlugin: typeof SchedulerPlugin;
1419
};
@@ -17,56 +22,63 @@ const kReload = Symbol("kReload");
1722

1823
export class Scheduler<Plugins extends SchedulerPluginSignatures> {
1924
// noinspection JSMismatchedCollectionQueryUpdate
20-
private previousValidatedCrons?: string[];
21-
private scheduledTasks?: ScheduledTask[];
25+
private previousValidatedCrons?: Cron[];
26+
private scheduledHandles?: ITimerHandle[];
2227

2328
constructor(
2429
private readonly mf: MiniflareCore<Plugins>,
25-
private readonly cron: Promise<{
26-
default: typeof import("node-cron");
27-
}> = import("node-cron")
30+
private readonly cronScheduler: Promise<CronScheduler> = import(
31+
"cron-schedule"
32+
).then((module) => module.TimerBasedCronScheduler)
2833
) {
29-
this[kReload] = this[kReload].bind(this);
3034
mf.addEventListener("reload", this[kReload]);
3135
}
3236

33-
async [kReload](event: ReloadEvent<Plugins>): Promise<void> {
37+
[kReload] = async (event: ReloadEvent<Plugins>): Promise<void> => {
3438
const validatedCrons = event.plugins.SchedulerPlugin.validatedCrons;
3539
// Checking references here, if different, SchedulerPlugin setup must've
3640
// been called meaning crons changed so reload scheduled tasks
3741
if (this.previousValidatedCrons === validatedCrons) return;
3842
this.previousValidatedCrons = validatedCrons;
3943

44+
const cronScheduler = await this.cronScheduler;
45+
4046
// Schedule tasks, stopping all current ones first
41-
this.scheduledTasks?.forEach((task) => task.destroy());
47+
this.scheduledHandles?.forEach((handle) =>
48+
cronScheduler.clearTimeoutOrInterval(handle)
49+
);
4250
if (!validatedCrons.length) return;
43-
const cron = await this.cron;
44-
this.scheduledTasks = validatedCrons?.map((expression) =>
45-
cron.default.schedule(expression, async () => {
51+
52+
this.scheduledHandles = validatedCrons?.map((cron) => {
53+
const spec = cron.toString();
54+
return cronScheduler.setInterval(cron, async () => {
4655
const start = process.hrtime();
4756
// scheduledTime will default to Date.now()
48-
const waitUntil = this.mf.dispatchScheduled(undefined, expression);
57+
const waitUntil = this.mf.dispatchScheduled(undefined, spec);
4958
await logResponse(this.mf.log, {
5059
start,
5160
method: "SCHD",
52-
url: expression,
61+
url: spec,
5362
waitUntil,
5463
});
55-
})
56-
);
57-
}
64+
});
65+
});
66+
};
5867

59-
dispose(): void {
68+
async dispose(): Promise<void> {
6069
this.mf.removeEventListener("reload", this[kReload]);
61-
this.scheduledTasks?.forEach((task) => task.destroy());
70+
const cronScheduler = await this.cronScheduler;
71+
this.scheduledHandles?.forEach((handle) =>
72+
cronScheduler.clearTimeoutOrInterval(handle)
73+
);
6274
}
6375
}
6476

6577
export async function startScheduler<Plugins extends SchedulerPluginSignatures>(
6678
mf: MiniflareCore<Plugins>,
67-
cron?: Promise<{ default: typeof import("node-cron") }>
79+
cronScheduler?: Promise<CronScheduler>
6880
): Promise<Scheduler<Plugins>> {
69-
const scheduler = new Scheduler(mf, cron);
81+
const scheduler = new Scheduler(mf, cronScheduler);
7082
await scheduler[kReload](new ReloadEvent(await mf.getPlugins()));
7183
return scheduler;
7284
}

0 commit comments

Comments
 (0)