diff --git a/back/protos/api.proto b/back/protos/api.proto index 77d35ee9..fc9ac829 100644 --- a/back/protos/api.proto +++ b/back/protos/api.proto @@ -92,8 +92,8 @@ message CreateCronRequest { message UpdateCronRequest { int32 id = 1; - string command = 2; - string schedule = 3; + optional string command = 2; + optional string schedule = 3; optional string name = 4; repeated string labels = 5; optional int32 sub_id = 6; diff --git a/back/protos/api.ts b/back/protos/api.ts index 558cb693..b20c1956 100644 --- a/back/protos/api.ts +++ b/back/protos/api.ts @@ -125,8 +125,8 @@ export interface CreateCronRequest { export interface UpdateCronRequest { id: number; - command: string; - schedule: string; + command?: string | undefined; + schedule?: string | undefined; name?: string | undefined; labels: string[]; sub_id?: number | undefined; @@ -1797,8 +1797,8 @@ export const CreateCronRequest: MessageFns = { function createBaseUpdateCronRequest(): UpdateCronRequest { return { id: 0, - command: "", - schedule: "", + command: undefined, + schedule: undefined, name: undefined, labels: [], sub_id: undefined, @@ -1813,10 +1813,10 @@ export const UpdateCronRequest: MessageFns = { if (message.id !== 0) { writer.uint32(8).int32(message.id); } - if (message.command !== "") { + if (message.command !== undefined) { writer.uint32(18).string(message.command); } - if (message.schedule !== "") { + if (message.schedule !== undefined) { writer.uint32(26).string(message.schedule); } if (message.name !== undefined) { @@ -1931,8 +1931,8 @@ export const UpdateCronRequest: MessageFns = { fromJSON(object: any): UpdateCronRequest { return { id: isSet(object.id) ? globalThis.Number(object.id) : 0, - command: isSet(object.command) ? globalThis.String(object.command) : "", - schedule: isSet(object.schedule) ? globalThis.String(object.schedule) : "", + command: isSet(object.command) ? globalThis.String(object.command) : undefined, + schedule: isSet(object.schedule) ? globalThis.String(object.schedule) : undefined, name: isSet(object.name) ? globalThis.String(object.name) : undefined, labels: globalThis.Array.isArray(object?.labels) ? object.labels.map((e: any) => globalThis.String(e)) : [], sub_id: isSet(object.sub_id) ? globalThis.Number(object.sub_id) : undefined, @@ -1949,10 +1949,10 @@ export const UpdateCronRequest: MessageFns = { if (message.id !== 0) { obj.id = Math.round(message.id); } - if (message.command !== "") { + if (message.command !== undefined) { obj.command = message.command; } - if (message.schedule !== "") { + if (message.schedule !== undefined) { obj.schedule = message.schedule; } if (message.name !== undefined) { @@ -1982,8 +1982,8 @@ export const UpdateCronRequest: MessageFns = { fromPartial, I>>(object: I): UpdateCronRequest { const message = createBaseUpdateCronRequest(); message.id = object.id ?? 0; - message.command = object.command ?? ""; - message.schedule = object.schedule ?? ""; + message.command = object.command ?? undefined; + message.schedule = object.schedule ?? undefined; message.name = object.name ?? undefined; message.labels = object.labels?.map((e) => e) || []; message.sub_id = object.sub_id ?? undefined; diff --git a/back/schedule/api.ts b/back/schedule/api.ts index be301543..09adec08 100644 --- a/back/schedule/api.ts +++ b/back/schedule/api.ts @@ -39,6 +39,13 @@ export const getEnvs = async ( callback: sendUnaryData, ) => { try { + if (!call.request.searchValue) { + return callback(null, { + code: 400, + data: [], + message: 'searchValue is required', + }); + } const envService = Container.get(EnvService); const data = await envService.envs(call.request.searchValue); callback(null, { @@ -182,17 +189,35 @@ export const systemNotify = async ( } }; +const normalizeCronData = (data: CronItem | null): CronItem | undefined => { + if (!data) return undefined; + return { + ...data, + sub_id: data.sub_id ?? undefined, + extra_schedules: data.extra_schedules ?? undefined, + pid: data.pid ?? undefined, + task_before: data.task_before ?? undefined, + task_after: data.task_after ?? undefined, + }; +}; + export const getCronDetail = async ( call: ServerUnaryCall, callback: sendUnaryData, ) => { try { + if (!call.request.log_path) { + return callback(null, { + code: 400, + data: undefined, + message: 'log_path is required', + }); + } const cronService = Container.get(CronService); const data = (await cronService.find({ log_path: call.request.log_path, })) as CronItem; - console.log('data', data); - callback(null, { code: 200, data: data || undefined }); + callback(null, { code: 200, data: normalizeCronData(data) }); } catch (e: any) { callback(e); } @@ -205,7 +230,7 @@ export const createCron = async ( try { const cronService = Container.get(CronService); const data = (await cronService.create(call.request)) as CronItem; - callback(null, { code: 200, data }); + callback(null, { code: 200, data: normalizeCronData(data) }); } catch (e: any) { callback(e); } @@ -217,8 +242,20 @@ export const updateCron = async ( ) => { try { const cronService = Container.get(CronService); - const data = (await cronService.update(call.request)) as CronItem; - callback(null, { code: 200, data }); + const { id, ...fields } = call.request; + + const updateRequest = { + id, + ...Object.entries(fields).reduce((acc: any, [key, value]) => { + if (value !== undefined) { + acc[key] = value; + } + return acc; + }, {}), + } as UpdateCronRequest; + + const data = (await cronService.update(updateRequest)) as CronItem; + callback(null, { code: 200, data: normalizeCronData(data) }); } catch (e: any) { callback(e); } diff --git a/back/services/cron.ts b/back/services/cron.ts index 299d691c..add8f1df 100644 --- a/back/services/cron.ts +++ b/back/services/cron.ts @@ -58,7 +58,7 @@ export default class CronService { return await CrontabModel.create(payload, { returning: true }); } - public async update(payload: Crontab): Promise { + public async update(payload: Partial): Promise { const doc = await this.getDb({ id: payload.id }); const tab = new Crontab({ ...doc, ...payload }); tab.saved = false; diff --git a/shell/preload/client.js b/shell/preload/client.js index 6ca48a4e..bd154b71 100644 --- a/shell/preload/client.js +++ b/shell/preload/client.js @@ -35,7 +35,7 @@ class GrpcClient { 'getCronDetail', 'createCron', 'updateCron', - 'deleteCrons' + 'deleteCrons', ]; #client; @@ -79,7 +79,7 @@ class GrpcClient { #promisifyMethod(methodName) { const capitalizedMethod = methodName.charAt(0).toUpperCase() + methodName.slice(1); - const grpcMethod = this.#client[capitalizedMethod].bind(this.#client); + const method = this.#client[capitalizedMethod].bind(this.#client); return async (params = {}) => { return new Promise((resolve, reject) => { @@ -88,7 +88,7 @@ class GrpcClient { Date.now() + GrpcClient.#config.defaultTimeout, ); - grpcMethod(params, metadata, { deadline }, (error, response) => { + method(params, metadata, { deadline }, (error, response) => { if (error) { return reject(error); } @@ -131,4 +131,24 @@ process.on('SIGINT', () => { process.exit(0); }); +process.on('unhandledRejection', (reason, promise) => { + if (reason instanceof Error) { + if (reason.stack) { + const relevantStack = reason.stack + .split('\n') + .filter((line) => { + return ( + !line.includes('node:internal') && + !line.includes('node_modules/@grpc') && + !line.includes('processTicksAndRejections') + ); + }) + .join('\n'); + console.error(relevantStack); + } + } else { + console.error(reason); + } +}); + module.exports = grpcClient.getApi(); diff --git a/shell/preload/client.py b/shell/preload/client.py index ebdf3619..07bad008 100644 --- a/shell/preload/client.py +++ b/shell/preload/client.py @@ -29,14 +29,14 @@ def error_handler(func): f'"{k}": {v.__name__}' for k, v in required_fields.items() ) raise Exception( - f"unknown error: {func_name}() requires a dictionary with parameters: {{{fields_str}}}" + f"{func_name}() requires a dictionary with parameters: {{{fields_str}}}" ) from None - raise Exception(f"unknown error: {str(e)}") from None + raise Exception(f"{str(e)}") from None except Exception as e: error_msg = str(e) if "Error:" in error_msg: error_msg = error_msg.split("Error:")[-1].split("\n")[0].strip() - raise Exception(f"unknown error: {error_msg}") from None + raise Exception(f"{error_msg}") from None return wrapper