node-red-contrib-uos-nats 1.2.0 → 1.2.2

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.
@@ -214,7 +214,14 @@ module.exports = function (RED) {
214
214
 
215
215
  // If Wildcard (empty targetIds and isWildcard=true) -> Request ALL.
216
216
  // If Specific (targetIds has items) -> Request specific.
217
- const snapshotMsg = await nc.request(subjects.readVariablesQuery(this.providerId), payloads.buildReadVariablesQuery(targetIds), { timeout: 2000 });
217
+ // Use serialRequest via Config Node to prevent concurrency issues on the connection
218
+ let snapshotMsg;
219
+ if (typeof connection.serialRequest === 'function') {
220
+ snapshotMsg = await connection.serialRequest(subjects.readVariablesQuery(this.providerId), payloads.buildReadVariablesQuery(targetIds), { timeout: 5000 });
221
+ } else {
222
+ // Fallback for older config nodes (should not happen if package updated correctly)
223
+ snapshotMsg = await nc.request(subjects.readVariablesQuery(this.providerId), payloads.buildReadVariablesQuery(targetIds), { timeout: 5000 });
224
+ }
218
225
 
219
226
  const bb = new flatbuffers.ByteBuffer(snapshotMsg.data);
220
227
  const snapshotObj = ReadVariablesQueryResponse.getRootAsReadVariablesQueryResponse(bb);
@@ -239,7 +246,9 @@ module.exports = function (RED) {
239
246
 
240
247
 
241
248
 
242
- // Initial snapshot
249
+ // Initial snapshot with random jitter into prevent concurrency overload
250
+ // (If multiple nodes start simultaneously)
251
+ await new Promise(r => setTimeout(r, Math.floor(Math.random() * 500) + 100));
243
252
  await performSnapshot();
244
253
 
245
254
  // Setup polling if configured
@@ -175,6 +175,31 @@ module.exports = function (RED) {
175
175
  return this.nc;
176
176
  };
177
177
 
178
+ this.requestQueue = Promise.resolve();
179
+
180
+ this.serialRequest = async (subject, payload, options = {}) => {
181
+ // Enqueue request to run sequentially
182
+ const result = this.requestQueue.then(async () => {
183
+ const nc = await this.ensureConnection();
184
+ return nc.request(subject, payload, options);
185
+ });
186
+
187
+ // Ensure queue does not block on failures (catch individually inside the chain logic)
188
+ // Actually, chaining the result directly makes the next one wait for result resolution.
189
+ // We want to update queue pointer to catch errors so next request still runs.
190
+ this.requestQueue = result.catch(() => { });
191
+
192
+ return result;
193
+ };
194
+
195
+ /**
196
+ * @deprecated Use serialRequest for concurrency safety
197
+ */
198
+ this.acquire = async () => {
199
+ this.users += 1;
200
+ return this.ensureConnection();
201
+ };
202
+
178
203
  this.getGrantedScopes = async () => {
179
204
  await this.getToken();
180
205
  return this.tokenInfo?.grantedScope || '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-uos-nats",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Node-RED nodes for Weidmüller u-OS Data Hub. Read, write, and provide variables via NATS protocol with OAuth2 authentication. Features: Variable Key resolution, custom icons, example flows, and provider definition caching.",
5
5
  "author": {
6
6
  "name": "IoTUeli",