CoolFace
Apppublic

Leon4gr45/builder

sourceHugging Facemitupdated 2d agoView on Hugging Face
0likes
task-manager.ts88 linesDownload Raw Back to server-generate
1import { randomUUID } from 'node:crypto';2import type { ServerTask } from './types';3 4interface TaskManagerOptions {5  maxConcurrentPerScope: number;6  keyTTLMs: number;7}8 9export class TaskManager {10  private tasks = new Map<string, ServerTask>();11  private apiKeys = new Map<string, { key: string; createdAt: number }>();12  private sweepInterval: ReturnType<typeof setInterval> | null = null;13 14  constructor(private readonly options: TaskManagerOptions) {15    this.sweepInterval = setInterval(() => this.sweepExpiredKeys(), 60_000);16  }17 18  createTask(projectId: string, sessionId: string, apiKey: string, workspaceId?: string): string {19    const scope = workspaceId ?? sessionId;20    const activeTasks = [...this.tasks.values()].filter(21      (t) => (t.workspaceId ?? t.sessionId) === scope && (t.status === 'running' || t.status === 'paused'),22    );23 24    if (activeTasks.length >= this.options.maxConcurrentPerScope) {25      throw new Error(`Concurrent task limit (${this.options.maxConcurrentPerScope}) reached`);26    }27 28    const taskId = randomUUID();29    const task: ServerTask = {30      taskId,31      projectId,32      sessionId,33      workspaceId,34      status: 'running',35      startedAt: Date.now(),36      orchestrator: null,37      buildDeferred: false,38      pendingBuildResolve: null,39    };40 41    this.tasks.set(taskId, task);42    this.apiKeys.set(taskId, { key: apiKey, createdAt: Date.now() });43    return taskId;44  }45 46  getTask(taskId: string): ServerTask | undefined {47    return this.tasks.get(taskId);48  }49 50  getApiKey(taskId: string): string | undefined {51    return this.apiKeys.get(taskId)?.key;52  }53 54  completeTask(taskId: string, status: 'completed' | 'failed' | 'cancelled'): void {55    const task = this.tasks.get(taskId);56    if (task) {57      task.status = status;58      task.orchestrator = null;59    }60    this.apiKeys.delete(taskId);61  }62 63  getTasksForSession(sessionId: string): ServerTask[] {64    return [...this.tasks.values()].filter((t) => t.sessionId === sessionId);65  }66 67  sweepExpiredKeys(): void {68    const now = Date.now();69    for (const [taskId, entry] of this.apiKeys) {70      if (now - entry.createdAt > this.options.keyTTLMs) {71        this.apiKeys.delete(taskId);72      }73    }74    for (const [taskId, task] of this.tasks) {75      if (task.status !== 'running' && task.status !== 'paused' && now - task.startedAt > this.options.keyTTLMs) {76        this.tasks.delete(taskId);77      }78    }79  }80 81  dispose(): void {82    if (this.sweepInterval) {83      clearInterval(this.sweepInterval);84      this.sweepInterval = null;85    }86  }87}88