Spaces:
Running
Running
| import {DetectTaskHandler} from './tasks/DetectTaskHandler'; | |
| import {DescribeTaskHandler} from './tasks/DescribeTaskHandler'; | |
| import {AbstractModelTaskHandler} from './tasks/AbstractModelTaskHandler'; | |
| import type { | |
| ClusterTaskHandlerOptions, | |
| ClusterTaskHostContext, | |
| ClusterTaskKind, | |
| HostTaskMessage, | |
| } from './tasks/types'; | |
| export type {ClusterTaskKind, HostTaskMessage, ClusterTaskHandlerOptions} from './tasks/types'; | |
| export class ClusterTaskHandler { | |
| private readonly taskQueue: HostTaskMessage[] = []; | |
| private processing = false; | |
| private readonly host: ClusterTaskHostContext; | |
| private readonly handlers: Map<ClusterTaskKind, AbstractModelTaskHandler>; | |
| constructor(options: ClusterTaskHandlerOptions) { | |
| this.host = { | |
| apiBase: options.apiBase, | |
| getSelectedModelId: options.getSelectedModelId, | |
| setStatus: options.setStatus, | |
| }; | |
| this.handlers = new Map<ClusterTaskKind, AbstractModelTaskHandler>([ | |
| ['detect', new DetectTaskHandler(this.host, options.getDetector)], | |
| ['describe', new DescribeTaskHandler(this.host, options.getDescriber)], | |
| ]); | |
| } | |
| enqueueTask(task: HostTaskMessage): void { | |
| this.taskQueue.push(task); | |
| void this.drainTaskQueue(); | |
| } | |
| parseIncomingTask( | |
| raw: HostTaskMessage & {kind?: ClusterTaskKind}, | |
| defaultKind: ClusterTaskKind, | |
| ): HostTaskMessage { | |
| return { | |
| ...raw, | |
| kind: raw.kind ?? defaultKind, | |
| }; | |
| } | |
| private async drainTaskQueue(): Promise<void> { | |
| if (this.processing || this.taskQueue.length === 0) { | |
| return; | |
| } | |
| const task = this.taskQueue.shift(); | |
| if (task) { | |
| await this.processTask(task); | |
| } | |
| } | |
| private async processTask(task: HostTaskMessage): Promise<void> { | |
| const handler = this.handlers.get(task.kind); | |
| if (!handler) { | |
| throw new Error(`No handler for task kind '${task.kind}'`); | |
| } | |
| this.processing = true; | |
| this.host.setStatus(`Processing task ${task.id.slice(0, 8)}…`); | |
| try { | |
| await handler.process(task); | |
| this.host.setStatus(`Task ${task.id.slice(0, 8)} complete. Waiting for requests…`); | |
| } catch (error) { | |
| const message = error instanceof Error ? error.message : String(error); | |
| this.host.setStatus(`Task failed: ${message}`); | |
| } finally { | |
| this.processing = false; | |
| void this.drainTaskQueue(); | |
| } | |
| } | |
| } | |