From dd90ed50d51f17ce8f21c2884db2c096bdd2e1a4 Mon Sep 17 00:00:00 2001 From: Roman Nikitenko Date: Tue, 8 Oct 2019 19:20:18 +0300 Subject: [PATCH] Change way of storage runtime info for che tasks Signed-off-by: Roman Nikitenko --- .../src/browser/che-task-client.ts | 55 ++++------------ .../src/browser/che-task-main.ts | 7 +- .../src/common/che-protocol.ts | 18 ++--- .../src/node/che-task-service.ts | 66 ++++++++----------- .../src/plugin/che-task-impl.ts | 34 +++------- .../src/che-proposed.d.ts | 11 +--- .../task-plugin/src/task/che-task-runner.ts | 21 +++--- 7 files changed, 70 insertions(+), 142 deletions(-) diff --git a/extensions/eclipse-che-theia-plugin-ext/src/browser/che-task-client.ts b/extensions/eclipse-che-theia-plugin-ext/src/browser/che-task-client.ts index 0433669de..495e6deb3 100644 --- a/extensions/eclipse-che-theia-plugin-ext/src/browser/che-task-client.ts +++ b/extensions/eclipse-che-theia-plugin-ext/src/browser/che-task-client.ts @@ -14,63 +14,32 @@ import { TaskConfiguration, TaskInfo } from '@eclipse-che/plugin'; @injectable() export class CheTaskClientImpl implements CheTaskClient { - private readonly onKillEventEmitter: Emitter; - private taskInfoHandlers: ((id: number) => Promise)[] = []; - private runTaskHandlers: ((id: number, config: TaskConfiguration, ctx?: string) => Promise)[] = []; - private taskExitedHandlers: ((id: number) => Promise)[] = []; + private readonly onKillEventEmitter: Emitter; + private runTaskHandlers: ((config: TaskConfiguration, ctx?: string) => Promise)[] = []; constructor() { - this.onKillEventEmitter = new Emitter(); + this.onKillEventEmitter = new Emitter(); } - async runTask(id: number, taskConfig: TaskConfiguration, ctx?: string): Promise { + async runTask(taskConfig: TaskConfiguration, ctx?: string): Promise { for (const runTaskHandler of this.runTaskHandlers) { - await runTaskHandler(id, taskConfig, ctx); - } - return undefined; - } - - async getTaskInfo(id: number): Promise { - for (const taskInfoHandler of this.taskInfoHandlers) { - try { - const taskInfo = await taskInfoHandler(id); - if (taskInfo) { - return taskInfo; - } - } catch (e) { - // allow another handlers to handle request + const taskInfo = await runTaskHandler(taskConfig, ctx); + if (taskInfo) { + return taskInfo; } } - return undefined; + throw new Error(`Failed to process configuration with label ${taskConfig.label} by Che Task Handler`); } - async onTaskExited(id: number): Promise { - for (const taskExitedHandler of this.taskExitedHandlers) { - try { - await taskExitedHandler(id); - } catch (e) { - // allow another handlers to handle request - } - } - } - - get onKillEvent(): Event { + get onKillEvent(): Event { return this.onKillEventEmitter.event; } - async killTask(id: number): Promise { - this.onKillEventEmitter.fire(id); - } - - addTaskInfoHandler(handler: (id: number) => Promise) { - this.taskInfoHandlers.push(handler); + async killTask(taskInfo: TaskInfo): Promise { + this.onKillEventEmitter.fire(taskInfo); } - addRunTaskHandler(handler: (id: number, config: TaskConfiguration, ctx?: string) => Promise) { + addRunTaskHandler(handler: (config: TaskConfiguration, ctx?: string) => Promise) { this.runTaskHandlers.push(handler); } - - addTaskExitedHandler(handler: (id: number) => Promise) { - this.taskExitedHandlers.push(handler); - } } diff --git a/extensions/eclipse-che-theia-plugin-ext/src/browser/che-task-main.ts b/extensions/eclipse-che-theia-plugin-ext/src/browser/che-task-main.ts index a9ab2b0e4..a0cce7037 100644 --- a/extensions/eclipse-che-theia-plugin-ext/src/browser/che-task-main.ts +++ b/extensions/eclipse-che-theia-plugin-ext/src/browser/che-task-main.ts @@ -20,11 +20,10 @@ export class CheTaskMainImpl implements CheTaskMain { const proxy: CheTask = rpc.getProxy(PLUGIN_RPC_CONTEXT.CHE_TASK); this.delegate = container.get(CheTaskService); this.cheTaskClient = container.get(CheTaskClient); - this.cheTaskClient.onKillEvent(id => proxy.$killTask(id)); - this.cheTaskClient.addTaskInfoHandler(id => proxy.$getTaskInfo(id)); - this.cheTaskClient.addTaskExitedHandler(id => proxy.$onTaskExited(id)); - this.cheTaskClient.addRunTaskHandler((id, config, ctx) => proxy.$runTask(id, config, ctx)); + this.cheTaskClient.onKillEvent(taskInfo => proxy.$killTask(taskInfo)); + this.cheTaskClient.addRunTaskHandler((config, ctx) => proxy.$runTask(config, ctx)); } + $registerTaskRunner(type: string): Promise { return this.delegate.registerTaskRunner(type); } diff --git a/extensions/eclipse-che-theia-plugin-ext/src/common/che-protocol.ts b/extensions/eclipse-che-theia-plugin-ext/src/common/che-protocol.ts index d69c0949e..34982cf6b 100644 --- a/extensions/eclipse-che-theia-plugin-ext/src/common/che-protocol.ts +++ b/extensions/eclipse-che-theia-plugin-ext/src/common/che-protocol.ts @@ -76,10 +76,8 @@ export interface CheVariablesMain { export interface CheTask { registerTaskRunner(type: string, runner: che.TaskRunner): Promise; fireTaskExited(event: che.TaskExitedEvent): Promise; - $runTask(id: number, config: che.TaskConfiguration, ctx?: string): Promise; - $onTaskExited(id: number): Promise; - $killTask(id: number): Promise; - $getTaskInfo(id: number): Promise; + $runTask(config: che.TaskConfiguration, ctx?: string): Promise; + $killTask(taskInfo: che.TaskInfo): Promise; } export const CheTaskMain = Symbol('CheTaskMain'); @@ -419,14 +417,10 @@ export interface CheTaskService extends JsonRpcServer { export const CheTaskClient = Symbol('CheTaskClient'); export interface CheTaskClient { - runTask(id: number, taskConfig: che.TaskConfiguration, ctx?: string): Promise; - killTask(id: number): Promise; - getTaskInfo(id: number): Promise; - onTaskExited(id: number): Promise; - addTaskInfoHandler(func: (id: number) => Promise): void; - addRunTaskHandler(func: (id: number, config: che.TaskConfiguration, ctx?: string) => Promise): void; - addTaskExitedHandler(func: (id: number) => Promise): void; - onKillEvent: Event + runTask(taskConfig: che.TaskConfiguration, ctx?: string): Promise; + killTask(taskInfo: che.TaskInfo): Promise; + addRunTaskHandler(func: (config: che.TaskConfiguration, ctx?: string) => Promise): void; + onKillEvent: Event } export interface ChePluginRegistry { diff --git a/extensions/eclipse-che-theia-plugin-ext/src/node/che-task-service.ts b/extensions/eclipse-che-theia-plugin-ext/src/node/che-task-service.ts index 86b9601c0..162dc5b16 100644 --- a/extensions/eclipse-che-theia-plugin-ext/src/node/che-task-service.ts +++ b/extensions/eclipse-che-theia-plugin-ext/src/node/che-task-service.ts @@ -22,14 +22,12 @@ export class CheTaskServiceImpl implements CheTaskService { private readonly disposableMap: Map; private readonly cheTasks: CheTask[] = []; private readonly clients: CheTaskClient[]; - private taskId: number; constructor(container: interfaces.Container) { this.runnerRegistry = container.get(TaskRunnerRegistry); this.taskManager = container.get(TaskManager); this.logger = container.get(ILogger); this.disposableMap = new Map(); this.clients = []; - this.taskId = 0; } async registerTaskRunner(type: string): Promise { @@ -40,13 +38,15 @@ export class CheTaskServiceImpl implements CheTaskService { }; this.disposableMap.set(type, this.runnerRegistry.registerRunner(type, runner)); const runTask = async (config: TaskConfiguration, ctx?: string): Promise => { - const id = this.taskId++; for (const client of this.clients) { - await client.runTask(id, config, ctx); + const taskInfo = await client.runTask(config, ctx); + const options: CheTaskOptions = { label: config.label, config, context: ctx, runtimeInfo: taskInfo }; + + const cheTask = new CheTask(this.taskManager, this.logger, this.clients, options); + this.cheTasks.push(cheTask); + return cheTask; } - const cheTask = new CheTask(id, this.taskManager, this.logger, { label: config.label, config, context: ctx }, this.clients); - this.cheTasks.push(cheTask); - return cheTask; + throw new Error(`Failed to process configuration with label ${config.label} by Che Task Client`); }; } @@ -74,57 +74,45 @@ export class CheTaskServiceImpl implements CheTaskService { async fireTaskExited(event: TaskExitedEvent): Promise { for (const task of this.cheTasks) { - try { - const runtimeInfo = await task.getRuntimeInfo(); - if (runtimeInfo.execId === event.execId || runtimeInfo.taskId === event.taskId) { - - task.fireTaskExited({ taskId: task.id, code: event.code, ctx: runtimeInfo.ctx }); + const runtimeInfo = task.getRuntimeInfo(); + if (runtimeInfo.execId === event.execId || runtimeInfo.taskId === event.taskId) { - task.onTaskExited(); + task.fireTaskExited({ taskId: task.id, code: event.code, ctx: runtimeInfo.ctx }); - const index = this.cheTasks.indexOf(task); - if (index > -1) { - this.cheTasks.splice(index, 1); - } - break; + const index = this.cheTasks.indexOf(task); + if (index > -1) { + this.cheTasks.splice(index, 1); } - } catch (e) { - // allow another handlers to handle request + break; } } } } +export interface CheTaskOptions extends TaskOptions { + runtimeInfo: TaskInfo; +} + class CheTask extends Task { private readonly clients: CheTaskClient[]; - constructor(id: number, + private taskInfo: TaskInfo; + constructor( taskManager: TaskManager, logger: ILogger, - options: TaskOptions, - clients: CheTaskClient[]) { + clients: CheTaskClient[], + options: CheTaskOptions) { + super(taskManager, logger, options); this.clients = clients; - this.taskId = id; + this.taskInfo = this.toTaskInfo(options.runtimeInfo); } - async getRuntimeInfo(): Promise { - for (const client of this.clients) { - const taskInfo = await client.getTaskInfo(this.taskId); - if (taskInfo) { - return this.toTaskInfo(taskInfo); - } - } - throw new Error(`Runtime Information for task ${this.options.label} is not found`); - } - - async onTaskExited(): Promise { - for (const client of this.clients) { - await client.onTaskExited(this.taskId); - } + getRuntimeInfo(): TaskInfo { + return this.taskInfo; } async kill(): Promise { - this.clients.forEach(client => client.killTask(this.taskId)); + this.clients.forEach(client => client.killTask(this.taskInfo)); } fireTaskExited(event: TaskExitedEvent): void { diff --git a/extensions/eclipse-che-theia-plugin-ext/src/plugin/che-task-impl.ts b/extensions/eclipse-che-theia-plugin-ext/src/plugin/che-task-impl.ts index 1fedbb711..0d6e60d54 100644 --- a/extensions/eclipse-che-theia-plugin-ext/src/plugin/che-task-impl.ts +++ b/extensions/eclipse-che-theia-plugin-ext/src/plugin/che-task-impl.ts @@ -8,17 +8,15 @@ * SPDX-License-Identifier: EPL-2.0 **********************************************************************/ import { CheTask, CheTaskMain, PLUGIN_RPC_CONTEXT } from '../common/che-protocol'; -import { TaskRunner, Disposable, Task, TaskInfo, TaskExitedEvent, TaskConfiguration } from '@eclipse-che/plugin'; +import { TaskRunner, Disposable, TaskInfo, TaskExitedEvent, TaskConfiguration } from '@eclipse-che/plugin'; import { RPCProtocol } from '@theia/plugin-ext/lib/common/rpc-protocol'; export class CheTaskImpl implements CheTask { private readonly cheTaskMain: CheTaskMain; private readonly runnerMap: Map; - private readonly taskMap: Map; constructor(rpc: RPCProtocol) { this.cheTaskMain = rpc.getProxy(PLUGIN_RPC_CONTEXT.CHE_TASK_MAIN); this.runnerMap = new Map(); - this.taskMap = new Map(); } async registerTaskRunner(type: string, runner: TaskRunner): Promise { this.runnerMap.set(type, runner); @@ -30,34 +28,20 @@ export class CheTaskImpl implements CheTask { }; } - async $runTask(id: number, config: TaskConfiguration, ctx?: string): Promise { + async $runTask(config: TaskConfiguration, ctx?: string): Promise { const runner = this.runnerMap.get(config.type); if (runner) { - const task = await runner.run(config, ctx); - this.taskMap.set(id, task); + return await runner.run(config, ctx); } + throw new Error(`Task Runner for type ${config.type} is not found.`); } - async $killTask(id: number): Promise { - const task = this.taskMap.get(id); - if (task) { - await task.kill(); - this.taskMap.delete(id); - } - } - - async $getTaskInfo(id: number): Promise { - const task = this.taskMap.get(id); - if (task) { - return task.getRuntimeInfo(); - } - } - - async $onTaskExited(id: number): Promise { - const task = this.taskMap.get(id); - if (task) { - this.taskMap.delete(id); + async $killTask(taskInfo: TaskInfo): Promise { + const runner = this.runnerMap.get(taskInfo.config.type); + if (runner) { + return await runner.kill(taskInfo); } + throw new Error(`Failed to terminate Che command: ${taskInfo.config.label}: the corresponging executor is not found`); } async fireTaskExited(event: TaskExitedEvent): Promise { diff --git a/extensions/eclipse-che-theia-plugin/src/che-proposed.d.ts b/extensions/eclipse-che-theia-plugin/src/che-proposed.d.ts index 07a53891b..356fe44c3 100644 --- a/extensions/eclipse-che-theia-plugin/src/che-proposed.d.ts +++ b/extensions/eclipse-che-theia-plugin/src/che-proposed.d.ts @@ -112,14 +112,9 @@ declare module '@eclipse-che/plugin' { /** A Task Runner knows how to run a Task of a particular type. */ export interface TaskRunner { /** Runs a task based on the given task configuration. */ - run(taskConfig: TaskConfiguration, ctx?: string): Promise; - } - - export interface Task { - /** Terminates the task. */ - kill(): Promise; - /** Returns runtime information about task. */ - getRuntimeInfo(): TaskInfo; + run(taskConfig: TaskConfiguration, ctx?: string): Promise; + /** Terminates a task based on the given info. */ + kill(taskInfo: TaskInfo): Promise; } /** Runtime information about Task. */ diff --git a/plugins/task-plugin/src/task/che-task-runner.ts b/plugins/task-plugin/src/task/che-task-runner.ts index fc36a3748..db1157a0a 100644 --- a/plugins/task-plugin/src/task/che-task-runner.ts +++ b/plugins/task-plugin/src/task/che-task-runner.ts @@ -44,7 +44,7 @@ export class CheTaskRunner { /** * Runs a task from the given task configuration which must have a target property specified. */ - async run(taskConfig: che.TaskConfiguration, ctx?: string): Promise { + async run(taskConfig: che.TaskConfiguration, ctx?: string): Promise { const { type, label, ...definition } = taskConfig; if (type !== CHE_TASK_TYPE) { throw new Error(`Unsupported task type: ${type}`); @@ -77,20 +77,19 @@ export class CheTaskRunner { const execId = await terminal.processId; return { - kill: () => { - throw new Error('Stopping a Che task currently is not supported.'); - }, - getRuntimeInfo: () => - ({ - taskId: STUB_TASK_ID, - ctx: ctx, - config: taskConfig, - execId: execId - }) + taskId: STUB_TASK_ID, + ctx: ctx, + config: taskConfig, + execId: execId }; } catch (error) { console.error('Failed to execute Che command:', error); throw new Error(`Failed to execute Che command: ${error.message}`); } } + + /** Terminates a task based on the given info. */ + async kill(taskInfo: che.TaskInfo): Promise { + throw new Error('Stopping a Che task currently is not supported.'); + } }