From 58f5fe763f1e20c7f3b3a49879d7136e6fe014a6 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 23:20:56 +0800 Subject: [PATCH] Add cron task management to QLAPI (#2826) * Initial plan * Add cron management capabilities to QLAPI - Added GetCrons, GetCronById, EnableCrons, DisableCrons, RunCrons to proto - Implemented gRPC handlers for new cron operations - Updated client.js to expose new methods to scripts - Updated sample to demonstrate new API usage Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> * Add documentation for QLAPI cron management features Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> * Specify pnpm version 8.3.1 in package.json Add packageManager field to enforce pnpm@8.3.1 as requested Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> * Revert pnpm-lock.yaml to original state The lockfile was inadvertently updated during dependency installation for proto generation. Reverting to maintain consistency with pnpm@8.3.1. Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> * Regenerate proto files with correct tool versions Regenerated using protoc v3.17.3 and protoc-gen-ts_proto v2.6.1 to match the original project configuration. Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> --- QLAPI_CRON_MANAGEMENT.md | 198 ++++++++++++++++ back/protos/api.proto | 17 ++ back/protos/api.ts | 471 +++++++++++++++++++++++++++++++++++++++ back/schedule/api.ts | 119 ++++++++++ package.json | 1 + sample/ql_sample.js | 28 +++ shell/preload/client.js | 5 + 7 files changed, 839 insertions(+) create mode 100644 QLAPI_CRON_MANAGEMENT.md diff --git a/QLAPI_CRON_MANAGEMENT.md b/QLAPI_CRON_MANAGEMENT.md new file mode 100644 index 00000000..19111336 --- /dev/null +++ b/QLAPI_CRON_MANAGEMENT.md @@ -0,0 +1,198 @@ +# QLAPI Cron Management Features + +## Overview + +This document describes the new cron task management capabilities added to the QLAPI (Qinglong API). These features allow scripts to interact with scheduled tasks (cron jobs) programmatically. + +## New API Methods + +### 1. getCrons - Query Cron Tasks + +Query and search for cron tasks. + +```javascript +// Get all cron tasks +QLAPI.getCrons({}).then((response) => { + console.log('All cron tasks:', response); + // response.code: 200 for success + // response.data: array of cron items +}); + +// Search for specific cron tasks +QLAPI.getCrons({ searchValue: 'test' }).then((response) => { + console.log('Search results:', response); + // Returns cron tasks matching the search term +}); +``` + +**Parameters:** +- `searchValue` (optional): String to search for in task names, commands, schedules, or labels + +**Response:** +- `code`: 200 for success, 500 for error +- `data`: Array of cron items with properties: + - `id`: Task ID + - `name`: Task name + - `command`: Command to execute + - `schedule`: Cron schedule expression + - `status`: Task status (0=idle, 1=running, 2=queued) + - `isDisabled`: 0=enabled, 1=disabled + - `labels`: Array of labels + - `task_before`: Script to run before task + - `task_after`: Script to run after task + - Other metadata fields + +### 2. getCronById - Get Cron Task by ID + +Retrieve a specific cron task by its ID. + +```javascript +QLAPI.getCronById({ id: 1 }).then((response) => { + console.log('Cron task:', response); + // response.code: 200 for success, 404 if not found + // response.data: cron item details +}).catch((err) => { + console.log('Error:', err); +}); +``` + +**Parameters:** +- `id` (required): The task ID + +**Response:** +- `code`: 200 for success, 400 for invalid parameters, 404 if not found +- `data`: Cron item with full details + +### 3. enableCrons - Enable Cron Tasks + +Enable one or more cron tasks by their IDs. + +```javascript +// Enable a single task +QLAPI.enableCrons({ ids: [1] }).then((response) => { + console.log('Task enabled:', response); +}); + +// Enable multiple tasks +QLAPI.enableCrons({ ids: [1, 2, 3] }).then((response) => { + console.log('Tasks enabled:', response); +}); +``` + +**Parameters:** +- `ids` (required): Array of task IDs to enable + +**Response:** +- `code`: 200 for success, 400 for invalid parameters + +### 4. disableCrons - Disable Cron Tasks + +Disable one or more cron tasks by their IDs. + +```javascript +// Disable a single task +QLAPI.disableCrons({ ids: [1] }).then((response) => { + console.log('Task disabled:', response); +}); + +// Disable multiple tasks +QLAPI.disableCrons({ ids: [1, 2, 3] }).then((response) => { + console.log('Tasks disabled:', response); +}); +``` + +**Parameters:** +- `ids` (required): Array of task IDs to disable + +**Response:** +- `code`: 200 for success, 400 for invalid parameters + +### 5. runCrons - Manually Execute Cron Tasks + +Manually trigger execution of one or more cron tasks. + +```javascript +// Run a single task +QLAPI.runCrons({ ids: [1] }).then((response) => { + console.log('Task started:', response); +}); + +// Run multiple tasks +QLAPI.runCrons({ ids: [1, 2, 3] }).then((response) => { + console.log('Tasks started:', response); +}); +``` + +**Parameters:** +- `ids` (required): Array of task IDs to run + +**Response:** +- `code`: 200 for success, 400 for invalid parameters + +## Use Cases + +### Task Coordination + +Execute tasks in sequence or based on conditions: + +```javascript +// Run task 2 after task 1 completes +QLAPI.runCrons({ ids: [1] }).then(() => { + console.log('Task 1 started'); + // You might want to poll or wait for task 1 to complete + // before running task 2 +}); +``` + +### Conditional Task Management + +Enable or disable tasks based on certain conditions: + +```javascript +// Get all tasks and conditionally enable/disable them +QLAPI.getCrons({}).then((response) => { + const tasks = response.data; + + tasks.forEach(task => { + if (task.name.includes('special')) { + // Enable special tasks + QLAPI.enableCrons({ ids: [task.id] }); + } else { + // Disable other tasks + QLAPI.disableCrons({ ids: [task.id] }); + } + }); +}); +``` + +### Task Status Monitoring + +Query task status to determine what actions to take: + +```javascript +QLAPI.getCronById({ id: 1 }).then((response) => { + const task = response.data; + + console.log('Task name:', task.name); + console.log('Is enabled:', task.isDisabled === 0); + console.log('Current status:', task.status === 0 ? 'idle' : + task.status === 1 ? 'running' : 'queued'); + + // Take action based on status + if (task.status === 0 && task.isDisabled === 0) { + console.log('Task is idle and enabled, ready to run'); + } +}); +``` + +## Complete Example + +See `sample/ql_sample.js` for a complete working example of all the new features. + +## Notes + +- All methods return Promises +- Task IDs are numeric integers +- Task status values: 0 (idle), 1 (running), 2 (queued) +- Disabled status: isDisabled = 0 (enabled), isDisabled = 1 (disabled) +- When searching with `getCrons`, the search applies to name, command, schedule, and labels diff --git a/back/protos/api.proto b/back/protos/api.proto index a4541884..cb658829 100644 --- a/back/protos/api.proto +++ b/back/protos/api.proto @@ -97,6 +97,18 @@ message UpdateCronRequest { message DeleteCronsRequest { repeated int32 ids = 1; } +message GetCronsRequest { + optional string searchValue = 1; +} + +message GetCronByIdRequest { int32 id = 1; } + +message EnableCronsRequest { repeated int32 ids = 1; } + +message DisableCronsRequest { repeated int32 ids = 1; } + +message RunCronsRequest { repeated int32 ids = 1; } + message CronsResponse { int32 code = 1; repeated CronItem data = 2; @@ -254,4 +266,9 @@ service Api { rpc CreateCron(CreateCronRequest) returns (CronResponse) {} rpc UpdateCron(UpdateCronRequest) returns (CronResponse) {} rpc DeleteCrons(DeleteCronsRequest) returns (Response) {} + rpc GetCrons(GetCronsRequest) returns (CronsResponse) {} + rpc GetCronById(GetCronByIdRequest) returns (CronResponse) {} + rpc EnableCrons(EnableCronsRequest) returns (Response) {} + rpc DisableCrons(DisableCronsRequest) returns (Response) {} + rpc RunCrons(RunCronsRequest) returns (Response) {} } \ No newline at end of file diff --git a/back/protos/api.ts b/back/protos/api.ts index 9a7fb443..967f7520 100644 --- a/back/protos/api.ts +++ b/back/protos/api.ts @@ -281,6 +281,26 @@ export interface DeleteCronsRequest { ids: number[]; } +export interface GetCronsRequest { + searchValue?: string | undefined; +} + +export interface GetCronByIdRequest { + id: number; +} + +export interface EnableCronsRequest { + ids: number[]; +} + +export interface DisableCronsRequest { + ids: number[]; +} + +export interface RunCronsRequest { + ids: number[]; +} + export interface CronsResponse { code: number; data: CronItem[]; @@ -2207,6 +2227,332 @@ export const DeleteCronsRequest: MessageFns = { }, }; +function createBaseGetCronsRequest(): GetCronsRequest { + return { searchValue: undefined }; +} + +export const GetCronsRequest: MessageFns = { + encode(message: GetCronsRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.searchValue !== undefined) { + writer.uint32(10).string(message.searchValue); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GetCronsRequest { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGetCronsRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.searchValue = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GetCronsRequest { + return { searchValue: isSet(object.searchValue) ? globalThis.String(object.searchValue) : undefined }; + }, + + toJSON(message: GetCronsRequest): unknown { + const obj: any = {}; + if (message.searchValue !== undefined) { + obj.searchValue = message.searchValue; + } + return obj; + }, + + create, I>>(base?: I): GetCronsRequest { + return GetCronsRequest.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): GetCronsRequest { + const message = createBaseGetCronsRequest(); + message.searchValue = object.searchValue ?? undefined; + return message; + }, +}; + +function createBaseGetCronByIdRequest(): GetCronByIdRequest { + return { id: 0 }; +} + +export const GetCronByIdRequest: MessageFns = { + encode(message: GetCronByIdRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.id !== 0) { + writer.uint32(8).int32(message.id); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GetCronByIdRequest { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGetCronByIdRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } + + message.id = reader.int32(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GetCronByIdRequest { + return { id: isSet(object.id) ? globalThis.Number(object.id) : 0 }; + }, + + toJSON(message: GetCronByIdRequest): unknown { + const obj: any = {}; + if (message.id !== 0) { + obj.id = Math.round(message.id); + } + return obj; + }, + + create, I>>(base?: I): GetCronByIdRequest { + return GetCronByIdRequest.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): GetCronByIdRequest { + const message = createBaseGetCronByIdRequest(); + message.id = object.id ?? 0; + return message; + }, +}; + +function createBaseEnableCronsRequest(): EnableCronsRequest { + return { ids: [] }; +} + +export const EnableCronsRequest: MessageFns = { + encode(message: EnableCronsRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + writer.uint32(10).fork(); + for (const v of message.ids) { + writer.int32(v); + } + writer.join(); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): EnableCronsRequest { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseEnableCronsRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag === 8) { + message.ids.push(reader.int32()); + + continue; + } + + if (tag === 10) { + const end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) { + message.ids.push(reader.int32()); + } + + continue; + } + + break; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): EnableCronsRequest { + return { ids: globalThis.Array.isArray(object?.ids) ? object.ids.map((e: any) => globalThis.Number(e)) : [] }; + }, + + toJSON(message: EnableCronsRequest): unknown { + const obj: any = {}; + if (message.ids?.length) { + obj.ids = message.ids.map((e) => Math.round(e)); + } + return obj; + }, + + create, I>>(base?: I): EnableCronsRequest { + return EnableCronsRequest.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): EnableCronsRequest { + const message = createBaseEnableCronsRequest(); + message.ids = object.ids?.map((e) => e) || []; + return message; + }, +}; + +function createBaseDisableCronsRequest(): DisableCronsRequest { + return { ids: [] }; +} + +export const DisableCronsRequest: MessageFns = { + encode(message: DisableCronsRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + writer.uint32(10).fork(); + for (const v of message.ids) { + writer.int32(v); + } + writer.join(); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): DisableCronsRequest { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseDisableCronsRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag === 8) { + message.ids.push(reader.int32()); + + continue; + } + + if (tag === 10) { + const end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) { + message.ids.push(reader.int32()); + } + + continue; + } + + break; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): DisableCronsRequest { + return { ids: globalThis.Array.isArray(object?.ids) ? object.ids.map((e: any) => globalThis.Number(e)) : [] }; + }, + + toJSON(message: DisableCronsRequest): unknown { + const obj: any = {}; + if (message.ids?.length) { + obj.ids = message.ids.map((e) => Math.round(e)); + } + return obj; + }, + + create, I>>(base?: I): DisableCronsRequest { + return DisableCronsRequest.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): DisableCronsRequest { + const message = createBaseDisableCronsRequest(); + message.ids = object.ids?.map((e) => e) || []; + return message; + }, +}; + +function createBaseRunCronsRequest(): RunCronsRequest { + return { ids: [] }; +} + +export const RunCronsRequest: MessageFns = { + encode(message: RunCronsRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + writer.uint32(10).fork(); + for (const v of message.ids) { + writer.int32(v); + } + writer.join(); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): RunCronsRequest { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseRunCronsRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag === 8) { + message.ids.push(reader.int32()); + + continue; + } + + if (tag === 10) { + const end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) { + message.ids.push(reader.int32()); + } + + continue; + } + + break; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): RunCronsRequest { + return { ids: globalThis.Array.isArray(object?.ids) ? object.ids.map((e: any) => globalThis.Number(e)) : [] }; + }, + + toJSON(message: RunCronsRequest): unknown { + const obj: any = {}; + if (message.ids?.length) { + obj.ids = message.ids.map((e) => Math.round(e)); + } + return obj; + }, + + create, I>>(base?: I): RunCronsRequest { + return RunCronsRequest.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): RunCronsRequest { + const message = createBaseRunCronsRequest(); + message.ids = object.ids?.map((e) => e) || []; + return message; + }, +}; + function createBaseCronsResponse(): CronsResponse { return { code: 0, data: [], message: undefined }; } @@ -3976,6 +4322,51 @@ export const ApiService = { responseSerialize: (value: Response) => Buffer.from(Response.encode(value).finish()), responseDeserialize: (value: Buffer) => Response.decode(value), }, + getCrons: { + path: "/com.ql.api.Api/GetCrons", + requestStream: false, + responseStream: false, + requestSerialize: (value: GetCronsRequest) => Buffer.from(GetCronsRequest.encode(value).finish()), + requestDeserialize: (value: Buffer) => GetCronsRequest.decode(value), + responseSerialize: (value: CronsResponse) => Buffer.from(CronsResponse.encode(value).finish()), + responseDeserialize: (value: Buffer) => CronsResponse.decode(value), + }, + getCronById: { + path: "/com.ql.api.Api/GetCronById", + requestStream: false, + responseStream: false, + requestSerialize: (value: GetCronByIdRequest) => Buffer.from(GetCronByIdRequest.encode(value).finish()), + requestDeserialize: (value: Buffer) => GetCronByIdRequest.decode(value), + responseSerialize: (value: CronResponse) => Buffer.from(CronResponse.encode(value).finish()), + responseDeserialize: (value: Buffer) => CronResponse.decode(value), + }, + enableCrons: { + path: "/com.ql.api.Api/EnableCrons", + requestStream: false, + responseStream: false, + requestSerialize: (value: EnableCronsRequest) => Buffer.from(EnableCronsRequest.encode(value).finish()), + requestDeserialize: (value: Buffer) => EnableCronsRequest.decode(value), + responseSerialize: (value: Response) => Buffer.from(Response.encode(value).finish()), + responseDeserialize: (value: Buffer) => Response.decode(value), + }, + disableCrons: { + path: "/com.ql.api.Api/DisableCrons", + requestStream: false, + responseStream: false, + requestSerialize: (value: DisableCronsRequest) => Buffer.from(DisableCronsRequest.encode(value).finish()), + requestDeserialize: (value: Buffer) => DisableCronsRequest.decode(value), + responseSerialize: (value: Response) => Buffer.from(Response.encode(value).finish()), + responseDeserialize: (value: Buffer) => Response.decode(value), + }, + runCrons: { + path: "/com.ql.api.Api/RunCrons", + requestStream: false, + responseStream: false, + requestSerialize: (value: RunCronsRequest) => Buffer.from(RunCronsRequest.encode(value).finish()), + requestDeserialize: (value: Buffer) => RunCronsRequest.decode(value), + responseSerialize: (value: Response) => Buffer.from(Response.encode(value).finish()), + responseDeserialize: (value: Buffer) => Response.decode(value), + }, } as const; export interface ApiServer extends UntypedServiceImplementation { @@ -3993,6 +4384,11 @@ export interface ApiServer extends UntypedServiceImplementation { createCron: handleUnaryCall; updateCron: handleUnaryCall; deleteCrons: handleUnaryCall; + getCrons: handleUnaryCall; + getCronById: handleUnaryCall; + enableCrons: handleUnaryCall; + disableCrons: handleUnaryCall; + runCrons: handleUnaryCall; } export interface ApiClient extends Client { @@ -4206,6 +4602,81 @@ export interface ApiClient extends Client { options: Partial, callback: (error: ServiceError | null, response: Response) => void, ): ClientUnaryCall; + getCrons( + request: GetCronsRequest, + callback: (error: ServiceError | null, response: CronsResponse) => void, + ): ClientUnaryCall; + getCrons( + request: GetCronsRequest, + metadata: Metadata, + callback: (error: ServiceError | null, response: CronsResponse) => void, + ): ClientUnaryCall; + getCrons( + request: GetCronsRequest, + metadata: Metadata, + options: Partial, + callback: (error: ServiceError | null, response: CronsResponse) => void, + ): ClientUnaryCall; + getCronById( + request: GetCronByIdRequest, + callback: (error: ServiceError | null, response: CronResponse) => void, + ): ClientUnaryCall; + getCronById( + request: GetCronByIdRequest, + metadata: Metadata, + callback: (error: ServiceError | null, response: CronResponse) => void, + ): ClientUnaryCall; + getCronById( + request: GetCronByIdRequest, + metadata: Metadata, + options: Partial, + callback: (error: ServiceError | null, response: CronResponse) => void, + ): ClientUnaryCall; + enableCrons( + request: EnableCronsRequest, + callback: (error: ServiceError | null, response: Response) => void, + ): ClientUnaryCall; + enableCrons( + request: EnableCronsRequest, + metadata: Metadata, + callback: (error: ServiceError | null, response: Response) => void, + ): ClientUnaryCall; + enableCrons( + request: EnableCronsRequest, + metadata: Metadata, + options: Partial, + callback: (error: ServiceError | null, response: Response) => void, + ): ClientUnaryCall; + disableCrons( + request: DisableCronsRequest, + callback: (error: ServiceError | null, response: Response) => void, + ): ClientUnaryCall; + disableCrons( + request: DisableCronsRequest, + metadata: Metadata, + callback: (error: ServiceError | null, response: Response) => void, + ): ClientUnaryCall; + disableCrons( + request: DisableCronsRequest, + metadata: Metadata, + options: Partial, + callback: (error: ServiceError | null, response: Response) => void, + ): ClientUnaryCall; + runCrons( + request: RunCronsRequest, + callback: (error: ServiceError | null, response: Response) => void, + ): ClientUnaryCall; + runCrons( + request: RunCronsRequest, + metadata: Metadata, + callback: (error: ServiceError | null, response: Response) => void, + ): ClientUnaryCall; + runCrons( + request: RunCronsRequest, + metadata: Metadata, + options: Partial, + callback: (error: ServiceError | null, response: Response) => void, + ): ClientUnaryCall; } export const ApiClient = makeGenericClientConstructor(ApiService, "com.ql.api.Api") as unknown as { diff --git a/back/schedule/api.ts b/back/schedule/api.ts index dd80e44c..5bcc7b1f 100644 --- a/back/schedule/api.ts +++ b/back/schedule/api.ts @@ -30,6 +30,12 @@ import { UpdateCronRequest, DeleteCronsRequest, CronResponse, + GetCronsRequest, + CronsResponse, + GetCronByIdRequest, + EnableCronsRequest, + DisableCronsRequest, + RunCronsRequest, } from '../protos/api'; import { NotificationInfo } from '../data/notify'; @@ -323,3 +329,116 @@ export const deleteCrons = async ( callback(e); } }; + +export const getCrons = async ( + call: ServerUnaryCall, + callback: sendUnaryData, +) => { + try { + const cronService = Container.get(CronService); + const result = await cronService.crontabs({ + searchValue: call.request.searchValue || '', + page: '0', + size: '0', + sorter: '', + filters: '', + queryString: '', + }); + const data = result.data.map((x) => normalizeCronData(x as CronItem)); + callback(null, { + code: 200, + data: data.filter((x): x is CronItem => x !== undefined), + }); + } catch (e: any) { + callback(null, { + code: 500, + data: [], + message: e.message, + }); + } +}; + +export const getCronById = async ( + call: ServerUnaryCall, + callback: sendUnaryData, +) => { + try { + if (!call.request.id) { + return callback(null, { + code: 400, + data: undefined, + message: 'id parameter is required', + }); + } + + const cronService = Container.get(CronService); + const data = (await cronService.getDb({ id: call.request.id })) as CronItem; + callback(null, { code: 200, data: normalizeCronData(data) }); + } catch (e: any) { + callback(null, { + code: 404, + data: undefined, + message: e.message, + }); + } +}; + +export const enableCrons = async ( + call: ServerUnaryCall, + callback: sendUnaryData, +) => { + try { + if (!call.request.ids || call.request.ids.length === 0) { + return callback(null, { + code: 400, + message: 'ids parameter is required', + }); + } + + const cronService = Container.get(CronService); + await cronService.enabled(call.request.ids); + callback(null, { code: 200 }); + } catch (e: any) { + callback(e); + } +}; + +export const disableCrons = async ( + call: ServerUnaryCall, + callback: sendUnaryData, +) => { + try { + if (!call.request.ids || call.request.ids.length === 0) { + return callback(null, { + code: 400, + message: 'ids parameter is required', + }); + } + + const cronService = Container.get(CronService); + await cronService.disabled(call.request.ids); + callback(null, { code: 200 }); + } catch (e: any) { + callback(e); + } +}; + +export const runCrons = async ( + call: ServerUnaryCall, + callback: sendUnaryData, +) => { + try { + if (!call.request.ids || call.request.ids.length === 0) { + return callback(null, { + code: 400, + message: 'ids parameter is required', + }); + } + + const cronService = Container.get(CronService); + await cronService.run(call.request.ids); + callback(null, { code: 200 }); + } catch (e: any) { + callback(e); + } +}; diff --git a/package.json b/package.json index ab349946..038f8c1d 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "private": true, + "packageManager": "pnpm@8.3.1", "scripts": { "start": "concurrently -n w: npm:start:*", "start:back": "nodemon ./back/app.ts", diff --git a/sample/ql_sample.js b/sample/ql_sample.js index 4d64568e..7f5b6863 100644 --- a/sample/ql_sample.js +++ b/sample/ql_sample.js @@ -12,4 +12,32 @@ QLAPI.getEnvs({ searchValue: 'dddd' }).then((x) => { QLAPI.systemNotify({ title: '123', content: '231' }).then((x) => { console.log('systemNotify', x); }); + +// 查询定时任务 (Query cron tasks) +QLAPI.getCrons({ searchValue: 'test' }).then((x) => { + console.log('getCrons', x); +}); + +// 通过ID查询定时任务 (Get cron by ID) +QLAPI.getCronById({ id: 1 }).then((x) => { + console.log('getCronById', x); +}).catch((err) => { + console.log('getCronById error', err); +}); + +// 启用定时任务 (Enable cron tasks) +QLAPI.enableCrons({ ids: [1, 2] }).then((x) => { + console.log('enableCrons', x); +}); + +// 禁用定时任务 (Disable cron tasks) +QLAPI.disableCrons({ ids: [1, 2] }).then((x) => { + console.log('disableCrons', x); +}); + +// 手动执行定时任务 (Run cron tasks manually) +QLAPI.runCrons({ ids: [1] }).then((x) => { + console.log('runCrons', x); +}); + console.log('test desc'); diff --git a/shell/preload/client.js b/shell/preload/client.js index 51475311..3d9c4fb2 100644 --- a/shell/preload/client.js +++ b/shell/preload/client.js @@ -33,6 +33,11 @@ class GrpcClient { 'createCron', 'updateCron', 'deleteCrons', + 'getCrons', + 'getCronById', + 'enableCrons', + 'disableCrons', + 'runCrons', ]; #client;