mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 08:33:43 -05:00
feat(cron): added the support for json type schedule to cron api (#21340)
Added the support for JSON type schedule to cron API; previously it was string only. fixes #21122
This commit is contained in:
parent
8050cbf39e
commit
ab755a07d8
3 changed files with 197 additions and 6 deletions
|
@ -1,5 +1,9 @@
|
|||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||
import { assertEquals, assertThrows } from "./test_util.ts";
|
||||
import {
|
||||
formatToCronSchedule,
|
||||
parseScheduleToString,
|
||||
} from "../../../ext/cron/01_cron.ts";
|
||||
|
||||
const sleep = (time: number) => new Promise((r) => setTimeout(r, time));
|
||||
|
||||
|
@ -170,6 +174,31 @@ Deno.test(async function basicTest() {
|
|||
}
|
||||
});
|
||||
|
||||
Deno.test(async function basicTestWithJsonFormatScheduleExpression() {
|
||||
Deno.env.set("DENO_CRON_TEST_SCHEDULE_OFFSET", "100");
|
||||
|
||||
let count = 0;
|
||||
const { promise, resolve } = Promise.withResolvers<void>();
|
||||
const ac = new AbortController();
|
||||
const c = Deno.cron(
|
||||
"abc",
|
||||
{ minute: { every: 20 } },
|
||||
{ signal: ac.signal },
|
||||
() => {
|
||||
count++;
|
||||
if (count > 5) {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
);
|
||||
try {
|
||||
await promise;
|
||||
} finally {
|
||||
ac.abort();
|
||||
await c;
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test(async function multipleCrons() {
|
||||
Deno.env.set("DENO_CRON_TEST_SCHEDULE_OFFSET", "100");
|
||||
|
||||
|
@ -284,3 +313,67 @@ Deno.test(async function retriesWithBackoffScheduleOldApi() {
|
|||
// The cron should have executed 3 times (1st attempt and 2 retries).
|
||||
assertEquals(count, 3);
|
||||
});
|
||||
|
||||
Deno.test("formatToCronSchedule - undefined value", () => {
|
||||
const result = formatToCronSchedule();
|
||||
assertEquals(result, "*");
|
||||
});
|
||||
|
||||
Deno.test("formatToCronSchedule - number value", () => {
|
||||
const result = formatToCronSchedule(5);
|
||||
assertEquals(result, "5");
|
||||
});
|
||||
|
||||
Deno.test("formatToCronSchedule - exact array value", () => {
|
||||
const result = formatToCronSchedule({ exact: [1, 2, 3] });
|
||||
assertEquals(result, "1,2,3");
|
||||
});
|
||||
|
||||
Deno.test("formatToCronSchedule - exact number value", () => {
|
||||
const result = formatToCronSchedule({ exact: 5 });
|
||||
assertEquals(result, "5");
|
||||
});
|
||||
|
||||
Deno.test("formatToCronSchedule - start, end, every values", () => {
|
||||
const result = formatToCronSchedule({ start: 1, end: 10, every: 2 });
|
||||
assertEquals(result, "1-10/2");
|
||||
});
|
||||
|
||||
Deno.test("formatToCronSchedule - start, end values", () => {
|
||||
const result = formatToCronSchedule({ start: 1, end: 10 });
|
||||
assertEquals(result, "1-10");
|
||||
});
|
||||
|
||||
Deno.test("formatToCronSchedule - start, every values", () => {
|
||||
const result = formatToCronSchedule({ start: 1, every: 2 });
|
||||
assertEquals(result, "1/2");
|
||||
});
|
||||
|
||||
Deno.test("formatToCronSchedule - start value", () => {
|
||||
const result = formatToCronSchedule({ start: 1 });
|
||||
assertEquals(result, "1/1");
|
||||
});
|
||||
|
||||
Deno.test("formatToCronSchedule - end, every values", () => {
|
||||
assertThrows(
|
||||
() => formatToCronSchedule({ end: 10, every: 2 }),
|
||||
TypeError,
|
||||
"Invalid cron schedule",
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("Parse CronSchedule to string", () => {
|
||||
const result = parseScheduleToString({
|
||||
minute: { exact: [1, 2, 3] },
|
||||
hour: { start: 1, end: 10, every: 2 },
|
||||
dayOfMonth: { exact: 5 },
|
||||
month: { start: 1, end: 10 },
|
||||
dayOfWeek: { start: 1, every: 2 },
|
||||
});
|
||||
assertEquals(result, "1,2,3 1-10/2 5 1-10 1/2");
|
||||
});
|
||||
|
||||
Deno.test("Parse schedule to string - string", () => {
|
||||
const result = parseScheduleToString("* * * * *");
|
||||
assertEquals(result, "* * * * *");
|
||||
});
|
||||
|
|
42
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
42
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
|
@ -1317,11 +1317,41 @@ declare namespace Deno {
|
|||
*/
|
||||
export function openKv(path?: string): Promise<Deno.Kv>;
|
||||
|
||||
/** **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* CronScheduleExpression is used as the type of `minute`, `hour`,
|
||||
* `dayOfMonth`, `month`, and `dayOfWeek` in {@linkcode CronSchedule}.
|
||||
* @category Cron
|
||||
*/
|
||||
type CronScheduleExpression = number | { exact: number | number[] } | {
|
||||
start?: number;
|
||||
end?: number;
|
||||
every?: number;
|
||||
};
|
||||
|
||||
/** **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* CronSchedule is the interface used for JSON format
|
||||
* cron `schedule`.
|
||||
* @category Cron
|
||||
*/
|
||||
export interface CronSchedule {
|
||||
minute?: CronScheduleExpression;
|
||||
hour?: CronScheduleExpression;
|
||||
dayOfMonth?: CronScheduleExpression;
|
||||
month?: CronScheduleExpression;
|
||||
dayOfWeek?: CronScheduleExpression;
|
||||
}
|
||||
|
||||
/** **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* Create a cron job that will periodically execute the provided handler
|
||||
* callback based on the specified schedule.
|
||||
*
|
||||
* `schedule` can be a string in the Unix cron format or in JSON format
|
||||
* as specified by interface {@linkcode CronSchedule}, where time is specified
|
||||
* using UTC time zone.
|
||||
*
|
||||
* ```ts
|
||||
* Deno.cron("sample cron", "20 * * * *", () => {
|
||||
* console.log("cron job executed");
|
||||
|
@ -1339,7 +1369,7 @@ declare namespace Deno {
|
|||
*/
|
||||
export function cron(
|
||||
name: string,
|
||||
schedule: string,
|
||||
schedule: string | CronSchedule,
|
||||
handler: () => Promise<void> | void,
|
||||
options: { backoffSchedule?: number[]; signal?: AbortSignal },
|
||||
): Promise<void>;
|
||||
|
@ -1355,14 +1385,15 @@ declare namespace Deno {
|
|||
* });
|
||||
* ```
|
||||
*
|
||||
* `schedule` is a Unix cron format expression, where time is specified
|
||||
* `schedule` can be a string in the Unix cron format or in JSON format
|
||||
* as specified by interface {@linkcode CronSchedule}, where time is specified
|
||||
* using UTC time zone.
|
||||
*
|
||||
* @category Cron
|
||||
*/
|
||||
export function cron(
|
||||
name: string,
|
||||
schedule: string,
|
||||
schedule: string | CronSchedule,
|
||||
handler: () => Promise<void> | void,
|
||||
): Promise<void>;
|
||||
|
||||
|
@ -1379,7 +1410,8 @@ declare namespace Deno {
|
|||
* });
|
||||
* ```
|
||||
*
|
||||
* `schedule` is a Unix cron format expression, where time is specified
|
||||
* `schedule` can be a string in the Unix cron format or in JSON format
|
||||
* as specified by interface {@linkcode CronSchedule}, where time is specified
|
||||
* using UTC time zone.
|
||||
*
|
||||
* `backoffSchedule` option can be used to specify the retry policy for failed
|
||||
|
@ -1392,7 +1424,7 @@ declare namespace Deno {
|
|||
*/
|
||||
export function cron(
|
||||
name: string,
|
||||
schedule: string,
|
||||
schedule: string | CronSchedule,
|
||||
options: { backoffSchedule?: number[]; signal?: AbortSignal },
|
||||
handler: () => Promise<void> | void,
|
||||
): Promise<void>;
|
||||
|
|
|
@ -3,9 +3,73 @@
|
|||
// @ts-ignore internal api
|
||||
const core = Deno.core;
|
||||
|
||||
export function formatToCronSchedule(
|
||||
value?: number | { exact: number | number[] } | {
|
||||
start?: number;
|
||||
end?: number;
|
||||
every?: number;
|
||||
},
|
||||
): string {
|
||||
if (value === undefined) {
|
||||
return "*";
|
||||
} else if (typeof value === "number") {
|
||||
return value.toString();
|
||||
} else {
|
||||
const { exact } = value as { exact: number | number[] };
|
||||
if (exact === undefined) {
|
||||
const { start, end, every } = value as {
|
||||
start?: number;
|
||||
end?: number;
|
||||
every?: number;
|
||||
};
|
||||
if (start !== undefined && end !== undefined && every !== undefined) {
|
||||
return start + "-" + end + "/" + every;
|
||||
} else if (start !== undefined && end !== undefined) {
|
||||
return start + "-" + end;
|
||||
} else if (start !== undefined && every !== undefined) {
|
||||
return start + "/" + every;
|
||||
} else if (start !== undefined) {
|
||||
return start + "/1";
|
||||
} else if (end === undefined && every !== undefined) {
|
||||
return "*/" + every;
|
||||
} else {
|
||||
throw new TypeError("Invalid cron schedule");
|
||||
}
|
||||
} else {
|
||||
if (typeof exact === "number") {
|
||||
return exact.toString();
|
||||
} else {
|
||||
return exact.join(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function parseScheduleToString(
|
||||
schedule: string | Deno.CronSchedule,
|
||||
): string {
|
||||
if (typeof schedule === "string") {
|
||||
return schedule;
|
||||
} else {
|
||||
const {
|
||||
minute,
|
||||
hour,
|
||||
dayOfMonth,
|
||||
month,
|
||||
dayOfWeek,
|
||||
} = schedule;
|
||||
|
||||
return formatToCronSchedule(minute) +
|
||||
" " + formatToCronSchedule(hour) +
|
||||
" " + formatToCronSchedule(dayOfMonth) +
|
||||
" " + formatToCronSchedule(month) +
|
||||
" " + formatToCronSchedule(dayOfWeek);
|
||||
}
|
||||
}
|
||||
|
||||
function cron(
|
||||
name: string,
|
||||
schedule: string,
|
||||
schedule: string | Deno.CronSchedule,
|
||||
handlerOrOptions1:
|
||||
| (() => Promise<void> | void)
|
||||
| ({ backoffSchedule?: number[]; signal?: AbortSignal }),
|
||||
|
@ -20,6 +84,8 @@ function cron(
|
|||
throw new TypeError("Deno.cron requires a valid schedule");
|
||||
}
|
||||
|
||||
schedule = parseScheduleToString(schedule);
|
||||
|
||||
let handler: () => Promise<void> | void;
|
||||
let options: { backoffSchedule?: number[]; signal?: AbortSignal } | undefined;
|
||||
|
||||
|
|
Loading…
Reference in a new issue