{"version":3,"file":"index.cjs","names":["SYSTEM_CONTEXT_KEY"],"sources":["../../src/runtime/strategies/local-execution-strategy.ts","../../src/runtime/strategies/web-worker-strategy.ts","../../src/runtime/worker-runtime.ts"],"sourcesContent":["import { ILogger, PerformanceTimeEntry } from '@awesome-ecs/abstract/utils';\r\nimport { WorkerExecutionMode } from '../../abstract/worker-execution-mode';\nimport {\n  IWorkerExecutionStrategy,\n  WorkerResponseCallback\n} from '../../abstract/worker-execution-strategy';\nimport { IWorkerHandlerRegistry } from '../../abstract/worker-handler-registry';\nimport { WorkerRequestMessage, WorkerResponseMessage } from '../../abstract/worker-message';\nimport { WorkerStatus } from '../../components/worker-instance';\nimport { WorkerThreadEntity } from '../../entities/worker-thread';\n\r\nexport class LocalExecutionStrategy implements IWorkerExecutionStrategy {\r\n  readonly mode = WorkerExecutionMode.local;\r\n\r\n  constructor(\r\n    private readonly handlerRegistry: IWorkerHandlerRegistry,\r\n    private readonly logger: ILogger\r\n  ) {}\r\n\r\n  dispatch(\n    message: WorkerRequestMessage<any>,\n    entity: WorkerThreadEntity,\n    onResponse: WorkerResponseCallback\n  ): void {\n    entity.instance.status = WorkerStatus.busy;\r\n\r\n    try {\r\n      const handler = this.handlerRegistry.resolve(message.request.type);\r\n\r\n      if (!handler) {\r\n        this.logger.warn(\r\n          `[LOCAL-WORKER] No handler registered for request type: ${message.request.type}`\r\n        );\r\n        entity.instance.status = WorkerStatus.available;\r\n        return;\r\n      }\r\n\r\n      this.logger.debug(\r\n        '[LOCAL-WORKER] Executing handler locally',\r\n        message.request.type,\r\n        message.messageUid\r\n      );\r\n\r\n      const startTime = performance.now();\r\n      const result = handler.handle(message.request);\r\n      const duration = performance.now() - startTime;\r\n\r\n      const metric: PerformanceTimeEntry = {\r\n        name: message.request.type,\r\n        startedAt: startTime,\r\n        endedAt: startTime + duration,\r\n        msPassed: duration\r\n      };\r\n\r\n      const response: WorkerResponseMessage<any> = {\r\n        data: result.data,\r\n        transfer: result.transfer,\r\n        metrics: result.metrics ? [...result.metrics, metric] : [metric],\r\n        messageType: message.messageType,\r\n        messageUid: message.messageUid,\r\n        workerType: message.workerType\r\n      };\r\n\r\n      onResponse(entity, response);\r\n    } catch (error: any) {\r\n      this.logger.warn(`[LOCAL-WORKER] Handler error: ${error?.message}`, message.request.type, error);\r\n      entity.instance.status = WorkerStatus.error;\r\n    }\r\n  }\r\n}\r\n","import { ILogger } from '@awesome-ecs/abstract/utils';\nimport { WorkerExecutionMode } from '../../abstract/worker-execution-mode';\nimport { IWorkerExecutionStrategy } from '../../abstract/worker-execution-strategy';\nimport { WorkerRequestMessage } from '../../abstract/worker-message';\nimport { WorkerStatus } from '../../components/worker-instance';\nimport { WorkerThreadEntity } from '../../entities/worker-thread';\n\nexport class WebWorkerExecutionStrategy implements IWorkerExecutionStrategy {\n  readonly mode = WorkerExecutionMode.worker;\n\n  constructor(private readonly logger: ILogger) {}\n\n  dispatch(message: WorkerRequestMessage<any>, entity: WorkerThreadEntity): void {\n    this.logger.debug('Sending message to Worker', entity.identity.model.uid, message);\n\n    entity.instance.worker.postMessage(message);\n    entity.instance.status = WorkerStatus.busy;\n  }\n}\n","import {\r\n  IContextRepository,\r\n  IEntityProxy,\r\n  IEntityRepository,\r\n  SYSTEM_CONTEXT_KEY\r\n} from '@awesome-ecs/abstract/entities';\r\nimport { IMutableSystemContext } from '@awesome-ecs/abstract/systems';\r\nimport { ILogger } from '@awesome-ecs/abstract/utils';\r\nimport { WorkerThreadEventType } from '../abstract/events/event-type';\r\nimport { WorkerThreadEventMessageResponseData } from '../abstract/events/message';\r\nimport { WorkerEntityType } from '../abstract/types/entity-type';\r\nimport {\r\n  IWorkerExecutionStrategy,\r\n  WorkerResponseCallback\r\n} from '../abstract/worker-execution-strategy';\r\nimport { WorkerMessageType, WorkerResponseMessage } from '../abstract/worker-message';\r\nimport { IWorkerMessageQueue } from '../abstract/worker-queue';\r\nimport { WorkerStatus } from '../components/worker-instance';\r\nimport { WorkerThreadEntity } from '../entities/worker-thread';\r\nimport { WorkerPerformanceTracker } from '../utils/worker-performance-tracker';\r\n\r\ntype InstrumentedWorkerMessageQueue = IWorkerMessageQueue & {\r\n  flushWaitTimes?: () => number[];\r\n  markAllAsStalled?: () => void;\r\n};\r\n\r\n// @injectable\r\nexport class WorkerSystemRuntime {\r\n  private readonly onResponse: WorkerResponseCallback;\r\n\r\n  constructor(\r\n    private readonly workerMessageQueue: IWorkerMessageQueue,\r\n    private readonly entityRepository: IEntityRepository,\r\n    private readonly logger: ILogger,\r\n    private readonly strategy: IWorkerExecutionStrategy,\r\n    private readonly contextRepository?: IContextRepository,\r\n    private readonly performanceTracker?: WorkerPerformanceTracker\r\n  ) {\r\n    this.onResponse = (\r\n      entity: Readonly<WorkerThreadEntity>,\r\n      response: WorkerResponseMessage<any>\r\n    ) => {\r\n      if (!this.contextRepository) {\r\n        this.logger.warn(\r\n          '[WORKER-RUNTIME] No context repository configured for local response handling'\r\n        );\r\n        return;\r\n      }\r\n\r\n      const systemContext = this.contextRepository.get<IMutableSystemContext<WorkerThreadEntity>>(\r\n        entity.identity.proxy,\r\n        SYSTEM_CONTEXT_KEY\r\n      );\r\n      if (!systemContext) {\r\n        this.logger.warn('[WORKER-RUNTIME] No context found for entity', entity.identity.model.uid);\r\n        return;\r\n      }\r\n\r\n      const eventData: WorkerThreadEventMessageResponseData<any> = {\r\n        uid:\r\n          response.messageType === WorkerMessageType.health\r\n            ? WorkerThreadEventType.messageReceivedHealth\r\n            : WorkerThreadEventType.messageReceivedData,\r\n        message: response\r\n      };\r\n\r\n      systemContext.events.dispatchEvent(eventData, entity.identity.proxy as IEntityProxy);\r\n\r\n      this.logger.debug(\r\n        '[WORKER-LOCAL-RESPONSE] Dispatched response event',\r\n        response.messageType,\r\n        response.messageUid\r\n      );\r\n    };\r\n  }\r\n\r\n  runTick(): void {\r\n    while (this.workerMessageQueue.size > 0) {\r\n      const message = this.workerMessageQueue.peek();\r\n\r\n      if (!message) {\r\n        return;\r\n      }\r\n\r\n      const workers = this.entityRepository.getEntities<WorkerThreadEntity>(\r\n        WorkerEntityType.workerThread\r\n      );\r\n\r\n      if (!workers) {\r\n        this.logger.warn('No WorkerThreadEntity was registered for type: ', message.workerType);\r\n        return;\r\n      }\r\n\r\n      const availableWorker = this.findAvailableWorker(\r\n        workers.filter((worker): worker is WorkerThreadEntity => !!worker)\r\n      );\r\n\r\n      if (!availableWorker) {\r\n        this.logger.debug(\r\n          'No available worker found. Skipping remaining messages.',\r\n          message.workerType,\r\n          message.messageUid\r\n        );\r\n\r\n        if (this.performanceTracker) {\r\n          const queue = this.workerMessageQueue as InstrumentedWorkerMessageQueue;\r\n          if (typeof queue.markAllAsStalled === 'function') {\r\n            queue.markAllAsStalled();\r\n          }\r\n          this.performanceTracker.recordStalledCount(this.workerMessageQueue.size);\r\n        }\r\n        return;\r\n      }\r\n\r\n      this.strategy.dispatch(message, availableWorker, this.onResponse);\r\n      this.workerMessageQueue.dequeue();\r\n    }\r\n\r\n    this.flushQueueWaitTimes();\r\n  }\r\n\r\n  private flushQueueWaitTimes(): void {\r\n    if (!this.performanceTracker) return;\r\n    const queue = this.workerMessageQueue as InstrumentedWorkerMessageQueue;\r\n    if (typeof queue.flushWaitTimes === 'function') {\r\n      const waitTimes: number[] = queue.flushWaitTimes();\r\n      if (waitTimes.length) {\r\n        this.performanceTracker.recordWaitTimes(waitTimes);\r\n      }\r\n    }\r\n  }\r\n\r\n  private findAvailableWorker(\r\n    workers: ReadonlyArray<WorkerThreadEntity>\r\n  ): WorkerThreadEntity | undefined {\r\n    for (const worker of workers) {\r\n      if (worker.instance.status === WorkerStatus.available) {\r\n        return worker;\r\n      }\r\n    }\r\n\r\n    return undefined;\r\n  }\r\n}\r\n"],"mappings":"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"}