node-opcua-client 2.167.0 → 2.169.0

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 (41) hide show
  1. package/dist/client_monitored_item.d.ts +4 -4
  2. package/dist/client_monitored_item.js +6 -5
  3. package/dist/client_monitored_item.js.map +1 -1
  4. package/dist/client_monitored_item_base.d.ts +7 -7
  5. package/dist/client_monitored_item_toolbox.d.ts +5 -5
  6. package/dist/client_monitored_item_toolbox.js +26 -19
  7. package/dist/client_monitored_item_toolbox.js.map +1 -1
  8. package/dist/private/client_base_impl.js +116 -85
  9. package/dist/private/client_base_impl.js.map +1 -1
  10. package/dist/private/client_monitored_item_group_impl.d.ts +7 -6
  11. package/dist/private/client_monitored_item_group_impl.js +6 -8
  12. package/dist/private/client_monitored_item_group_impl.js.map +1 -1
  13. package/dist/private/client_monitored_item_impl.d.ts +10 -9
  14. package/dist/private/client_monitored_item_impl.js +40 -26
  15. package/dist/private/client_monitored_item_impl.js.map +1 -1
  16. package/dist/private/client_session_impl.d.ts +1 -0
  17. package/dist/private/client_session_impl.js +12 -0
  18. package/dist/private/client_session_impl.js.map +1 -1
  19. package/dist/private/client_subscription_impl.d.ts +7 -4
  20. package/dist/private/client_subscription_impl.js +101 -77
  21. package/dist/private/client_subscription_impl.js.map +1 -1
  22. package/dist/private/opcua_client_impl.d.ts +1 -0
  23. package/dist/private/opcua_client_impl.js +11 -0
  24. package/dist/private/opcua_client_impl.js.map +1 -1
  25. package/dist/private/reconnection/client_publish_engine_reconnection.js +54 -45
  26. package/dist/private/reconnection/client_publish_engine_reconnection.js.map +1 -1
  27. package/dist/private/reconnection/reconnection.d.ts +1 -1
  28. package/dist/private/reconnection/reconnection.js +199 -280
  29. package/dist/private/reconnection/reconnection.js.map +1 -1
  30. package/package.json +43 -44
  31. package/source/client_monitored_item.ts +5 -4
  32. package/source/client_monitored_item_base.ts +13 -8
  33. package/source/client_monitored_item_toolbox.ts +24 -20
  34. package/source/private/client_base_impl.ts +169 -199
  35. package/source/private/client_monitored_item_group_impl.ts +15 -16
  36. package/source/private/client_monitored_item_impl.ts +56 -38
  37. package/source/private/client_session_impl.ts +29 -14
  38. package/source/private/client_subscription_impl.ts +151 -91
  39. package/source/private/opcua_client_impl.ts +13 -0
  40. package/source/private/reconnection/client_publish_engine_reconnection.ts +67 -60
  41. package/source/private/reconnection/reconnection.ts +253 -344
@@ -1,11 +1,8 @@
1
- import async from "async";
2
1
  import chalk from "chalk";
3
2
  import assert from "node-opcua-assert";
4
3
  import { checkDebugFlag, make_debugLog } from "node-opcua-debug";
5
4
  import { StatusCodes } from "node-opcua-status-code";
6
5
  import { RepublishRequest, type RepublishResponse } from "node-opcua-types";
7
- import { types } from "util";
8
- import type { SubscriptionId } from "../../client_session";
9
6
  import type { ClientSidePublishEngine } from "../client_publish_engine";
10
7
  import type { ClientSessionImpl } from "../client_session_impl";
11
8
  import type { ClientSubscriptionImpl } from "../client_subscription_impl";
@@ -15,12 +12,12 @@ import { _shouldNotContinue2 } from "./reconnection";
15
12
  const debugLog = make_debugLog("RECONNECTION");
16
13
  const doDebug = checkDebugFlag("RECONNECTION");
17
14
 
18
- function _republish(engine: ClientSidePublishEngine, subscription: ClientSubscriptionImpl, callback: (err?: Error) => void) {
19
- let isDone = false;
20
- const session = engine.session as ClientSessionImpl;
21
-
22
- const sendRepublishFunc = (callback2: (err?: Error) => void) => {
23
- assert(isFinite(subscription.lastSequenceNumber) && subscription.lastSequenceNumber + 1 >= 0);
15
+ function _sendRepublish(
16
+ session: ClientSessionImpl,
17
+ subscription: ClientSubscriptionImpl
18
+ ): Promise<{ isDone: boolean }> {
19
+ return new Promise<{ isDone: boolean }>((resolve, reject) => {
20
+ assert(Number.isFinite(subscription.lastSequenceNumber) && subscription.lastSequenceNumber + 1 >= 0);
24
21
 
25
22
  const request = new RepublishRequest({
26
23
  retransmitSequenceNumber: subscription.lastSequenceNumber + 1,
@@ -38,68 +35,76 @@ function _republish(engine: ClientSidePublishEngine, subscription: ClientSubscri
38
35
  );
39
36
  }
40
37
 
41
- if (!session || session!._closeEventHasBeenEmitted) {
38
+ if (!session || session._closeEventHasBeenEmitted) {
42
39
  debugLog("ClientPublishEngine#_republish aborted ");
43
- // has client been disconnected in the mean time ?
44
- isDone = true;
45
- return callback2();
40
+ return resolve({ isDone: true });
46
41
  }
42
+
47
43
  session.republish(request, (err: Error | null, response?: RepublishResponse) => {
48
- const statusCode = err ? StatusCodes.Bad : response!.responseHeader.serviceResult;
44
+ if (!response) {
45
+ reject(err);
46
+ return;
47
+ }
48
+ const statusCode = err ? StatusCodes.Bad : response.responseHeader.serviceResult;
49
49
  if (!err && (statusCode.equals(StatusCodes.Good) || statusCode.equals(StatusCodes.BadMessageNotAvailable))) {
50
- // reprocess notification message and keep going
50
+ // reprocess notification message and keep going
51
51
  if (statusCode.equals(StatusCodes.Good)) {
52
- subscription.onNotificationMessage(response!.notificationMessage);
52
+ subscription.onNotificationMessage(response.notificationMessage);
53
53
  }
54
- } else {
55
- if (!err) {
56
- err = new Error(response!.responseHeader.serviceResult.toString());
57
- }
58
- debugLog(" _send_republish ends with ", err.message);
59
- isDone = true;
54
+ return resolve({ isDone: false });
55
+ }
56
+ if (!err) {
57
+ err = new Error(response.responseHeader.serviceResult.toString());
60
58
  }
61
- callback2(err ? err : undefined);
59
+ debugLog(" _send_republish ends with ", err.message);
60
+ reject(err);
62
61
  });
63
- };
62
+ });
63
+ }
64
64
 
65
- const sendRepublishUntilDone = () => {
66
- async.whilst(
67
- (cb: (err: null, truth: boolean) => void) => cb(null, !isDone),
68
- sendRepublishFunc,
69
- ((err?: Error | null): void => {
70
- debugLog("nbPendingPublishRequest = ", engine.nbPendingPublishRequests);
71
- debugLog(" _republish ends with ", err ? err.message : "null");
72
- callback(err!);
73
- }) as any // Wait for @type/async bug to be fixed !
74
- );
75
- };
65
+ async function _republish(
66
+ engine: ClientSidePublishEngine,
67
+ subscription: ClientSubscriptionImpl
68
+ ): Promise<void> {
69
+ const session = engine.session as ClientSessionImpl;
76
70
 
77
- setImmediate(sendRepublishUntilDone);
71
+ // loop until done (all messages re-published or error)
72
+ let isDone = false;
73
+ while (!isDone) {
74
+ // yield to event loop before each iteration
75
+ await new Promise<void>((resolve) => setImmediate(resolve));
76
+ const result = await _sendRepublish(session, subscription);
77
+ isDone = result.isDone;
78
+ }
79
+
80
+ debugLog("nbPendingPublishRequest = ", engine.nbPendingPublishRequests);
81
+ debugLog(" _republish ends with ", "null");
78
82
  }
79
83
 
80
- function __askSubscriptionRepublish(
84
+ async function __askSubscriptionRepublish(
81
85
  engine: ClientSidePublishEngine,
82
- subscription: ClientSubscriptionImpl,
83
- callback: (err?: Error) => void
84
- ) {
85
- _republish(engine, subscription, (err?: Error) => {
86
+ subscription: ClientSubscriptionImpl
87
+ ): Promise<void> {
88
+ try {
89
+ await _republish(engine, subscription);
90
+ } catch (err) {
86
91
  // prettier-ignore
87
92
  {
88
93
  const _err = _shouldNotContinue2(subscription);
89
94
  if (_err) {
90
- return callback(_err);
95
+ throw _err;
91
96
  }
92
97
  }
93
98
 
94
- assert(!err || types.isNativeError(err));
99
+ const error = err as Error;
95
100
 
96
- debugLog("__askSubscriptionRepublish--------------------- err =", err ? err.message : null);
101
+ debugLog("__askSubscriptionRepublish--------------------- err =", error.message);
97
102
 
98
- if (err && err.message.match(/BadSessionInvalid/)) {
103
+ if (error.message.match(/BadSessionInvalid/)) {
99
104
  // _republish failed because session is not valid anymore on server side.
100
- return callback(err);
105
+ throw error;
101
106
  }
102
- if (err && err.message.match(/SubscriptionIdInvalid/)) {
107
+ if (error.message.match(/SubscriptionIdInvalid/)) {
103
108
  // _republish failed because subscriptionId is not valid anymore on server side.
104
109
  //
105
110
  // This could happen when the subscription has timed out and has been deleted by server
@@ -112,15 +117,18 @@ function __askSubscriptionRepublish(
112
117
  debugLog(
113
118
  chalk.bgWhite.red("__askSubscriptionRepublish failed " + " subscriptionId is not valid anymore on server side.")
114
119
  );
115
- return recreateSubscriptionAndMonitoredItem(subscription)
116
- .then(() => callback())
117
- .catch((err) => callback(err));
120
+ await recreateSubscriptionAndMonitoredItem(subscription);
121
+ return;
118
122
  }
119
- if (err && err.message.match(/|MessageNotAvailable/)) {
123
+ if (error.message.match(/|MessageNotAvailable/)) {
120
124
  // start engine and start monitoring
121
125
  }
122
- callback();
123
- });
126
+ }
127
+ // check after successful republish too
128
+ const _err = _shouldNotContinue2(subscription);
129
+ if (_err) {
130
+ throw _err;
131
+ }
124
132
  }
125
133
 
126
134
  export function republish(engine: ClientSidePublishEngine, callback: () => void): void {
@@ -135,13 +143,12 @@ export function republish(engine: ClientSidePublishEngine, callback: () => void)
135
143
  * call Republish continuously until all Notification messages of
136
144
  * un-acknowledged notifications are reprocessed.
137
145
  */
138
- const askSubscriptionRepublish = (
139
- subscription: ClientSubscriptionImpl,
140
- subscriptionId: SubscriptionId | string,
141
- innerCallback: () => void
142
- ) => {
143
- __askSubscriptionRepublish(engine, subscription, innerCallback);
146
+ const processAll = async () => {
147
+ const entries = Object.entries(engine.subscriptionMap);
148
+ for (const [_subscriptionId, subscription] of entries) {
149
+ await __askSubscriptionRepublish(engine, subscription as ClientSubscriptionImpl);
150
+ }
144
151
  };
145
152
 
146
- async.forEachOf(engine.subscriptionMap, askSubscriptionRepublish, callback);
153
+ processAll().then(() => callback()).catch(() => callback());
147
154
  }