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

Commit 3b4b175

Browse files
authored
Merge pull request #652 from cloudflare/jspspike/cron-trigger
Trigger scheduled handler on '/cdn-cgi/mf/scheduled'
2 parents cf080a8 + 9b183da commit 3b4b175

File tree

6 files changed

+61
-15
lines changed

6 files changed

+61
-15
lines changed

package-lock.json

Lines changed: 8 additions & 8 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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"zod": "^3.20.6"
4646
},
4747
"devDependencies": {
48-
"@cloudflare/workers-types": "^4.20230419.0",
48+
"@cloudflare/workers-types": "^4.20230807.0",
4949
"@types/better-sqlite3": "^7.6.2",
5050
"@types/debug": "^4.1.7",
5151
"@types/estree": "^1.0.0",

packages/miniflare/src/workers/core/entry.worker.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,29 @@ async function handleQueue(
159159
const flattened = await request.json<number | unknown[]>();
160160
const messages = unflatten(flattened, structuredSerializableRevivers);
161161
const queueResponse = await service.queue(queueName, messages);
162-
(queueResponse as QueueResponse & { time: number }).time =
162+
(queueResponse as FetcherQueueResult & { time: number }).time =
163163
Date.now() - startTime;
164164
return Response.json(queueResponse);
165165
}
166166

167+
async function handleScheduled(
168+
params: URLSearchParams,
169+
service: Fetcher
170+
): Promise<Response> {
171+
const time = params.get("time");
172+
const scheduledTime = time ? new Date(parseInt(time)) : undefined;
173+
const cron = params.get("cron") ?? undefined;
174+
175+
const result = await service.scheduled({
176+
scheduledTime,
177+
cron,
178+
});
179+
180+
return new Response(result.outcome, {
181+
status: result.outcome === "ok" ? 200 : 500,
182+
});
183+
}
184+
167185
export default <ExportedHandler<Env>>{
168186
async fetch(request, env, ctx) {
169187
const startTime = Date.now();
@@ -183,11 +201,14 @@ export default <ExportedHandler<Env>>{
183201

184202
try {
185203
const customEvent = request.headers.get(CoreHeaders.CUSTOM_EVENT);
186-
// TODO(soon): support scheduled events, requires support from workerd
187204
if (customEvent === "queue") {
188205
return await handleQueue(request, url, service, startTime);
189206
}
190207

208+
if (url.pathname === "/cdn-cgi/mf/scheduled") {
209+
return await handleScheduled(url.searchParams, service);
210+
}
211+
191212
let response = await service.fetch(request);
192213
if (!isDispatchFetch) {
193214
response = await maybePrettifyError(request, response, env);

packages/miniflare/test/index.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,3 +498,31 @@ test("Miniflare: Accepts https requests", async (t) => {
498498

499499
t.assert(log.logs[0][1].startsWith("Ready on https://"));
500500
});
501+
502+
test("Miniflare: Manually triggered scheduled events", async (t) => {
503+
const log = new TestLog(t);
504+
505+
const mf = new Miniflare({
506+
log,
507+
modules: true,
508+
script: `
509+
let scheduledRun = false;
510+
export default {
511+
fetch() {
512+
return new Response(scheduledRun);
513+
},
514+
scheduled() {
515+
scheduledRun = true;
516+
}
517+
}`,
518+
});
519+
520+
let res = await mf.dispatchFetch("http://localhost");
521+
t.is(await res.text(), "false");
522+
523+
res = await mf.dispatchFetch("http://localhost/cdn-cgi/mf/scheduled");
524+
t.is(await res.text(), "ok");
525+
526+
res = await mf.dispatchFetch("http://localhost");
527+
t.is(await res.text(), "true");
528+
});

packages/miniflare/test/plugins/d1/shared.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,6 @@ export class TestD1Database implements D1Database {
5454
return this[kSend]("/batch", statements);
5555
}
5656

57-
// @ts-expect-error this function should return a `Promise<D1ExecResult>`,
58-
// not a `Promise<D1Result<T>>`, `@cloudflare/workers-types` is wrong here
59-
// TODO(now): fix in `@cloudflare/workers-types`
6057
async exec(query: string): Promise<D1ExecResult> {
6158
return this[kSend]("/exec", query);
6259
}

packages/miniflare/test/plugins/d1/suite.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ export default (binding: string, WORKER_PATH: string) => {
192192
const select = await db.prepare(`SELECT * FROM ${tableColours}`);
193193
let result: ColourRow | null = await select.first<ColourRow>();
194194
t.deepEqual(result, { id: 1, name: "red", rgb: 0xff0000 });
195-
let id = await select.first<number>("id");
195+
let id: number | null = await select.first<number>("id");
196196
t.is(id, 1);
197197

198198
// Check with multiple statements (should only match on first statement)

0 commit comments

Comments
 (0)