UNPKG

@awesome-ecs/workers

Version:

The Workers package for Awesome ECS. Provides basic implementation for the Worker communication using ECS.

261 lines (210 loc) 7.46 kB
# Awesome ECS (Entity-Component-System) ## Workers Package The Workers package extends the Awesome ECS framework with multithreaded processing capabilities using Web Workers or Node.js Worker Threads. It enables distributing computational workloads across multiple threads while maintaining the ECS architecture. ## Real-World Usage Patterns Based on the analysis of real-world usage in project-anchor, here are the key implementation patterns for the Workers package: ### Worker Thread Integration - **Worker-Specific Components**: Special components manage worker state and communication ```typescript // In worker-thread.ts module export class WorkerThreadEntity extends EntityBase<WorkerModel> { get status(): TasksComponent { return this.getComponent(ComponentType.tasks); } } ``` - **Thread Task Scheduling**: Systems coordinate task distribution across worker threads ```typescript // Inside a system middleware action(context: ISystemContext<WorkerThreadEntity>): void { const entity = context.entity; const tasks = entity.tasks; // Assign tasks to worker threads if (tasks.queue.length < tasks.maxQueueSize) { tasks.queue.push(this.getNextTask()); } } ``` - **Message Passing**: Structured communication between main thread and worker threads ```typescript // Inside worker communication system const message = { type: 'TASK_COMPLETE', data: result, taskId: task.id }; worker.postMessage(message); ``` ### Task Management - **Task Queuing**: Tasks are queued and processed by worker threads ```typescript // In a terrain generation system const task = { id: generateUid(), type: 'GENERATE_TERRAIN', data: { seed: this.seed, resolution: this.resolution, chunks: pendingChunks } }; workerEntity.tasks.queue.push(task); ``` - **Result Handling**: Systems process results from worker threads ```typescript // Inside result handling system handleWorkerMessage(message: WorkerMessage) { if (message.type === 'TASK_COMPLETE') { const { taskId, data } = message; // Find the entity waiting for this task result const entity = this.findEntityByTaskId(taskId); // Update entity with worker result if (entity) { this.updateEntityWithResult(entity, data); } } } ``` ### Integration with ECS - **Worker System Modules**: Dedicated system modules manage worker threads ```typescript @autoinject export class WorkerThreadSystemsModule extends LocalSystemsModuleBase<WorkerThreadEntity> { constructor( private workerInitSystem: WorkerInitSystem, private workerMessageSystem: WorkerMessageSystem, private workerTaskSystem: WorkerTaskSystem ) { super(); this.registerSystems(SystemPipelineType.initialize, [ workerInitSystem ]); this.registerSystems(SystemPipelineType.update, [ workerMessageSystem, workerTaskSystem ]); } } ``` - **CPU-Intensive Operations**: Workers handle computationally expensive tasks ```typescript // Examples of operations offloaded to workers: // - Terrain generation // - Pathfinding calculations // - Physics simulations // - AI processing ``` ### Overview The Workers implementation provides: - Thread-based parallel processing for CPU-intensive tasks - Message-based communication between the main thread and worker threads - Health monitoring and worker lifecycle management - Queue-based work distribution system ### Package Structure - **abstract/**: Core interfaces and types for worker operations - `worker-message.ts`: Defines message formats for worker communication - `worker-queue.ts`: Queue implementation for worker messages - `worker-instance.ts`: Defines worker instance structure - `worker-health.ts`: Health monitoring interfaces - `worker-factory.ts`: Factory for creating worker instances - `worker-system-context.ts`: System context for worker operations - `types/`: Type definitions for worker components - `events/`: Event definitions for worker communication - **components/**: Worker-specific components - Components for managing worker state and communication - **systems/**: Systems for handling worker operations - `middlewares/`: Middleware implementations for worker systems - Systems for worker lifecycle management - **runtime/**: Worker runtime implementation - Runtime environment for workers - **entities/**: Worker-specific entities - Entity implementations for workers - **helpers/**: Utility functions for worker operations - Helper functions for common worker tasks ## Real-World Example ### Using Workers for Terrain Generation ```typescript // Main thread: Setting up worker system class TerrainGenerationSystem implements ISystemMiddleware<TerrainEntity> { action(context: ISystemContext<TerrainEntity>): void { const terrain = context.entity; // Create task for terrain generation const task = { id: generateUid(), type: 'GENERATE_TERRAIN', data: { seed: terrain.seed.value, size: terrain.area.size, resolution: terrain.area.resolution } }; // Send task to worker this.workerManager.assignTask(task, (result) => { // Process result when task is complete this.applyTerrainData(terrain, result.heightmapData); }); } } // Worker thread: Processing terrain generation self.addEventListener('message', (event) => { const { id, type, data } = event.data; if (type === 'GENERATE_TERRAIN') { // Generate terrain data using the provided parameters const terrainData = generateTerrain(data.seed, data.size, data.resolution); // Send result back to main thread self.postMessage({ type: 'TASK_COMPLETE', taskId: id, data: { heightmapData: terrainData } }); } }); ``` ### Worker Lifecycle Management ```typescript // Worker manager module @autoinject export class WorkerManager { private workers: Map<string, WorkerEntity> = new Map(); constructor(private entityManager: EntityManager) {} initialize(numWorkers: number) { // Create worker entities for (let i = 0; i < numWorkers; i++) { const workerId = `worker-${i}`; // Create worker entity const workerEntity = this.entityManager.createEntity({ entityType: EntityType.worker, entityUid: workerId, model: { uid: workerId, workerType: 'general' } }); this.workers.set(workerId, workerEntity); } } assignTask(task: WorkerTask, callback: (result: any) => void) { // Find available worker const availableWorker = this.findAvailableWorker(); if (availableWorker) { // Register callback for when task completes this.taskCallbacks.set(task.id, callback); // Assign task to worker availableWorker.tasks.queue.push(task); availableWorker.tasks.status = 'busy'; } else { // Queue task for later assignment this.pendingTasks.push({ task, callback }); } } } ``` ### Integration with Other Packages The Workers package is designed to integrate with: - `@awesome-ecs/core`: Core ECS functionality - `@awesome-ecs/ai`: AI behavior implementations that can be offloaded to worker threads