@uns-kit/core 2.0.70 → 2.0.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +304 -302
  3. package/dist/base-path.js.map +1 -1
  4. package/dist/config/app-config.js.map +1 -1
  5. package/dist/config/project.config.extension.js.map +1 -1
  6. package/dist/config-file.js.map +1 -1
  7. package/dist/examples/datahub-client.js.map +1 -1
  8. package/dist/graphql/schema.js.map +1 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/logger.js.map +1 -1
  11. package/dist/tools/auth/auth-client.js.map +1 -1
  12. package/dist/tools/auth/index.js.map +1 -1
  13. package/dist/tools/auth/secure-store.js.map +1 -1
  14. package/dist/tools/base-path.js.map +1 -1
  15. package/dist/tools/datahub/datahub-client.js.map +1 -1
  16. package/dist/tools/file-utils.js.map +1 -1
  17. package/dist/tools/generate-config-schema.js.map +1 -1
  18. package/dist/tools/generate-uns-dictionary.js +7 -7
  19. package/dist/tools/generate-uns-dictionary.js.map +1 -1
  20. package/dist/tools/generate-uns-measurements.js +7 -7
  21. package/dist/tools/generate-uns-measurements.js.map +1 -1
  22. package/dist/tools/generate-uns-reference.js +9 -9
  23. package/dist/tools/generate-uns-reference.js.map +1 -1
  24. package/dist/tools/pull-request.js.map +1 -1
  25. package/dist/tools/refresh-uns.js.map +1 -1
  26. package/dist/tools/schema.js.map +1 -1
  27. package/dist/tools/sync-uns-metadata.js +22 -22
  28. package/dist/tools/sync-uns-metadata.js.map +1 -1
  29. package/dist/tools/sync-uns-schema.js +17 -17
  30. package/dist/tools/sync-uns-schema.js.map +1 -1
  31. package/dist/uns/handover-manager-event-emitter.js.map +1 -1
  32. package/dist/uns/handover-manager.js.map +1 -1
  33. package/dist/uns/process-config.js.map +1 -1
  34. package/dist/uns/service-metadata.js.map +1 -1
  35. package/dist/uns/status-monitor.js.map +1 -1
  36. package/dist/uns/uns-asset.js.map +1 -1
  37. package/dist/uns/uns-attributes.js.map +1 -1
  38. package/dist/uns/uns-dictionary-registry.js.map +1 -1
  39. package/dist/uns/uns-dictionary.generated.js.map +1 -1
  40. package/dist/uns/uns-event-emitter.js.map +1 -1
  41. package/dist/uns/uns-interfaces.js.map +1 -1
  42. package/dist/uns/uns-measurements.generated.js.map +1 -1
  43. package/dist/uns/uns-measurements.js.map +1 -1
  44. package/dist/uns/uns-object.js.map +1 -1
  45. package/dist/uns/uns-packet.js.map +1 -1
  46. package/dist/uns/uns-path.js.map +1 -1
  47. package/dist/uns/uns-proxy-process.d.ts +2 -0
  48. package/dist/uns/uns-proxy-process.d.ts.map +1 -1
  49. package/dist/uns/uns-proxy-process.js +34 -9
  50. package/dist/uns/uns-proxy-process.js.map +1 -1
  51. package/dist/uns/uns-proxy.js.map +1 -1
  52. package/dist/uns/uns-tags.js.map +1 -1
  53. package/dist/uns/uns-topic-matcher.js.map +1 -1
  54. package/dist/uns/uns-topics.js.map +1 -1
  55. package/dist/uns-config/config-schema.js.map +1 -1
  56. package/dist/uns-config/host-placeholders.js.map +1 -1
  57. package/dist/uns-config/schema-tolls.js.map +1 -1
  58. package/dist/uns-config/schema-tools.js.map +1 -1
  59. package/dist/uns-config/secret-placeholders.js.map +1 -1
  60. package/dist/uns-config/secret-resolver.js.map +1 -1
  61. package/dist/uns-config/uns-core-schema.js.map +1 -1
  62. package/dist/uns-grpc/uns-gateway-cli.js.map +1 -1
  63. package/dist/uns-grpc/uns-gateway-server.d.ts.map +1 -1
  64. package/dist/uns-grpc/uns-gateway-server.js +11 -2
  65. package/dist/uns-grpc/uns-gateway-server.js.map +1 -1
  66. package/dist/uns-grpc/uns-gateway.proto +107 -107
  67. package/dist/uns-mqtt/mqtt-interfaces.js.map +1 -1
  68. package/dist/uns-mqtt/mqtt-proxy.d.ts +1 -1
  69. package/dist/uns-mqtt/mqtt-proxy.d.ts.map +1 -1
  70. package/dist/uns-mqtt/mqtt-proxy.js +33 -34
  71. package/dist/uns-mqtt/mqtt-proxy.js.map +1 -1
  72. package/dist/uns-mqtt/mqtt-topic-builder.js.map +1 -1
  73. package/dist/uns-mqtt/mqtt-worker-init.js.map +1 -1
  74. package/dist/uns-mqtt/mqtt-worker.js.map +1 -1
  75. package/dist/uns-mqtt/throttled-queue.d.ts.map +1 -1
  76. package/dist/uns-mqtt/throttled-queue.js +7 -2
  77. package/dist/uns-mqtt/throttled-queue.js.map +1 -1
  78. package/dist/uns-mqtt/uns-mqtt-proxy.d.ts +5 -0
  79. package/dist/uns-mqtt/uns-mqtt-proxy.d.ts.map +1 -1
  80. package/dist/uns-mqtt/uns-mqtt-proxy.js +78 -34
  81. package/dist/uns-mqtt/uns-mqtt-proxy.js.map +1 -1
  82. package/dist/uns-mqtt/ws-proxy.js.map +1 -1
  83. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"mqtt-worker.js","sourceRoot":"","sources":["../../src/uns-mqtt/mqtt-worker.ts"],"names":[],"mappings":"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","sourcesContent":["import { IClientPublishOptions } from \"mqtt\";\r\nimport { join } from \"path\";\r\nimport { parentPort } from \"worker_threads\";\r\n\r\nimport { basePath } from \"../base-path.js\";\r\nimport logger from \"../logger.js\";\r\nimport { IMqttWorkerData } from \"./mqtt-interfaces.js\";\r\nimport MqttProxy from \"./mqtt-proxy.js\";\r\nimport { ThrottledPublisher, ThrottledSubscriber } from \"./throttled-queue.js\";\r\n\r\nexport class MqttWorker {\r\n private mqttProxy: MqttProxy;\r\n protected publisher: ThrottledPublisher;\r\n protected subscriber: ThrottledSubscriber;\r\n\r\n constructor(workerData: IMqttWorkerData) {\r\n const publishThrottlingDelay = workerData.publishThrottlingDelay ?? 1;\r\n const publishConcurrency = workerData.publishConcurrency ?? 1;\r\n const maxPendingPublishes = workerData.maxPendingPublishes;\r\n const subscribeThrottlingDelay = workerData.subscribeThrottlingDelay ?? 1;\r\n const persistToDisk = workerData.persistToDisk ?? false;\r\n const mqttHost = workerData.mqttHost;\r\n const instanceName = workerData.instanceNameWithSuffix;\r\n const mqttParameters = workerData.mqttParameters;\r\n const publisherActive = workerData.publisherActive;\r\n const subscriberActive = workerData.subscriberActive;\r\n const defaultPublishOptions = workerData.defaultPublishOptions;\r\n\r\n // Initialize and start the MQTT proxy.\r\n this.mqttProxy = new MqttProxy(mqttHost, instanceName, mqttParameters, this);\r\n this.mqttProxy.start();\r\n\r\n // Set up the event listener for incoming messages from the MQTT proxy.\r\n this.mqttProxy.event.on(\"input\", (event) => {\r\n this.subscriber.enqueue(event.topic, event.message.toString());\r\n });\r\n\r\n // Set up the event listener for status messages from the MQTT proxy.\r\n this.mqttProxy.event.on(\"mqttProxyStatus\", (event) => {\r\n parentPort?.postMessage({\r\n command: \"mqttProxyStatus\",\r\n event: event.event,\r\n value: event.value,\r\n statusTopic: event.statusTopic,\r\n uom: event.uom,\r\n });\r\n });\r\n\r\n // Define the publish function to be used by the ThrottledPublisher.\r\n const publishFunction = async (topic: string, message: string, id: string, options?: IClientPublishOptions): Promise<void> => {\r\n const publishOptions = options ?? defaultPublishOptions;\r\n try {\r\n await this.mqttProxy.publish(topic, message, publishOptions);\r\n } catch (reason: any) {\r\n logger.error(`${instanceName} - Error publishing message to topic ${topic}: ${reason?.message ?? String(reason)}`);\r\n throw reason;\r\n }\r\n };\r\n\r\n // Create an instance of ThrottledPublisher.\r\n this.publisher = new ThrottledPublisher(\r\n publishThrottlingDelay,\r\n publishFunction,\r\n persistToDisk,\r\n join(basePath, \"/workerQueue/\", \"throttled-publisher-queue.json\"),\r\n instanceName,\r\n publisherActive,\r\n publishConcurrency,\r\n maxPendingPublishes,\r\n );\r\n\r\n // Define the message handler for incoming messages.\r\n const messageHandler = async (topic: string, message: string): Promise<void> => {\r\n parentPort?.postMessage({\r\n command: \"input\",\r\n topic: topic,\r\n message: message,\r\n });\r\n };\r\n\r\n // Create an instance of ThrottledSubscriber.\r\n this.subscriber = new ThrottledSubscriber(\r\n subscribeThrottlingDelay,\r\n messageHandler,\r\n persistToDisk,\r\n join(basePath, \"/workerQueue/\", \"throttled-subscriber-queue.json\"),\r\n instanceName,\r\n subscriberActive,\r\n );\r\n\r\n // Set up the message listener for commands from the main thread.\r\n this.initializeMessageListener();\r\n }\r\n\r\n /**\r\n * Listen for incoming messages from the main thread and process them.\r\n */\r\n private initializeMessageListener(): void {\r\n parentPort?.on(\"message\", async (msg) => {\r\n if (msg && msg.command === \"enqueue\" && msg.id && msg.topic && msg.message !== undefined) {\n try {\n const publishPromise = this.publisher.enqueueOrThrow(msg.topic, msg.message, msg.id, msg.options);\n parentPort?.postMessage({\n command: \"enqueueAccepted\",\n id: msg.id,\n status: \"accepted\",\n });\n void publishPromise\r\n .then(() => {\r\n parentPort?.postMessage({\r\n command: \"publishResult\",\r\n id: msg.id,\r\n status: \"success\",\r\n topic: msg.topic,\r\n });\r\n })\r\n .catch((error: any) => {\r\n parentPort?.postMessage({\r\n command: \"publishResult\",\r\n id: msg.id,\r\n status: \"error\",\r\n topic: msg.topic,\r\n error: error?.message ?? String(error),\r\n });\r\n });\r\n } catch (error: any) {\n parentPort?.postMessage({\n command: \"enqueueAccepted\",\n id: msg.id,\n status: \"error\",\n error: error?.message ?? String(error),\n });\n }\n } else if (msg && msg.command === \"subscribeAsync\" && msg.topics) {\r\n this.mqttProxy.subscribeAsync(msg.topics);\r\n } else if (msg && msg.command === \"unsubscribeAsync\" && msg.topics) {\r\n this.mqttProxy.unsubscribeAsync(msg.topics);\r\n } else if (msg && msg.command === \"setPublisherActive\") {\r\n this.publisher.becomeActive({batchSize: msg?.batchSize, referenceHash: msg?.referenceHash});\r\n } else if (msg && msg.command === \"setPublisherPassive\") {\r\n const snapshot = await this.publisher.becomePassive(3);\r\n parentPort?.postMessage({\r\n command: \"handover_publisher\",\r\n ...snapshot\r\n }); \r\n } else if (msg && msg.command === \"setSubscriberActive\") {\r\n this.subscriber.becomeActive({batchSize: msg?.batchSize, referenceHash: msg?.referenceHash});\r\n } else if (msg && msg.command === \"setSubscriberPassive\") {\r\n const snapshot = await this.subscriber.becomePassive(3);\r\n parentPort?.postMessage({\r\n command: \"handover_subscriber\",\r\n ...snapshot\r\n }); \r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Get the state of the publisher.\r\n */\r\n public getPublisherState(): boolean {\r\n return this.publisher.getState();\r\n }\r\n /**\r\n * Get the state of the subscriber.\r\n */\r\n public getSubscriberState(): boolean {\r\n return this.subscriber.getState();\r\n }\r\n\r\n}\r\n"]}
1
+ {"version":3,"file":"mqtt-worker.js","sourceRoot":"","sources":["../../src/uns-mqtt/mqtt-worker.ts"],"names":[],"mappings":"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","sourcesContent":["import { IClientPublishOptions } from \"mqtt\";\nimport { join } from \"path\";\nimport { parentPort } from \"worker_threads\";\n\nimport { basePath } from \"../base-path.js\";\nimport logger from \"../logger.js\";\nimport { IMqttWorkerData } from \"./mqtt-interfaces.js\";\nimport MqttProxy from \"./mqtt-proxy.js\";\nimport { ThrottledPublisher, ThrottledSubscriber } from \"./throttled-queue.js\";\n\nexport class MqttWorker {\n private mqttProxy: MqttProxy;\n protected publisher: ThrottledPublisher;\n protected subscriber: ThrottledSubscriber;\n\n constructor(workerData: IMqttWorkerData) {\n const publishThrottlingDelay = workerData.publishThrottlingDelay ?? 1;\n const publishConcurrency = workerData.publishConcurrency ?? 1;\n const maxPendingPublishes = workerData.maxPendingPublishes;\n const subscribeThrottlingDelay = workerData.subscribeThrottlingDelay ?? 1;\n const persistToDisk = workerData.persistToDisk ?? false;\n const mqttHost = workerData.mqttHost;\n const instanceName = workerData.instanceNameWithSuffix;\n const mqttParameters = workerData.mqttParameters;\n const publisherActive = workerData.publisherActive;\n const subscriberActive = workerData.subscriberActive;\n const defaultPublishOptions = workerData.defaultPublishOptions;\n\n // Initialize and start the MQTT proxy.\n this.mqttProxy = new MqttProxy(mqttHost, instanceName, mqttParameters, this);\n this.mqttProxy.start();\n\n // Set up the event listener for incoming messages from the MQTT proxy.\n this.mqttProxy.event.on(\"input\", (event) => {\n this.subscriber.enqueue(event.topic, event.message.toString());\n });\n\n // Set up the event listener for status messages from the MQTT proxy.\n this.mqttProxy.event.on(\"mqttProxyStatus\", (event) => {\n parentPort?.postMessage({\n command: \"mqttProxyStatus\",\n event: event.event,\n value: event.value,\n statusTopic: event.statusTopic,\n uom: event.uom,\n });\n });\n\n // Define the publish function to be used by the ThrottledPublisher.\n const publishFunction = async (topic: string, message: string, id: string, options?: IClientPublishOptions): Promise<void> => {\n const publishOptions = options ?? defaultPublishOptions;\n try {\n await this.mqttProxy.publish(topic, message, publishOptions);\n } catch (reason: any) {\n logger.error(`${instanceName} - Error publishing message to topic ${topic}: ${reason?.message ?? String(reason)}`);\n throw reason;\n }\n };\n\n // Create an instance of ThrottledPublisher.\n this.publisher = new ThrottledPublisher(\n publishThrottlingDelay,\n publishFunction,\n persistToDisk,\n join(basePath, \"/workerQueue/\", \"throttled-publisher-queue.json\"),\n instanceName,\n publisherActive,\n publishConcurrency,\n maxPendingPublishes,\n );\n\n // Define the message handler for incoming messages.\n const messageHandler = async (topic: string, message: string): Promise<void> => {\n parentPort?.postMessage({\n command: \"input\",\n topic: topic,\n message: message,\n });\n };\n\n // Create an instance of ThrottledSubscriber.\n this.subscriber = new ThrottledSubscriber(\n subscribeThrottlingDelay,\n messageHandler,\n persistToDisk,\n join(basePath, \"/workerQueue/\", \"throttled-subscriber-queue.json\"),\n instanceName,\n subscriberActive,\n );\n\n // Set up the message listener for commands from the main thread.\n this.initializeMessageListener();\n }\n\n /**\n * Listen for incoming messages from the main thread and process them.\n */\n private initializeMessageListener(): void {\n parentPort?.on(\"message\", async (msg) => {\n if (msg && msg.command === \"enqueue\" && msg.id && msg.topic && msg.message !== undefined) {\n try {\n const publishPromise = this.publisher.enqueueOrThrow(msg.topic, msg.message, msg.id, msg.options);\n parentPort?.postMessage({\n command: \"enqueueAccepted\",\n id: msg.id,\n status: \"accepted\",\n });\n void publishPromise\n .then(() => {\n parentPort?.postMessage({\n command: \"publishResult\",\n id: msg.id,\n status: \"success\",\n topic: msg.topic,\n });\n })\n .catch((error: any) => {\n parentPort?.postMessage({\n command: \"publishResult\",\n id: msg.id,\n status: \"error\",\n topic: msg.topic,\n error: error?.message ?? String(error),\n });\n });\n } catch (error: any) {\n parentPort?.postMessage({\n command: \"enqueueAccepted\",\n id: msg.id,\n status: \"error\",\n error: error?.message ?? String(error),\n });\n }\n } else if (msg && msg.command === \"subscribeAsync\" && msg.topics) {\n this.mqttProxy.subscribeAsync(msg.topics);\n } else if (msg && msg.command === \"unsubscribeAsync\" && msg.topics) {\n this.mqttProxy.unsubscribeAsync(msg.topics);\n } else if (msg && msg.command === \"setPublisherActive\") {\n this.publisher.becomeActive({batchSize: msg?.batchSize, referenceHash: msg?.referenceHash});\n } else if (msg && msg.command === \"setPublisherPassive\") {\n const snapshot = await this.publisher.becomePassive(3);\n parentPort?.postMessage({\n command: \"handover_publisher\",\n ...snapshot\n }); \n } else if (msg && msg.command === \"setSubscriberActive\") {\n this.subscriber.becomeActive({batchSize: msg?.batchSize, referenceHash: msg?.referenceHash});\n } else if (msg && msg.command === \"setSubscriberPassive\") {\n const snapshot = await this.subscriber.becomePassive(3);\n parentPort?.postMessage({\n command: \"handover_subscriber\",\n ...snapshot\n }); \n }\n });\n }\n\n /**\n * Get the state of the publisher.\n */\n public getPublisherState(): boolean {\n return this.publisher.getState();\n }\n /**\n * Get the state of the subscriber.\n */\n public getSubscriberState(): boolean {\n return this.subscriber.getState();\n }\n\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"throttled-queue.d.ts","sourceRoot":"","sources":["../../src/uns-mqtt/throttled-queue.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"throttled-queue.d.ts","sourceRoot":"","sources":["../../src/uns-mqtt/throttled-queue.ts"],"names":[],"mappings":"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"}
@@ -185,8 +185,13 @@ export class ThrottledPublisher extends ThrottledQueue {
185
185
  * Enqueue a publish request.
186
186
  */
187
187
  enqueue(topic, message, id, options) {
188
- this.assertCanAcceptPublish();
189
- return this.enqueueAcceptedPublish(topic, message, id, options);
188
+ try {
189
+ this.assertCanAcceptPublish();
190
+ return this.enqueueAcceptedPublish(topic, message, id, options);
191
+ }
192
+ catch (error) {
193
+ return Promise.reject(error);
194
+ }
190
195
  }
191
196
  /**
192
197
  * Enqueue a publish request and throw synchronously if the bounded queue is full.
@@ -1 +1 @@
1
- {"version":3,"file":"throttled-queue.js","sourceRoot":"","sources":["../../src/uns-mqtt/throttled-queue.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"crypto\";\r\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\r\nimport { IClientPublishOptions } from \"mqtt\";\r\nimport { join } from \"path\";\r\n\r\nimport { basePath } from \"../base-path.js\";\r\nimport logger from \"../logger.js\";\r\n\r\n/**\r\n * Abstract base class that encapsulates common functionality for managing\r\n * a throttled in‑memory queue with an optional disk persistence.\r\n */\r\nabstract class ThrottledQueue<T> {\r\n protected queue: T[] = [];\r\n protected lastProcessedItems: T[] = [];\r\n protected isProcessing = false;\r\n protected inFlight = 0;\r\n protected maxConcurrency: number;\r\n public delay: number;\r\n protected persistToDisk: boolean;\r\n protected persistenceFilePath: string;\r\n protected previousLoggedSize = 0;\r\n protected instanceName: string;\r\n protected active: boolean = true;\r\n private inactiveLogSent = false;\r\n\r\n constructor(delay: number, persistToDisk: boolean, instanceName: string, maxConcurrency: number = 1) {\r\n this.delay = delay;\r\n this.persistToDisk = persistToDisk;\r\n this.instanceName = instanceName;\r\n this.maxConcurrency = Math.max(1, maxConcurrency);\r\n\r\n if (this.persistToDisk) {\r\n this.loadQueueFromDisk();\r\n }\r\n }\r\n\r\n /**\r\n * Process the queue items one at a time with a delay between each.\r\n */\r\n protected async processQueue(): Promise<void> {\r\n if (this.isProcessing) return;\r\n\r\n if (!this.active) {\r\n if (!this.inactiveLogSent) {\r\n logger.info(`${this.instanceName} - Queue is not active. Exiting processQueue.`);\r\n this.inactiveLogSent = true;\r\n }\r\n this.isProcessing = false;\r\n return;\r\n }\r\n this.isProcessing = true;\r\n // Reset the flag when processing actually starts.\r\n this.inactiveLogSent = false;\r\n\r\n try {\r\n while (this.queue.length > 0 && this.inFlight < this.maxConcurrency) {\r\n // Check if the queue is active\r\n if (!this.active) {\r\n logger.info(`${this.instanceName} - Queue processing paused.`);\r\n return; // Exit the loop and stop processing\r\n }\r\n\r\n const item = this.queue.shift();\r\n if (!item) {\r\n continue;\r\n }\r\n\r\n this.inFlight += 1;\r\n void this.processItemWithBookkeeping(item);\r\n\r\n if (this.persistToDisk) {\r\n this.saveQueueToDisk();\r\n }\r\n\r\n this.logQueueSize();\r\n\r\n if (this.delay > 0 && this.queue.length > 0 && this.inFlight < this.maxConcurrency) {\r\n await new Promise((resolve) => setTimeout(resolve, this.delay));\r\n }\r\n }\r\n } finally {\r\n this.isProcessing = false;\r\n if (this.active && this.queue.length > 0 && this.inFlight < this.maxConcurrency) {\r\n void this.processQueue();\r\n }\r\n }\r\n }\r\n\r\n private async processItemWithBookkeeping(item: T): Promise<void> {\r\n try {\r\n await this.processItem(item);\r\n // Only store 10 last processed items\r\n if (this.lastProcessedItems.length >= 10) {\r\n this.lastProcessedItems.shift();\r\n }\r\n // Store the last processed item\r\n this.lastProcessedItems.push(item);\r\n } catch (error) {\r\n // Specific error handling can be done in the subclass if needed.\r\n logger.error(`${this.instanceName} - Error processing item: ${(error as Error).message}`);\r\n } finally {\r\n this.inFlight = Math.max(0, this.inFlight - 1);\r\n\r\n if (this.persistToDisk) {\r\n this.saveQueueToDisk();\r\n }\r\n\r\n this.logQueueSize();\r\n\r\n // Check if the queue is active\r\n if (this.active && this.queue.length > 0) {\r\n void this.processQueue();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Log changes to the queue size at significant thresholds.\r\n */\r\n protected logQueueSize(): void {\r\n const className = `${this.constructor.name.includes(\"Publisher\") ? \"Publisher\" : this.constructor.name.includes(\"Subscriber\") ? \"Subscriber\" : \"Unknown\"}`;\r\n const pendingCount = this.getPendingCount();\r\n if (\r\n pendingCount > 1\r\n && pendingCount > this.previousLoggedSize\r\n && Math.floor(pendingCount / 100) > Math.floor(this.previousLoggedSize / 100)\r\n ) {\r\n logger.info(`${this.instanceName} - ${className} queue size length is ${pendingCount}.`);\r\n this.previousLoggedSize = pendingCount;\r\n } else if (pendingCount === 0 && this.previousLoggedSize > 0) {\r\n logger.info(`${this.instanceName} - ${className} queue is empty.`);\r\n this.previousLoggedSize = 0;\r\n }\r\n }\r\n\r\n protected getPendingCount(): number {\r\n return this.queue.length + this.inFlight;\r\n }\r\n\r\n /**\r\n * Save the current queue to disk.\r\n */\r\n protected saveQueueToDisk(): void {\r\n try {\r\n const queueData = this.queue.map((item) => this.serializeItem(item));\r\n const dir = join(this.persistenceFilePath, \"..\");\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true });\r\n }\r\n writeFileSync(this.persistenceFilePath, JSON.stringify(queueData, null, 2));\r\n logger.debug(`${this.instanceName} - Queue saved to disk.`);\r\n } catch (error: any) {\r\n logger.error(`${this.instanceName} - Error saving queue to disk: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Load the queue from disk.\r\n */\r\n protected loadQueueFromDisk(): void {\r\n try {\r\n if (existsSync(this.persistenceFilePath)) {\r\n const queueData = JSON.parse(readFileSync(this.persistenceFilePath, \"utf8\"));\r\n this.queue = queueData.map((data: any) => this.deserializeItem(data));\r\n logger.info(`${this.instanceName} - Queue loaded from disk.`);\r\n }\r\n } catch (error: any) {\r\n logger.error(`${this.instanceName} - Error loading queue from disk: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Process a single queue item.\r\n */\r\n protected abstract processItem(item: T): Promise<void>;\r\n\r\n /**\r\n * Serialize a queue item for persistence.\r\n */\r\n protected abstract serializeItem(item: T): any;\r\n\r\n /**\r\n * Deserialize persisted data into a queue item.\r\n */\r\n protected abstract deserializeItem(data: any): T;\r\n}\r\n\r\n/**\r\n * Interface representing a queued publish item.\r\n */\r\ninterface PublisherQueueItem {\r\n topic: string;\r\n message: string;\r\n id: string;\r\n options?: IClientPublishOptions;\r\n resolve: () => void;\r\n reject: (err: any) => void;\r\n}\r\n\r\n/**\r\n * ThrottledPublisher: manages a queue of outgoing publish requests,\r\n * sending one message at a time using a provided publish function.\r\n */\r\nexport class ThrottledPublisher extends ThrottledQueue<PublisherQueueItem> {\n private publishFunction: (topic: string, message: string, id: string, options?: IClientPublishOptions) => Promise<void>;\r\n private maxPendingPublishes?: number;\r\n\r\n /**\r\n * @param delay Delay between messages in milliseconds.\r\n * @param publishFunction Function to perform the actual publish.\r\n * @param persistToDisk Whether to persist the queue to disk.\r\n * @param persistenceFilePath File path for queue persistence.\r\n * @param instanceName Unique instance name for logging.\r\n */\r\n constructor(\r\n delay: number,\r\n publishFunction: (topic: string, message: string, id: string, options?: IClientPublishOptions) => Promise<void>,\r\n persistToDisk: boolean = false,\r\n persistenceFilePath: string = join(basePath, \"/publisherQueue/\", \"throttled-publisher-queue.json\"),\r\n instanceName: string,\r\n active: boolean,\r\n maxConcurrency: number = 1,\r\n maxPendingPublishes?: number,\r\n ) {\r\n super(delay, persistToDisk, instanceName, maxConcurrency);\r\n this.persistenceFilePath = persistenceFilePath;\r\n this.publishFunction = publishFunction;\r\n this.active = active;\r\n this.maxPendingPublishes = maxPendingPublishes;\r\n if (active) {\r\n logger.info(`${this.instanceName} - Publisher is active.`);\r\n } else {\r\n logger.info(`${this.instanceName} - Publisher is passive.`);\r\n }\r\n }\r\n\r\n /**\n * Enqueue a publish request.\n */\n public enqueue(topic: string, message: string, id: string, options?: IClientPublishOptions): Promise<void> {\n this.assertCanAcceptPublish();\n return this.enqueueAcceptedPublish(topic, message, id, options);\n }\n\n /**\n * Enqueue a publish request and throw synchronously if the bounded queue is full.\n */\n public enqueueOrThrow(topic: string, message: string, id: string, options?: IClientPublishOptions): Promise<void> {\n this.assertCanAcceptPublish();\n return this.enqueueAcceptedPublish(topic, message, id, options);\n }\n\n private assertCanAcceptPublish(): void {\n if (this.maxPendingPublishes !== undefined && this.getPendingCount() >= this.maxPendingPublishes) {\n throw new Error(`${this.instanceName} - Publisher queue is full (${this.maxPendingPublishes}).`);\n }\n }\n\n private enqueueAcceptedPublish(topic: string, message: string, id: string, options?: IClientPublishOptions): Promise<void> {\n return new Promise((resolve, reject) => {\n this.queue.push({ topic, message, id, options, resolve, reject });\n\n // Trigger logging after a new message is added.\n this.logQueueSize(); \r\n\r\n if (this.persistToDisk) {\r\n this.saveQueueToDisk();\r\n }\r\n\r\n if (this.active) {\r\n this.processQueue();\r\n }\r\n });\r\n }\r\n\r\n private computeHashForBatch(messages: any[]): string {\r\n const data = JSON.stringify(messages);\r\n return createHash(\"sha256\").update(data).digest(\"hex\");\r\n }\r\n\r\n /**\r\n * Switch the publisher to a passive state and return a snapshot\r\n */\r\n public becomeActive(snapshot: { referenceHash: string; batchSize: number }): void {\r\n // If snapshot is empty (batchSize is zero), start processing from the beginning.\r\n if (snapshot.batchSize === 0 || snapshot.batchSize === undefined || snapshot.referenceHash === undefined) {\r\n this.active = true;\r\n logger.info(`${this.instanceName} - Publisher became active.`);\r\n this.processQueue();\r\n return;\r\n }\r\n\r\n const { referenceHash, batchSize } = snapshot;\r\n let resumeIndex = -1;\r\n\r\n // Use batchSize as the window length.\r\n for (let i = 0; i <= this.queue.length - batchSize; i++) {\r\n const currentBatch = this.queue.slice(i, i + batchSize);\r\n const currentHash = this.computeHashForBatch(currentBatch);\r\n if (currentHash === referenceHash) {\r\n resumeIndex = i + batchSize; // resume immediately after the matched batch\r\n break;\r\n }\r\n }\r\n\r\n if (resumeIndex !== -1) {\r\n // Adjust the queue so that processing resumes after the matching batch.\r\n this.queue = this.queue.slice(resumeIndex);\r\n logger.info(`${this.instanceName} - Publisher resumed from the matched snapshot position.`);\r\n } else if (this.queue.length > 0) {\r\n // Log info message and process the entire queue if no match is found.\r\n logger.info(`${this.instanceName} - No matching batch found during resume; processing the entire publisher's queue.`);\r\n }\r\n\r\n this.active = true;\r\n logger.info(`${this.instanceName} - Publisher became active.`);\r\n this.processQueue();\r\n }\r\n\r\n /**\r\n * Switch the publisher to a passive state and return a snapshot\r\n */\r\n public async becomePassive(n: number): Promise<{ referenceHash: string; batchSize: number; }> {\r\n this.active = false;\r\n logger.info(`${this.instanceName} - Publisher became passive.`);\r\n const batch = this.queue.slice(-n);\r\n const batchSize = batch.length;\r\n const referenceHash = this.computeHashForBatch(batch);\r\n if (batchSize > 0) {\r\n logger.info(`${this.instanceName} - Publisher batch reference hash: ${referenceHash}, size: ${batchSize}`);\r\n }\r\n return { referenceHash, batchSize };\r\n }\r\n\r\n public getState(): boolean {\r\n return this.active;\r\n }\r\n\r\n /**\r\n * Process a single publish request.\r\n */\r\n protected async processItem(item: PublisherQueueItem): Promise<void> {\r\n try {\r\n await this.publishFunction(item.topic, item.message, item.id, item.options);\r\n item.resolve();\r\n } catch (error) {\r\n item.reject(error);\r\n }\r\n }\r\n\r\n /**\r\n * Serialize a publish request for persistence.\r\n */\r\n protected serializeItem(item: PublisherQueueItem): any {\r\n return {\r\n topic: item.topic,\r\n message: item.message,\r\n id: item.id,\r\n options: item.options,\r\n };\r\n }\r\n\r\n /**\r\n * Deserialize persisted data into a publish request.\r\n */\r\n protected deserializeItem(data: any): PublisherQueueItem {\r\n return {\r\n topic: data.topic,\r\n message: data.message,\r\n id: data.id,\r\n options: data.options,\r\n resolve: () => {},\r\n reject: (err: any) => logger.error(`${this.instanceName} - Error processing queued publish item: ${err.message}`),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Interface representing a queued subscribe item.\r\n */\r\ninterface SubscriberQueueItem {\r\n topic: string;\r\n message: string;\r\n timestamp: number;\r\n}\r\n\r\n/**\r\n * ThrottledSubscriber: manages a queue of incoming messages and processes\r\n * them one at a time using a provided message handler.\r\n */\r\nexport class ThrottledSubscriber extends ThrottledQueue<SubscriberQueueItem> {\r\n private messageHandler: (topic: string, message: string) => Promise<void>;\r\n\r\n /**\r\n * @param delay Delay between processing messages in milliseconds.\r\n * @param messageHandler Function to process incoming messages.\r\n * @param persistToDisk Whether to persist the queue to disk.\r\n * @param persistenceFilePath File path for queue persistence.\r\n * @param instanceName Unique instance name for logging.\r\n */\r\n constructor(\r\n delay: number,\r\n messageHandler: (topic: string, message: string) => Promise<void>,\r\n persistToDisk: boolean = false,\r\n persistenceFilePath: string = join(basePath, \"/subscriberQueue/\", \"throttled-subscriber-queue.json\"),\r\n instanceName: string,\r\n active: boolean,\r\n ) {\r\n super(delay, persistToDisk, instanceName);\r\n this.persistenceFilePath = persistenceFilePath;\r\n this.messageHandler = messageHandler;\r\n this.active = active;\r\n if (active) {\r\n logger.info(`${this.instanceName} - Subscriber is active.`);\r\n } else {\r\n logger.info(`${this.instanceName} - Subscriber is passive.`);\r\n }\r\n }\r\n\r\n /**\r\n * Enqueue subscribe messages for processing.\r\n */\r\n public enqueue(topic: string, message: string): void {\r\n this.queue.push({ topic, message, timestamp: Date.now() });\r\n \r\n // Trigger logging after a new message is added.\r\n this.logQueueSize();\r\n \r\n if (this.persistToDisk) {\r\n this.saveQueueToDisk();\r\n }\r\n\r\n if (this.active) {\r\n this.processQueue();\r\n }\r\n }\r\n\r\n /**\r\n * Process a single subscribe message.\r\n */\r\n protected async processItem(item: SubscriberQueueItem): Promise<void> {\r\n await this.messageHandler(item.topic, item.message);\r\n }\r\n\r\n /**\r\n * Serialize a subscribe message for persistence.\r\n */\r\n protected serializeItem(item: SubscriberQueueItem): any {\r\n return {\r\n message: item.message,\r\n };\r\n }\r\n\r\n /**\r\n * Deserialize persisted data into a subscribe message.\r\n */\r\n protected deserializeItem(data: any): SubscriberQueueItem {\r\n return {\r\n topic: data.topic,\r\n message: data.message,\r\n timestamp: data.timestamp,\r\n };\r\n }\r\n\r\n /**\r\n * Get the current state of the subscriber (active or passive).\r\n */\r\n public getState(): boolean {\r\n return this.active;\r\n }\r\n\r\n /**\r\n * Computes a SHA‑256 hash for a given batch of subscriber items.\r\n */\r\n private computeHashForBatch(messages: SubscriberQueueItem[]): string {\r\n const data = JSON.stringify(messages.map((item) => this.serializeItem(item)));\r\n return createHash(\"sha256\").update(data).digest(\"hex\");\r\n }\r\n\r\n /**\r\n * Switch the subscriber to a passive state and return a snapshot.\r\n */\r\n public async becomePassive(n: number): Promise<{ referenceHash: string; batchSize: number; }> {\r\n this.active = false;\r\n logger.info(`${this.instanceName} - Subscriber is passive.`);\r\n const batch = this.lastProcessedItems.slice(-n);\r\n const batchSize = batch.length;\r\n const referenceHash = this.computeHashForBatch(batch);\r\n if (batchSize > 0) {\r\n logger.info(`${this.instanceName} - Subscriber batch reference hash: ${referenceHash}, size: ${batchSize}`);\r\n }\r\n return { referenceHash, batchSize };\r\n }\r\n\r\n /**\r\n * Switch the subscriber to an active state and resume processing.\r\n */\r\n public becomeActive(snapshot: { referenceHash: string; batchSize: number }): void {\r\n // If snapshot is empty (batchSize is zero), start processing from the beginning.\r\n if (snapshot.batchSize === 0 || snapshot.batchSize === undefined || snapshot.referenceHash === undefined) {\r\n this.active = true;\r\n logger.info(`${this.instanceName} - Subscriber became active.`); \r\n this.processQueue();\r\n return;\r\n }\r\n\r\n const { referenceHash, batchSize } = snapshot;\r\n let resumeIndex = -1;\r\n\r\n // Use batchSize as the window length.\r\n for (let i = 0; i <= this.queue.length - batchSize; i++) {\r\n const currentBatch = this.queue.slice(i, i + batchSize);\r\n const currentHash = this.computeHashForBatch(currentBatch);\r\n if (currentHash === referenceHash) {\r\n resumeIndex = i + batchSize; // resume immediately after the matched batch\r\n break;\r\n }\r\n }\r\n\r\n if (resumeIndex !== -1) {\r\n // Adjust the queue so that processing resumes after the matching batch.\r\n const queueSlice = this.queue.slice(resumeIndex); \r\n this.queue = queueSlice;\r\n logger.info(`${this.instanceName} - Subscriber resumed from the matched snapshot position.`);\r\n } else if (this.queue.length > 0) {\r\n // Log info message and process the entire queue if no match is found.\r\n logger.info(`${this.instanceName} - No matching batch found during resume; processing the entire subscriber's queue.`);\r\n }\r\n\r\n this.active = true;\r\n logger.info(`${this.instanceName} - Subscriber became active.`); \r\n this.processQueue();\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"throttled-queue.js","sourceRoot":"","sources":["../../src/uns-mqtt/throttled-queue.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { IClientPublishOptions } from \"mqtt\";\nimport { join } from \"path\";\n\nimport { basePath } from \"../base-path.js\";\nimport logger from \"../logger.js\";\n\n/**\n * Abstract base class that encapsulates common functionality for managing\n * a throttled in‑memory queue with an optional disk persistence.\n */\nabstract class ThrottledQueue<T> {\n protected queue: T[] = [];\n protected lastProcessedItems: T[] = [];\n protected isProcessing = false;\n protected inFlight = 0;\n protected maxConcurrency: number;\n public delay: number;\n protected persistToDisk: boolean;\n protected persistenceFilePath: string;\n protected previousLoggedSize = 0;\n protected instanceName: string;\n protected active: boolean = true;\n private inactiveLogSent = false;\n\n constructor(delay: number, persistToDisk: boolean, instanceName: string, maxConcurrency: number = 1) {\n this.delay = delay;\n this.persistToDisk = persistToDisk;\n this.instanceName = instanceName;\n this.maxConcurrency = Math.max(1, maxConcurrency);\n\n if (this.persistToDisk) {\n this.loadQueueFromDisk();\n }\n }\n\n /**\n * Process the queue items one at a time with a delay between each.\n */\n protected async processQueue(): Promise<void> {\n if (this.isProcessing) return;\n\n if (!this.active) {\n if (!this.inactiveLogSent) {\n logger.info(`${this.instanceName} - Queue is not active. Exiting processQueue.`);\n this.inactiveLogSent = true;\n }\n this.isProcessing = false;\n return;\n }\n this.isProcessing = true;\n // Reset the flag when processing actually starts.\n this.inactiveLogSent = false;\n\n try {\n while (this.queue.length > 0 && this.inFlight < this.maxConcurrency) {\n // Check if the queue is active\n if (!this.active) {\n logger.info(`${this.instanceName} - Queue processing paused.`);\n return; // Exit the loop and stop processing\n }\n\n const item = this.queue.shift();\n if (!item) {\n continue;\n }\n\n this.inFlight += 1;\n void this.processItemWithBookkeeping(item);\n\n if (this.persistToDisk) {\n this.saveQueueToDisk();\n }\n\n this.logQueueSize();\n\n if (this.delay > 0 && this.queue.length > 0 && this.inFlight < this.maxConcurrency) {\n await new Promise((resolve) => setTimeout(resolve, this.delay));\n }\n }\n } finally {\n this.isProcessing = false;\n if (this.active && this.queue.length > 0 && this.inFlight < this.maxConcurrency) {\n void this.processQueue();\n }\n }\n }\n\n private async processItemWithBookkeeping(item: T): Promise<void> {\n try {\n await this.processItem(item);\n // Only store 10 last processed items\n if (this.lastProcessedItems.length >= 10) {\n this.lastProcessedItems.shift();\n }\n // Store the last processed item\n this.lastProcessedItems.push(item);\n } catch (error) {\n // Specific error handling can be done in the subclass if needed.\n logger.error(`${this.instanceName} - Error processing item: ${(error as Error).message}`);\n } finally {\n this.inFlight = Math.max(0, this.inFlight - 1);\n\n if (this.persistToDisk) {\n this.saveQueueToDisk();\n }\n\n this.logQueueSize();\n\n // Check if the queue is active\n if (this.active && this.queue.length > 0) {\n void this.processQueue();\n }\n }\n }\n\n /**\n * Log changes to the queue size at significant thresholds.\n */\n protected logQueueSize(): void {\n const className = `${this.constructor.name.includes(\"Publisher\") ? \"Publisher\" : this.constructor.name.includes(\"Subscriber\") ? \"Subscriber\" : \"Unknown\"}`;\n const pendingCount = this.getPendingCount();\n if (\n pendingCount > 1\n && pendingCount > this.previousLoggedSize\n && Math.floor(pendingCount / 100) > Math.floor(this.previousLoggedSize / 100)\n ) {\n logger.info(`${this.instanceName} - ${className} queue size length is ${pendingCount}.`);\n this.previousLoggedSize = pendingCount;\n } else if (pendingCount === 0 && this.previousLoggedSize > 0) {\n logger.info(`${this.instanceName} - ${className} queue is empty.`);\n this.previousLoggedSize = 0;\n }\n }\n\n protected getPendingCount(): number {\n return this.queue.length + this.inFlight;\n }\n\n /**\n * Save the current queue to disk.\n */\n protected saveQueueToDisk(): void {\n try {\n const queueData = this.queue.map((item) => this.serializeItem(item));\n const dir = join(this.persistenceFilePath, \"..\");\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(this.persistenceFilePath, JSON.stringify(queueData, null, 2));\n logger.debug(`${this.instanceName} - Queue saved to disk.`);\n } catch (error: any) {\n logger.error(`${this.instanceName} - Error saving queue to disk: ${error.message}`);\n }\n }\n\n /**\n * Load the queue from disk.\n */\n protected loadQueueFromDisk(): void {\n try {\n if (existsSync(this.persistenceFilePath)) {\n const queueData = JSON.parse(readFileSync(this.persistenceFilePath, \"utf8\"));\n this.queue = queueData.map((data: any) => this.deserializeItem(data));\n logger.info(`${this.instanceName} - Queue loaded from disk.`);\n }\n } catch (error: any) {\n logger.error(`${this.instanceName} - Error loading queue from disk: ${error.message}`);\n }\n }\n\n /**\n * Process a single queue item.\n */\n protected abstract processItem(item: T): Promise<void>;\n\n /**\n * Serialize a queue item for persistence.\n */\n protected abstract serializeItem(item: T): any;\n\n /**\n * Deserialize persisted data into a queue item.\n */\n protected abstract deserializeItem(data: any): T;\n}\n\n/**\n * Interface representing a queued publish item.\n */\ninterface PublisherQueueItem {\n topic: string;\n message: string;\n id: string;\n options?: IClientPublishOptions;\n resolve: () => void;\n reject: (err: any) => void;\n}\n\n/**\n * ThrottledPublisher: manages a queue of outgoing publish requests,\n * sending one message at a time using a provided publish function.\n */\nexport class ThrottledPublisher extends ThrottledQueue<PublisherQueueItem> {\n private publishFunction: (topic: string, message: string, id: string, options?: IClientPublishOptions) => Promise<void>;\n private maxPendingPublishes?: number;\n\n /**\n * @param delay Delay between messages in milliseconds.\n * @param publishFunction Function to perform the actual publish.\n * @param persistToDisk Whether to persist the queue to disk.\n * @param persistenceFilePath File path for queue persistence.\n * @param instanceName Unique instance name for logging.\n */\n constructor(\n delay: number,\n publishFunction: (topic: string, message: string, id: string, options?: IClientPublishOptions) => Promise<void>,\n persistToDisk: boolean = false,\n persistenceFilePath: string = join(basePath, \"/publisherQueue/\", \"throttled-publisher-queue.json\"),\n instanceName: string,\n active: boolean,\n maxConcurrency: number = 1,\n maxPendingPublishes?: number,\n ) {\n super(delay, persistToDisk, instanceName, maxConcurrency);\n this.persistenceFilePath = persistenceFilePath;\n this.publishFunction = publishFunction;\n this.active = active;\n this.maxPendingPublishes = maxPendingPublishes;\n if (active) {\n logger.info(`${this.instanceName} - Publisher is active.`);\n } else {\n logger.info(`${this.instanceName} - Publisher is passive.`);\n }\n }\n\n /**\n * Enqueue a publish request.\n */\n public enqueue(topic: string, message: string, id: string, options?: IClientPublishOptions): Promise<void> {\n try {\n this.assertCanAcceptPublish();\n return this.enqueueAcceptedPublish(topic, message, id, options);\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n /**\n * Enqueue a publish request and throw synchronously if the bounded queue is full.\n */\n public enqueueOrThrow(topic: string, message: string, id: string, options?: IClientPublishOptions): Promise<void> {\n this.assertCanAcceptPublish();\n return this.enqueueAcceptedPublish(topic, message, id, options);\n }\n\n private assertCanAcceptPublish(): void {\n if (this.maxPendingPublishes !== undefined && this.getPendingCount() >= this.maxPendingPublishes) {\n throw new Error(`${this.instanceName} - Publisher queue is full (${this.maxPendingPublishes}).`);\n }\n }\n\n private enqueueAcceptedPublish(topic: string, message: string, id: string, options?: IClientPublishOptions): Promise<void> {\n return new Promise((resolve, reject) => {\n this.queue.push({ topic, message, id, options, resolve, reject });\n\n // Trigger logging after a new message is added.\n this.logQueueSize(); \n\n if (this.persistToDisk) {\n this.saveQueueToDisk();\n }\n\n if (this.active) {\n this.processQueue();\n }\n });\n }\n\n private computeHashForBatch(messages: any[]): string {\n const data = JSON.stringify(messages);\n return createHash(\"sha256\").update(data).digest(\"hex\");\n }\n\n /**\n * Switch the publisher to a passive state and return a snapshot\n */\n public becomeActive(snapshot: { referenceHash: string; batchSize: number }): void {\n // If snapshot is empty (batchSize is zero), start processing from the beginning.\n if (snapshot.batchSize === 0 || snapshot.batchSize === undefined || snapshot.referenceHash === undefined) {\n this.active = true;\n logger.info(`${this.instanceName} - Publisher became active.`);\n this.processQueue();\n return;\n }\n\n const { referenceHash, batchSize } = snapshot;\n let resumeIndex = -1;\n\n // Use batchSize as the window length.\n for (let i = 0; i <= this.queue.length - batchSize; i++) {\n const currentBatch = this.queue.slice(i, i + batchSize);\n const currentHash = this.computeHashForBatch(currentBatch);\n if (currentHash === referenceHash) {\n resumeIndex = i + batchSize; // resume immediately after the matched batch\n break;\n }\n }\n\n if (resumeIndex !== -1) {\n // Adjust the queue so that processing resumes after the matching batch.\n this.queue = this.queue.slice(resumeIndex);\n logger.info(`${this.instanceName} - Publisher resumed from the matched snapshot position.`);\n } else if (this.queue.length > 0) {\n // Log info message and process the entire queue if no match is found.\n logger.info(`${this.instanceName} - No matching batch found during resume; processing the entire publisher's queue.`);\n }\n\n this.active = true;\n logger.info(`${this.instanceName} - Publisher became active.`);\n this.processQueue();\n }\n\n /**\n * Switch the publisher to a passive state and return a snapshot\n */\n public async becomePassive(n: number): Promise<{ referenceHash: string; batchSize: number; }> {\n this.active = false;\n logger.info(`${this.instanceName} - Publisher became passive.`);\n const batch = this.queue.slice(-n);\n const batchSize = batch.length;\n const referenceHash = this.computeHashForBatch(batch);\n if (batchSize > 0) {\n logger.info(`${this.instanceName} - Publisher batch reference hash: ${referenceHash}, size: ${batchSize}`);\n }\n return { referenceHash, batchSize };\n }\n\n public getState(): boolean {\n return this.active;\n }\n\n /**\n * Process a single publish request.\n */\n protected async processItem(item: PublisherQueueItem): Promise<void> {\n try {\n await this.publishFunction(item.topic, item.message, item.id, item.options);\n item.resolve();\n } catch (error) {\n item.reject(error);\n }\n }\n\n /**\n * Serialize a publish request for persistence.\n */\n protected serializeItem(item: PublisherQueueItem): any {\n return {\n topic: item.topic,\n message: item.message,\n id: item.id,\n options: item.options,\n };\n }\n\n /**\n * Deserialize persisted data into a publish request.\n */\n protected deserializeItem(data: any): PublisherQueueItem {\n return {\n topic: data.topic,\n message: data.message,\n id: data.id,\n options: data.options,\n resolve: () => {},\n reject: (err: any) => logger.error(`${this.instanceName} - Error processing queued publish item: ${err.message}`),\n };\n }\n}\n\n/**\n * Interface representing a queued subscribe item.\n */\ninterface SubscriberQueueItem {\n topic: string;\n message: string;\n timestamp: number;\n}\n\n/**\n * ThrottledSubscriber: manages a queue of incoming messages and processes\n * them one at a time using a provided message handler.\n */\nexport class ThrottledSubscriber extends ThrottledQueue<SubscriberQueueItem> {\n private messageHandler: (topic: string, message: string) => Promise<void>;\n\n /**\n * @param delay Delay between processing messages in milliseconds.\n * @param messageHandler Function to process incoming messages.\n * @param persistToDisk Whether to persist the queue to disk.\n * @param persistenceFilePath File path for queue persistence.\n * @param instanceName Unique instance name for logging.\n */\n constructor(\n delay: number,\n messageHandler: (topic: string, message: string) => Promise<void>,\n persistToDisk: boolean = false,\n persistenceFilePath: string = join(basePath, \"/subscriberQueue/\", \"throttled-subscriber-queue.json\"),\n instanceName: string,\n active: boolean,\n ) {\n super(delay, persistToDisk, instanceName);\n this.persistenceFilePath = persistenceFilePath;\n this.messageHandler = messageHandler;\n this.active = active;\n if (active) {\n logger.info(`${this.instanceName} - Subscriber is active.`);\n } else {\n logger.info(`${this.instanceName} - Subscriber is passive.`);\n }\n }\n\n /**\n * Enqueue subscribe messages for processing.\n */\n public enqueue(topic: string, message: string): void {\n this.queue.push({ topic, message, timestamp: Date.now() });\n \n // Trigger logging after a new message is added.\n this.logQueueSize();\n \n if (this.persistToDisk) {\n this.saveQueueToDisk();\n }\n\n if (this.active) {\n this.processQueue();\n }\n }\n\n /**\n * Process a single subscribe message.\n */\n protected async processItem(item: SubscriberQueueItem): Promise<void> {\n await this.messageHandler(item.topic, item.message);\n }\n\n /**\n * Serialize a subscribe message for persistence.\n */\n protected serializeItem(item: SubscriberQueueItem): any {\n return {\n message: item.message,\n };\n }\n\n /**\n * Deserialize persisted data into a subscribe message.\n */\n protected deserializeItem(data: any): SubscriberQueueItem {\n return {\n topic: data.topic,\n message: data.message,\n timestamp: data.timestamp,\n };\n }\n\n /**\n * Get the current state of the subscriber (active or passive).\n */\n public getState(): boolean {\n return this.active;\n }\n\n /**\n * Computes a SHA‑256 hash for a given batch of subscriber items.\n */\n private computeHashForBatch(messages: SubscriberQueueItem[]): string {\n const data = JSON.stringify(messages.map((item) => this.serializeItem(item)));\n return createHash(\"sha256\").update(data).digest(\"hex\");\n }\n\n /**\n * Switch the subscriber to a passive state and return a snapshot.\n */\n public async becomePassive(n: number): Promise<{ referenceHash: string; batchSize: number; }> {\n this.active = false;\n logger.info(`${this.instanceName} - Subscriber is passive.`);\n const batch = this.lastProcessedItems.slice(-n);\n const batchSize = batch.length;\n const referenceHash = this.computeHashForBatch(batch);\n if (batchSize > 0) {\n logger.info(`${this.instanceName} - Subscriber batch reference hash: ${referenceHash}, size: ${batchSize}`);\n }\n return { referenceHash, batchSize };\n }\n\n /**\n * Switch the subscriber to an active state and resume processing.\n */\n public becomeActive(snapshot: { referenceHash: string; batchSize: number }): void {\n // If snapshot is empty (batchSize is zero), start processing from the beginning.\n if (snapshot.batchSize === 0 || snapshot.batchSize === undefined || snapshot.referenceHash === undefined) {\n this.active = true;\n logger.info(`${this.instanceName} - Subscriber became active.`); \n this.processQueue();\n return;\n }\n\n const { referenceHash, batchSize } = snapshot;\n let resumeIndex = -1;\n\n // Use batchSize as the window length.\n for (let i = 0; i <= this.queue.length - batchSize; i++) {\n const currentBatch = this.queue.slice(i, i + batchSize);\n const currentHash = this.computeHashForBatch(currentBatch);\n if (currentHash === referenceHash) {\n resumeIndex = i + batchSize; // resume immediately after the matched batch\n break;\n }\n }\n\n if (resumeIndex !== -1) {\n // Adjust the queue so that processing resumes after the matching batch.\n const queueSlice = this.queue.slice(resumeIndex); \n this.queue = queueSlice;\n logger.info(`${this.instanceName} - Subscriber resumed from the matched snapshot position.`);\n } else if (this.queue.length > 0) {\n // Log info message and process the entire queue if no match is found.\n logger.info(`${this.instanceName} - No matching batch found during resume; processing the entire subscriber's queue.`);\n }\n\n this.active = true;\n logger.info(`${this.instanceName} - Subscriber became active.`); \n this.processQueue();\n }\n}\n"]}
@@ -32,6 +32,9 @@ export default class UnsMqttProxy extends UnsProxy {
32
32
  private deltaModeDeprecationWarned;
33
33
  private drainWaiters;
34
34
  private workerFailure;
35
+ private lifecycleState;
36
+ private stopPromise;
37
+ private expectedWorkerExit;
35
38
  constructor(mqttHost: string, processName: string, instanceName: string, unsParameters?: IUnsParameters, publisherActive?: boolean, subscriberActive?: boolean);
36
39
  /**
37
40
  * Resolve object identity from explicit fields or the tail of the topic path.
@@ -135,7 +138,9 @@ export default class UnsMqttProxy extends UnsProxy {
135
138
  * Stops the UnsProxy instance and cleans up resources.
136
139
  */
137
140
  stop(options?: UnsMqttProxyStopOptions): Promise<void>;
141
+ private performStop;
138
142
  private failPendingPublishes;
143
+ private rejectOutstandingPublishes;
139
144
  private notifyDrainWaiters;
140
145
  private removeDrainWaiter;
141
146
  }
@@ -1 +1 @@
1
- {"version":3,"file":"uns-mqtt-proxy.d.ts","sourceRoot":"","sources":["../../src/uns-mqtt/uns-mqtt-proxy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"uns-mqtt-proxy.d.ts","sourceRoot":"","sources":["../../src/uns-mqtt/uns-mqtt-proxy.ts"],"names":[],"mappings":"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"}
@@ -34,7 +34,7 @@ export default class UnsMqttProxy extends UnsProxy {
34
34
  lastValues = new Map();
35
35
  worker;
36
36
  pendingEnqueues = new Map();
37
- pendingPublishCompletions = 0;
37
+ pendingPublishCompletions = new Set();
38
38
  unsParameters;
39
39
  processStatusTopic;
40
40
  instanceName;
@@ -43,6 +43,9 @@ export default class UnsMqttProxy extends UnsProxy {
43
43
  deltaModeDeprecationWarned = false;
44
44
  drainWaiters = [];
45
45
  workerFailure = null;
46
+ lifecycleState = "running";
47
+ stopPromise = null;
48
+ expectedWorkerExit = false;
46
49
  constructor(mqttHost, processName, instanceName, unsParameters, publisherActive = false, subscriberActive = false) {
47
50
  super();
48
51
  this.instanceName = instanceName;
@@ -143,21 +146,19 @@ export default class UnsMqttProxy extends UnsProxy {
143
146
  if (msg && msg.command === "enqueueAccepted" && msg.id) {
144
147
  const pending = this.pendingEnqueues.get(msg.id);
145
148
  if (pending) {
149
+ this.pendingEnqueues.delete(msg.id);
146
150
  if (msg.status === "accepted") {
147
- this.pendingPublishCompletions += 1;
151
+ this.pendingPublishCompletions.add(msg.id);
148
152
  pending.resolve();
149
153
  }
150
154
  else {
151
155
  pending.reject(new Error(msg.error));
152
156
  }
153
- this.pendingEnqueues.delete(msg.id);
154
157
  this.notifyDrainWaiters();
155
158
  }
156
159
  }
157
160
  else if (msg && msg.command === "publishResult" && msg.id) {
158
- if (this.pendingPublishCompletions > 0) {
159
- this.pendingPublishCompletions -= 1;
160
- }
161
+ this.pendingPublishCompletions.delete(msg.id);
161
162
  if (msg.status === "error") {
162
163
  const errorMessage = msg.error ?? `Error publishing to topic ${msg.topic ?? "unknown"}`;
163
164
  this.event.emit("error", { code: 0, message: errorMessage });
@@ -175,16 +176,20 @@ export default class UnsMqttProxy extends UnsProxy {
175
176
  }
176
177
  });
177
178
  this.worker.on("error", (err) => {
179
+ if (this.expectedWorkerExit) {
180
+ return;
181
+ }
178
182
  logger.error("Error in worker:", err);
179
183
  const reason = err instanceof Error ? err : new Error(String(err));
180
184
  this.failPendingPublishes(reason);
181
185
  });
182
186
  this.worker.on("exit", (code) => {
183
- if (code !== 0) {
184
- logger.error(`Worker exited with code ${code}`);
185
- const reason = new Error(`MQTT worker exited with code ${code}`);
186
- this.failPendingPublishes(reason);
187
+ if (this.expectedWorkerExit) {
188
+ return;
187
189
  }
190
+ logger.error(`Worker exited unexpectedly with code ${code}`);
191
+ const reason = new Error(`MQTT worker exited unexpectedly with code ${code}`);
192
+ this.failPendingPublishes(reason);
188
193
  });
189
194
  }
190
195
  /**
@@ -197,13 +202,29 @@ export default class UnsMqttProxy extends UnsProxy {
197
202
  */
198
203
  async enqueueMessageToWorkerQueue(topic, message, options) {
199
204
  return new Promise((resolve, reject) => {
205
+ if (this.lifecycleState !== "running") {
206
+ reject(new Error(`${this.instanceNameWithSuffix} - MQTT proxy is ${this.lifecycleState}; publish rejected.`));
207
+ return;
208
+ }
200
209
  if (this.workerFailure) {
201
210
  reject(this.workerFailure);
202
211
  return;
203
212
  }
213
+ const maxPendingPublishes = this.unsParameters.maxPendingPublishes;
214
+ const pendingCount = this.pendingEnqueues.size + this.pendingPublishCompletions.size;
215
+ if (maxPendingPublishes !== undefined && pendingCount >= maxPendingPublishes) {
216
+ reject(new Error(`${this.instanceNameWithSuffix} - Publisher queue is full (${maxPendingPublishes}).`));
217
+ return;
218
+ }
204
219
  const id = `${Date.now()}-${Math.random()}`;
205
220
  this.pendingEnqueues.set(id, { resolve, reject });
206
- this.worker.postMessage({ command: "enqueue", id, topic, message, options });
221
+ try {
222
+ this.worker.postMessage({ command: "enqueue", id, topic, message, options });
223
+ }
224
+ catch (error) {
225
+ this.pendingEnqueues.delete(id);
226
+ reject(error);
227
+ }
207
228
  this.notifyDrainWaiters();
208
229
  });
209
230
  }
@@ -223,12 +244,14 @@ export default class UnsMqttProxy extends UnsProxy {
223
244
  setPublisherPassive() {
224
245
  this.worker.postMessage({ command: "setPublisherPassive" });
225
246
  return new Promise((resolve) => {
226
- this.event.on("mqttWorker", (msg) => {
247
+ const handler = (msg) => {
227
248
  if (msg.command === "handover_publisher") {
249
+ this.event.off("mqttWorker", handler);
228
250
  logger.info(`${this.instanceNameWithSuffix} - Publisher set to passive.`);
229
251
  resolve(msg);
230
252
  }
231
- });
253
+ };
254
+ this.event.on("mqttWorker", handler);
232
255
  });
233
256
  }
234
257
  /**
@@ -247,12 +270,14 @@ export default class UnsMqttProxy extends UnsProxy {
247
270
  setSubscriberPassive() {
248
271
  this.worker.postMessage({ command: "setSubscriberPassive" });
249
272
  return new Promise((resolve) => {
250
- this.event.on("mqttWorker", (msg) => {
273
+ const handler = (msg) => {
251
274
  if (msg.command === "handover_subscriber") {
252
- logger.info(`${this.instanceNameWithSuffix} - Publisher set to passive.`);
275
+ this.event.off("mqttWorker", handler);
276
+ logger.info(`${this.instanceNameWithSuffix} - Subscriber set to passive.`);
253
277
  resolve(msg);
254
278
  }
255
- });
279
+ };
280
+ this.event.on("mqttWorker", handler);
256
281
  });
257
282
  }
258
283
  /**
@@ -260,18 +285,16 @@ export default class UnsMqttProxy extends UnsProxy {
260
285
  * until the queue is empty (all messages are processed).
261
286
  */
262
287
  async setSubscriberPassiveAndDrainQueue() {
263
- return new Promise(async (resolve) => {
264
- const mqttWorkerData = await this.setSubscriberPassive();
265
- await this.flush();
266
- logger.info(`${this.instanceNameWithSuffix} - Subscriber set to passive and queue drained.`);
267
- resolve(mqttWorkerData);
268
- });
288
+ const mqttWorkerData = await this.setSubscriberPassive();
289
+ await this.flush();
290
+ logger.info(`${this.instanceNameWithSuffix} - Subscriber set to passive and queue drained.`);
291
+ return mqttWorkerData;
269
292
  }
270
293
  async drainPublishes(timeoutMs = UnsMqttProxy.DEFAULT_DRAIN_TIMEOUT_MS) {
271
294
  if (this.workerFailure) {
272
295
  throw this.workerFailure;
273
296
  }
274
- if (this.pendingEnqueues.size === 0 && this.pendingPublishCompletions === 0) {
297
+ if (this.pendingEnqueues.size === 0 && this.pendingPublishCompletions.size === 0) {
275
298
  return;
276
299
  }
277
300
  await new Promise((resolve, reject) => {
@@ -530,42 +553,63 @@ export default class UnsMqttProxy extends UnsProxy {
530
553
  /**
531
554
  * Stops the UnsProxy instance and cleans up resources.
532
555
  */
533
- async stop(options = {}) {
556
+ stop(options = {}) {
557
+ if (this.stopPromise) {
558
+ return this.stopPromise;
559
+ }
560
+ this.lifecycleState = "stopping";
561
+ this.stopPromise = this.performStop(options);
562
+ return this.stopPromise;
563
+ }
564
+ async performStop(options) {
534
565
  await super.stop();
535
566
  const drain = options.drain ?? true;
536
567
  const timeoutMs = options.timeoutMs ?? UnsMqttProxy.DEFAULT_DRAIN_TIMEOUT_MS;
537
- let drainError = null;
568
+ let stopError = null;
538
569
  if (drain) {
539
570
  try {
540
571
  await this.flush(timeoutMs);
541
572
  }
542
573
  catch (error) {
543
- drainError = error instanceof Error ? error : new Error(String(error));
544
- logger.error(`${this.instanceNameWithSuffix} - Error draining publishes before stop: ${drainError.message}`);
574
+ stopError = error instanceof Error ? error : new Error(String(error));
575
+ logger.error(`${this.instanceNameWithSuffix} - Error draining publishes before stop: ${stopError.message}`);
545
576
  }
546
577
  }
547
578
  if (this.worker) {
579
+ this.expectedWorkerExit = true;
548
580
  try {
549
581
  const exitCode = await this.worker.terminate();
550
582
  logger.info(`${this.instanceNameWithSuffix} - Worker terminated with exit code ${exitCode}`);
551
583
  }
552
584
  catch (error) {
553
- logger.error(`${this.instanceNameWithSuffix} - Error terminating worker: ${error.message}`);
585
+ const terminationError = error instanceof Error ? error : new Error(String(error));
586
+ logger.error(`${this.instanceNameWithSuffix} - Error terminating worker: ${terminationError.message}`);
587
+ stopError ??= terminationError;
554
588
  }
555
589
  }
556
- this.failPendingPublishes(drainError ?? new Error("UnsProxy has been stopped"));
557
- if (drainError) {
558
- throw drainError;
590
+ this.lifecycleState = "stopped";
591
+ this.rejectOutstandingPublishes(stopError ?? new Error("UnsProxy has been stopped"));
592
+ if (stopError) {
593
+ throw stopError;
559
594
  }
560
595
  }
561
596
  failPendingPublishes(reason) {
562
597
  this.workerFailure = reason;
598
+ this.rejectOutstandingPublishes(reason);
599
+ }
600
+ rejectOutstandingPublishes(reason) {
563
601
  for (const pending of this.pendingEnqueues.values()) {
564
602
  pending.reject(reason);
565
603
  }
566
604
  this.pendingEnqueues.clear();
567
- this.pendingPublishCompletions = 0;
568
- this.notifyDrainWaiters();
605
+ this.pendingPublishCompletions.clear();
606
+ const waiters = this.drainWaiters.splice(0);
607
+ for (const waiter of waiters) {
608
+ if (waiter.timer) {
609
+ clearTimeout(waiter.timer);
610
+ }
611
+ waiter.reject(reason);
612
+ }
569
613
  }
570
614
  notifyDrainWaiters() {
571
615
  if (this.workerFailure) {
@@ -578,7 +622,7 @@ export default class UnsMqttProxy extends UnsProxy {
578
622
  }
579
623
  return;
580
624
  }
581
- if (this.pendingEnqueues.size !== 0 || this.pendingPublishCompletions !== 0) {
625
+ if (this.pendingEnqueues.size !== 0 || this.pendingPublishCompletions.size !== 0) {
582
626
  return;
583
627
  }
584
628
  const waiters = this.drainWaiters.splice(0);