UNPKG

@awesome-ecs/workers

Version:

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

135 lines (134 loc) 4.83 kB
import "../worker-message-CpfPNmUD.mjs"; import "../worker-execution-mode-7gqqovFY.mjs"; import "../worker-instance-D6m0tNnA.mjs"; import { SYSTEM_CONTEXT_KEY } from "@awesome-ecs/abstract/entities"; //#region src/runtime/strategies/local-execution-strategy.ts var LocalExecutionStrategy = class { handlerRegistry; logger; mode = "local"; constructor(handlerRegistry, logger) { this.handlerRegistry = handlerRegistry; this.logger = logger; } dispatch(message, entity, onResponse) { entity.instance.status = 2; try { const handler = this.handlerRegistry.resolve(message.request.type); if (!handler) { this.logger.warn(`[LOCAL-WORKER] No handler registered for request type: ${message.request.type}`); entity.instance.status = 1; return; } this.logger.debug("[LOCAL-WORKER] Executing handler locally", message.request.type, message.messageUid); const startTime = performance.now(); const result = handler.handle(message.request); const duration = performance.now() - startTime; const metric = { name: message.request.type, startedAt: startTime, endedAt: startTime + duration, msPassed: duration }; onResponse(entity, { data: result.data, transfer: result.transfer, metrics: result.metrics ? [...result.metrics, metric] : [metric], messageType: message.messageType, messageUid: message.messageUid, workerType: message.workerType }); } catch (error) { this.logger.warn(`[LOCAL-WORKER] Handler error: ${error?.message}`, message.request.type, error); entity.instance.status = 3; } } }; //#endregion //#region src/runtime/strategies/web-worker-strategy.ts var WebWorkerExecutionStrategy = class { logger; mode = "worker"; constructor(logger) { this.logger = logger; } dispatch(message, entity) { this.logger.debug("Sending message to Worker", entity.identity.model.uid, message); entity.instance.worker.postMessage(message); entity.instance.status = 2; } }; //#endregion //#region src/runtime/worker-runtime.ts var WorkerSystemRuntime = class { workerMessageQueue; entityRepository; logger; strategy; contextRepository; performanceTracker; onResponse; constructor(workerMessageQueue, entityRepository, logger, strategy, contextRepository, performanceTracker) { this.workerMessageQueue = workerMessageQueue; this.entityRepository = entityRepository; this.logger = logger; this.strategy = strategy; this.contextRepository = contextRepository; this.performanceTracker = performanceTracker; this.onResponse = (entity, response) => { if (!this.contextRepository) { this.logger.warn("[WORKER-RUNTIME] No context repository configured for local response handling"); return; } const systemContext = this.contextRepository.get(entity.identity.proxy, SYSTEM_CONTEXT_KEY); if (!systemContext) { this.logger.warn("[WORKER-RUNTIME] No context found for entity", entity.identity.model.uid); return; } const eventData = { uid: response.messageType === "health" ? "message-received-health" : "message-received-data", message: response }; systemContext.events.dispatchEvent(eventData, entity.identity.proxy); this.logger.debug("[WORKER-LOCAL-RESPONSE] Dispatched response event", response.messageType, response.messageUid); }; } runTick() { while (this.workerMessageQueue.size > 0) { const message = this.workerMessageQueue.peek(); if (!message) return; const workers = this.entityRepository.getEntities("worker-thread"); if (!workers) { this.logger.warn("No WorkerThreadEntity was registered for type: ", message.workerType); return; } const availableWorker = this.findAvailableWorker(workers.filter((worker) => !!worker)); if (!availableWorker) { this.logger.debug("No available worker found. Skipping remaining messages.", message.workerType, message.messageUid); if (this.performanceTracker) { const queue = this.workerMessageQueue; if (typeof queue.markAllAsStalled === "function") queue.markAllAsStalled(); this.performanceTracker.recordStalledCount(this.workerMessageQueue.size); } return; } this.strategy.dispatch(message, availableWorker, this.onResponse); this.workerMessageQueue.dequeue(); } this.flushQueueWaitTimes(); } flushQueueWaitTimes() { if (!this.performanceTracker) return; const queue = this.workerMessageQueue; if (typeof queue.flushWaitTimes === "function") { const waitTimes = queue.flushWaitTimes(); if (waitTimes.length) this.performanceTracker.recordWaitTimes(waitTimes); } } findAvailableWorker(workers) { for (const worker of workers) if (worker.instance.status === 1) return worker; } }; //#endregion export { LocalExecutionStrategy, WebWorkerExecutionStrategy, WorkerSystemRuntime }; //# sourceMappingURL=index.mjs.map