mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 02:28:27 +00:00
refactor(gateway): dedupe cron protocol param schemas
This commit is contained in:
49
src/gateway/protocol/cron-validators.test.ts
Normal file
49
src/gateway/protocol/cron-validators.test.ts
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import {
|
||||||
|
validateCronAddParams,
|
||||||
|
validateCronRemoveParams,
|
||||||
|
validateCronRunParams,
|
||||||
|
validateCronRunsParams,
|
||||||
|
validateCronUpdateParams,
|
||||||
|
} from "./index.js";
|
||||||
|
|
||||||
|
const minimalAddParams = {
|
||||||
|
name: "daily-summary",
|
||||||
|
schedule: { kind: "every", everyMs: 60_000 },
|
||||||
|
sessionTarget: "main",
|
||||||
|
wakeMode: "next-heartbeat",
|
||||||
|
payload: { kind: "systemEvent", text: "tick" },
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
describe("cron protocol validators", () => {
|
||||||
|
it("accepts minimal add params", () => {
|
||||||
|
expect(validateCronAddParams(minimalAddParams)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects add params when required scheduling fields are missing", () => {
|
||||||
|
const { wakeMode: _wakeMode, ...withoutWakeMode } = minimalAddParams;
|
||||||
|
expect(validateCronAddParams(withoutWakeMode)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("accepts update params for id and jobId selectors", () => {
|
||||||
|
expect(validateCronUpdateParams({ id: "job-1", patch: { enabled: false } })).toBe(true);
|
||||||
|
expect(validateCronUpdateParams({ jobId: "job-2", patch: { enabled: true } })).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("accepts remove params for id and jobId selectors", () => {
|
||||||
|
expect(validateCronRemoveParams({ id: "job-1" })).toBe(true);
|
||||||
|
expect(validateCronRemoveParams({ jobId: "job-2" })).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("accepts run params mode for id and jobId selectors", () => {
|
||||||
|
expect(validateCronRunParams({ id: "job-1", mode: "force" })).toBe(true);
|
||||||
|
expect(validateCronRunParams({ jobId: "job-2", mode: "due" })).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("enforces runs limit minimum for id and jobId selectors", () => {
|
||||||
|
expect(validateCronRunsParams({ id: "job-1", limit: 1 })).toBe(true);
|
||||||
|
expect(validateCronRunsParams({ jobId: "job-2", limit: 1 })).toBe(true);
|
||||||
|
expect(validateCronRunsParams({ id: "job-1", limit: 0 })).toBe(false);
|
||||||
|
expect(validateCronRunsParams({ jobId: "job-2", limit: 0 })).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -19,6 +19,35 @@ function cronAgentTurnPayloadSchema(params: { message: TSchema }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CronSessionTargetSchema = Type.Union([Type.Literal("main"), Type.Literal("isolated")]);
|
||||||
|
const CronWakeModeSchema = Type.Union([Type.Literal("next-heartbeat"), Type.Literal("now")]);
|
||||||
|
const CronCommonOptionalFields = {
|
||||||
|
agentId: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
||||||
|
sessionKey: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
||||||
|
description: Type.Optional(Type.String()),
|
||||||
|
enabled: Type.Optional(Type.Boolean()),
|
||||||
|
deleteAfterRun: Type.Optional(Type.Boolean()),
|
||||||
|
};
|
||||||
|
|
||||||
|
function cronIdOrJobIdParams(extraFields: Record<string, TSchema>) {
|
||||||
|
return Type.Union([
|
||||||
|
Type.Object(
|
||||||
|
{
|
||||||
|
id: NonEmptyString,
|
||||||
|
...extraFields,
|
||||||
|
},
|
||||||
|
{ additionalProperties: false },
|
||||||
|
),
|
||||||
|
Type.Object(
|
||||||
|
{
|
||||||
|
jobId: NonEmptyString,
|
||||||
|
...extraFields,
|
||||||
|
},
|
||||||
|
{ additionalProperties: false },
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
export const CronScheduleSchema = Type.Union([
|
export const CronScheduleSchema = Type.Union([
|
||||||
Type.Object(
|
Type.Object(
|
||||||
{
|
{
|
||||||
@@ -144,8 +173,8 @@ export const CronJobSchema = Type.Object(
|
|||||||
createdAtMs: Type.Integer({ minimum: 0 }),
|
createdAtMs: Type.Integer({ minimum: 0 }),
|
||||||
updatedAtMs: Type.Integer({ minimum: 0 }),
|
updatedAtMs: Type.Integer({ minimum: 0 }),
|
||||||
schedule: CronScheduleSchema,
|
schedule: CronScheduleSchema,
|
||||||
sessionTarget: Type.Union([Type.Literal("main"), Type.Literal("isolated")]),
|
sessionTarget: CronSessionTargetSchema,
|
||||||
wakeMode: Type.Union([Type.Literal("next-heartbeat"), Type.Literal("now")]),
|
wakeMode: CronWakeModeSchema,
|
||||||
payload: CronPayloadSchema,
|
payload: CronPayloadSchema,
|
||||||
delivery: Type.Optional(CronDeliverySchema),
|
delivery: Type.Optional(CronDeliverySchema),
|
||||||
state: CronJobStateSchema,
|
state: CronJobStateSchema,
|
||||||
@@ -165,14 +194,10 @@ export const CronStatusParamsSchema = Type.Object({}, { additionalProperties: fa
|
|||||||
export const CronAddParamsSchema = Type.Object(
|
export const CronAddParamsSchema = Type.Object(
|
||||||
{
|
{
|
||||||
name: NonEmptyString,
|
name: NonEmptyString,
|
||||||
agentId: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
...CronCommonOptionalFields,
|
||||||
sessionKey: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
||||||
description: Type.Optional(Type.String()),
|
|
||||||
enabled: Type.Optional(Type.Boolean()),
|
|
||||||
deleteAfterRun: Type.Optional(Type.Boolean()),
|
|
||||||
schedule: CronScheduleSchema,
|
schedule: CronScheduleSchema,
|
||||||
sessionTarget: Type.Union([Type.Literal("main"), Type.Literal("isolated")]),
|
sessionTarget: CronSessionTargetSchema,
|
||||||
wakeMode: Type.Union([Type.Literal("next-heartbeat"), Type.Literal("now")]),
|
wakeMode: CronWakeModeSchema,
|
||||||
payload: CronPayloadSchema,
|
payload: CronPayloadSchema,
|
||||||
delivery: Type.Optional(CronDeliverySchema),
|
delivery: Type.Optional(CronDeliverySchema),
|
||||||
},
|
},
|
||||||
@@ -182,14 +207,10 @@ export const CronAddParamsSchema = Type.Object(
|
|||||||
export const CronJobPatchSchema = Type.Object(
|
export const CronJobPatchSchema = Type.Object(
|
||||||
{
|
{
|
||||||
name: Type.Optional(NonEmptyString),
|
name: Type.Optional(NonEmptyString),
|
||||||
agentId: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
...CronCommonOptionalFields,
|
||||||
sessionKey: Type.Optional(Type.Union([NonEmptyString, Type.Null()])),
|
|
||||||
description: Type.Optional(Type.String()),
|
|
||||||
enabled: Type.Optional(Type.Boolean()),
|
|
||||||
deleteAfterRun: Type.Optional(Type.Boolean()),
|
|
||||||
schedule: Type.Optional(CronScheduleSchema),
|
schedule: Type.Optional(CronScheduleSchema),
|
||||||
sessionTarget: Type.Optional(Type.Union([Type.Literal("main"), Type.Literal("isolated")])),
|
sessionTarget: Type.Optional(CronSessionTargetSchema),
|
||||||
wakeMode: Type.Optional(Type.Union([Type.Literal("next-heartbeat"), Type.Literal("now")])),
|
wakeMode: Type.Optional(CronWakeModeSchema),
|
||||||
payload: Type.Optional(CronPayloadPatchSchema),
|
payload: Type.Optional(CronPayloadPatchSchema),
|
||||||
delivery: Type.Optional(CronDeliveryPatchSchema),
|
delivery: Type.Optional(CronDeliveryPatchSchema),
|
||||||
state: Type.Optional(Type.Partial(CronJobStateSchema)),
|
state: Type.Optional(Type.Partial(CronJobStateSchema)),
|
||||||
@@ -197,71 +218,19 @@ export const CronJobPatchSchema = Type.Object(
|
|||||||
{ additionalProperties: false },
|
{ additionalProperties: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
export const CronUpdateParamsSchema = Type.Union([
|
export const CronUpdateParamsSchema = cronIdOrJobIdParams({
|
||||||
Type.Object(
|
patch: CronJobPatchSchema,
|
||||||
{
|
});
|
||||||
id: NonEmptyString,
|
|
||||||
patch: CronJobPatchSchema,
|
|
||||||
},
|
|
||||||
{ additionalProperties: false },
|
|
||||||
),
|
|
||||||
Type.Object(
|
|
||||||
{
|
|
||||||
jobId: NonEmptyString,
|
|
||||||
patch: CronJobPatchSchema,
|
|
||||||
},
|
|
||||||
{ additionalProperties: false },
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const CronRemoveParamsSchema = Type.Union([
|
export const CronRemoveParamsSchema = cronIdOrJobIdParams({});
|
||||||
Type.Object(
|
|
||||||
{
|
|
||||||
id: NonEmptyString,
|
|
||||||
},
|
|
||||||
{ additionalProperties: false },
|
|
||||||
),
|
|
||||||
Type.Object(
|
|
||||||
{
|
|
||||||
jobId: NonEmptyString,
|
|
||||||
},
|
|
||||||
{ additionalProperties: false },
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const CronRunParamsSchema = Type.Union([
|
export const CronRunParamsSchema = cronIdOrJobIdParams({
|
||||||
Type.Object(
|
mode: Type.Optional(Type.Union([Type.Literal("due"), Type.Literal("force")])),
|
||||||
{
|
});
|
||||||
id: NonEmptyString,
|
|
||||||
mode: Type.Optional(Type.Union([Type.Literal("due"), Type.Literal("force")])),
|
|
||||||
},
|
|
||||||
{ additionalProperties: false },
|
|
||||||
),
|
|
||||||
Type.Object(
|
|
||||||
{
|
|
||||||
jobId: NonEmptyString,
|
|
||||||
mode: Type.Optional(Type.Union([Type.Literal("due"), Type.Literal("force")])),
|
|
||||||
},
|
|
||||||
{ additionalProperties: false },
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const CronRunsParamsSchema = Type.Union([
|
export const CronRunsParamsSchema = cronIdOrJobIdParams({
|
||||||
Type.Object(
|
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 5000 })),
|
||||||
{
|
});
|
||||||
id: NonEmptyString,
|
|
||||||
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 5000 })),
|
|
||||||
},
|
|
||||||
{ additionalProperties: false },
|
|
||||||
),
|
|
||||||
Type.Object(
|
|
||||||
{
|
|
||||||
jobId: NonEmptyString,
|
|
||||||
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 5000 })),
|
|
||||||
},
|
|
||||||
{ additionalProperties: false },
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const CronRunLogEntrySchema = Type.Object(
|
export const CronRunLogEntrySchema = Type.Object(
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user