node-opcua-client 2.167.0 → 2.168.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.
- package/dist/private/client_base_impl.js +88 -81
- package/dist/private/client_base_impl.js.map +1 -1
- package/dist/private/reconnection/client_publish_engine_reconnection.js +54 -45
- package/dist/private/reconnection/client_publish_engine_reconnection.js.map +1 -1
- package/dist/private/reconnection/reconnection.d.ts +1 -1
- package/dist/private/reconnection/reconnection.js +199 -280
- package/dist/private/reconnection/reconnection.js.map +1 -1
- package/package.json +41 -42
- package/source/private/client_base_impl.ts +142 -193
- package/source/private/reconnection/client_publish_engine_reconnection.ts +67 -60
- 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
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
|
38
|
+
if (!session || session._closeEventHasBeenEmitted) {
|
|
42
39
|
debugLog("ClientPublishEngine#_republish aborted ");
|
|
43
|
-
|
|
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
|
-
|
|
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
|
|
50
|
+
// reprocess notification message and keep going
|
|
51
51
|
if (statusCode.equals(StatusCodes.Good)) {
|
|
52
|
-
subscription.onNotificationMessage(response
|
|
52
|
+
subscription.onNotificationMessage(response.notificationMessage);
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
59
|
+
debugLog(" _send_republish ends with ", err.message);
|
|
60
|
+
reject(err);
|
|
62
61
|
});
|
|
63
|
-
};
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
95
|
+
throw _err;
|
|
91
96
|
}
|
|
92
97
|
}
|
|
93
98
|
|
|
94
|
-
|
|
99
|
+
const error = err as Error;
|
|
95
100
|
|
|
96
|
-
debugLog("__askSubscriptionRepublish--------------------- err =",
|
|
101
|
+
debugLog("__askSubscriptionRepublish--------------------- err =", error.message);
|
|
97
102
|
|
|
98
|
-
if (
|
|
103
|
+
if (error.message.match(/BadSessionInvalid/)) {
|
|
99
104
|
// _republish failed because session is not valid anymore on server side.
|
|
100
|
-
|
|
105
|
+
throw error;
|
|
101
106
|
}
|
|
102
|
-
if (
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
.catch((err) => callback(err));
|
|
120
|
+
await recreateSubscriptionAndMonitoredItem(subscription);
|
|
121
|
+
return;
|
|
118
122
|
}
|
|
119
|
-
if (
|
|
123
|
+
if (error.message.match(/|MessageNotAvailable/)) {
|
|
120
124
|
// start engine and start monitoring
|
|
121
125
|
}
|
|
122
|
-
|
|
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
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
153
|
+
processAll().then(() => callback()).catch(() => callback());
|
|
147
154
|
}
|