node-opcua-client 2.128.0 → 2.130.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/client_base.d.ts +5 -1
- package/dist/client_base.js.map +1 -1
- package/dist/opcua_client.js.map +1 -1
- package/dist/private/client_base_impl.d.ts +2 -2
- package/dist/private/client_base_impl.js +6 -6
- package/dist/private/client_base_impl.js.map +1 -1
- package/dist/private/client_publish_engine.js +7 -5
- package/dist/private/client_publish_engine.js.map +1 -1
- package/dist/private/client_session_impl.d.ts +12 -6
- package/dist/private/client_session_impl.js +49 -40
- package/dist/private/client_session_impl.js.map +1 -1
- package/dist/private/opcua_client_impl.d.ts +0 -4
- package/dist/private/opcua_client_impl.js +0 -4
- package/dist/private/opcua_client_impl.js.map +1 -1
- package/dist/private/reconnection/reconnection.js +22 -9
- package/dist/private/reconnection/reconnection.js.map +1 -1
- package/package.json +29 -29
- package/source/client_base.ts +5 -1
- package/source/opcua_client.ts +1 -0
- package/source/private/client_base_impl.ts +11 -9
- package/source/private/client_publish_engine.ts +7 -6
- package/source/private/client_session_impl.ts +33 -40
- package/source/private/opcua_client_impl.ts +0 -4
- package/source/private/reconnection/reconnection.ts +35 -23
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-opcua-client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.130.0",
|
|
4
4
|
"description": "pure nodejs OPCUA SDK - module client",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"clean": "npx rimraf node_modules dist *.tsbuildinfo certificates",
|
|
@@ -17,51 +17,51 @@
|
|
|
17
17
|
"@types/async": "^3.2.24",
|
|
18
18
|
"async": "^3.2.5",
|
|
19
19
|
"chalk": "4.1.2",
|
|
20
|
-
"node-opcua-alarm-condition": "2.
|
|
20
|
+
"node-opcua-alarm-condition": "2.130.0",
|
|
21
21
|
"node-opcua-assert": "2.120.0",
|
|
22
22
|
"node-opcua-basic-types": "2.128.0",
|
|
23
23
|
"node-opcua-buffer-utils": "2.128.0",
|
|
24
|
-
"node-opcua-certificate-manager": "2.
|
|
25
|
-
"node-opcua-client-dynamic-extension-object": "2.
|
|
26
|
-
"node-opcua-common": "2.
|
|
24
|
+
"node-opcua-certificate-manager": "2.129.0",
|
|
25
|
+
"node-opcua-client-dynamic-extension-object": "2.130.0",
|
|
26
|
+
"node-opcua-common": "2.130.0",
|
|
27
27
|
"node-opcua-constants": "2.125.0",
|
|
28
|
-
"node-opcua-crypto": "4.
|
|
28
|
+
"node-opcua-crypto": "4.9.2",
|
|
29
29
|
"node-opcua-data-model": "2.128.0",
|
|
30
|
-
"node-opcua-data-value": "2.
|
|
30
|
+
"node-opcua-data-value": "2.129.0",
|
|
31
31
|
"node-opcua-date-time": "2.128.0",
|
|
32
32
|
"node-opcua-debug": "2.128.0",
|
|
33
33
|
"node-opcua-extension-object": "2.128.0",
|
|
34
34
|
"node-opcua-hostname": "2.128.0",
|
|
35
35
|
"node-opcua-nodeid": "2.128.0",
|
|
36
36
|
"node-opcua-object-registry": "2.128.0",
|
|
37
|
-
"node-opcua-pki": "4.
|
|
38
|
-
"node-opcua-pseudo-session": "2.
|
|
39
|
-
"node-opcua-schemas": "2.
|
|
40
|
-
"node-opcua-secure-channel": "2.
|
|
41
|
-
"node-opcua-service-browse": "2.
|
|
42
|
-
"node-opcua-service-call": "2.
|
|
43
|
-
"node-opcua-service-discovery": "2.
|
|
44
|
-
"node-opcua-service-endpoints": "2.
|
|
45
|
-
"node-opcua-service-filter": "2.
|
|
46
|
-
"node-opcua-service-history": "2.
|
|
47
|
-
"node-opcua-service-query": "2.
|
|
48
|
-
"node-opcua-service-read": "2.
|
|
49
|
-
"node-opcua-service-register-node": "2.
|
|
50
|
-
"node-opcua-service-secure-channel": "2.
|
|
51
|
-
"node-opcua-service-session": "2.
|
|
52
|
-
"node-opcua-service-subscription": "2.
|
|
53
|
-
"node-opcua-service-translate-browse-path": "2.
|
|
54
|
-
"node-opcua-service-write": "2.
|
|
37
|
+
"node-opcua-pki": "4.11.1",
|
|
38
|
+
"node-opcua-pseudo-session": "2.130.0",
|
|
39
|
+
"node-opcua-schemas": "2.129.0",
|
|
40
|
+
"node-opcua-secure-channel": "2.130.0",
|
|
41
|
+
"node-opcua-service-browse": "2.129.0",
|
|
42
|
+
"node-opcua-service-call": "2.129.0",
|
|
43
|
+
"node-opcua-service-discovery": "2.129.0",
|
|
44
|
+
"node-opcua-service-endpoints": "2.129.0",
|
|
45
|
+
"node-opcua-service-filter": "2.129.0",
|
|
46
|
+
"node-opcua-service-history": "2.129.0",
|
|
47
|
+
"node-opcua-service-query": "2.129.0",
|
|
48
|
+
"node-opcua-service-read": "2.129.0",
|
|
49
|
+
"node-opcua-service-register-node": "2.129.0",
|
|
50
|
+
"node-opcua-service-secure-channel": "2.129.0",
|
|
51
|
+
"node-opcua-service-session": "2.129.0",
|
|
52
|
+
"node-opcua-service-subscription": "2.130.0",
|
|
53
|
+
"node-opcua-service-translate-browse-path": "2.129.0",
|
|
54
|
+
"node-opcua-service-write": "2.129.0",
|
|
55
55
|
"node-opcua-status-code": "2.128.0",
|
|
56
|
-
"node-opcua-types": "2.
|
|
56
|
+
"node-opcua-types": "2.129.0",
|
|
57
57
|
"node-opcua-utils": "2.128.0",
|
|
58
|
-
"node-opcua-variant": "2.
|
|
58
|
+
"node-opcua-variant": "2.129.0",
|
|
59
59
|
"thenify": "^3.3.1"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/underscore": "^1.11.15",
|
|
63
63
|
"dequeue": "^1.0.5",
|
|
64
|
-
"node-opcua-address-space": "2.
|
|
64
|
+
"node-opcua-address-space": "2.130.0",
|
|
65
65
|
"node-opcua-binary-stream": "2.128.0",
|
|
66
66
|
"node-opcua-factory": "2.128.0",
|
|
67
67
|
"node-opcua-leak-detector": "2.128.0",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"internet of things"
|
|
89
89
|
],
|
|
90
90
|
"homepage": "http://node-opcua.github.io/",
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "94bf9012b03dbd4325cd122ce04edfa5466875bc",
|
|
92
92
|
"files": [
|
|
93
93
|
"dist",
|
|
94
94
|
"source"
|
package/source/client_base.ts
CHANGED
|
@@ -137,6 +137,10 @@ export interface OPCUAClientBaseOptions {
|
|
|
137
137
|
*/
|
|
138
138
|
transportSettings?: TransportSettings;
|
|
139
139
|
transportTimeout?: number;
|
|
140
|
+
/**
|
|
141
|
+
* defaultTransactionTimeout
|
|
142
|
+
*/
|
|
143
|
+
defaultTransactionTimeout?: number;
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
export interface GetEndpointsOptions {
|
|
@@ -284,7 +288,7 @@ export interface OPCUAClientBase extends EventEmitter {
|
|
|
284
288
|
* @param event
|
|
285
289
|
* @param eventHandler
|
|
286
290
|
*/
|
|
287
|
-
on(eventName: "security_token_renewed", eventHandler: () => void): this;
|
|
291
|
+
on(eventName: "security_token_renewed", eventHandler: (channel: ClientSecureChannelLayer, token: ChannelSecurityToken) => void): this;
|
|
288
292
|
|
|
289
293
|
/**
|
|
290
294
|
* this event is raised when the connection has been broken
|
package/source/opcua_client.ts
CHANGED
|
@@ -45,6 +45,7 @@ export interface OPCUAClientOptions extends OPCUAClientBaseOptions {
|
|
|
45
45
|
* default value : "Auto" : the client will attempt to extract DataTypeDefinition using the most efficient strategy
|
|
46
46
|
*/
|
|
47
47
|
dataTypeExtractStrategy?: DataTypeExtractStrategy;
|
|
48
|
+
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
export interface OPCUAClient extends OPCUAClientBase {
|
|
@@ -24,8 +24,7 @@ import {
|
|
|
24
24
|
ConnectionStrategyOptions,
|
|
25
25
|
Request as Request1,
|
|
26
26
|
Response as Response1,
|
|
27
|
-
SecurityPolicy
|
|
28
|
-
SecurityToken
|
|
27
|
+
SecurityPolicy
|
|
29
28
|
} from "node-opcua-secure-channel";
|
|
30
29
|
import {
|
|
31
30
|
FindServersOnNetworkRequest,
|
|
@@ -367,6 +366,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
367
366
|
public discoveryUrl: string;
|
|
368
367
|
public readonly applicationName: string;
|
|
369
368
|
private _applicationUri: string;
|
|
369
|
+
public defaultTransactionTimeout?: number;
|
|
370
370
|
|
|
371
371
|
/**
|
|
372
372
|
* true if session shall periodically probe the server to keep the session alive and prevent timeout
|
|
@@ -468,6 +468,9 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
468
468
|
this._serverEndpoints = [];
|
|
469
469
|
|
|
470
470
|
this.defaultSecureTokenLifetime = options.defaultSecureTokenLifetime || 600000;
|
|
471
|
+
|
|
472
|
+
this.defaultTransactionTimeout = options.defaultTransactionTimeout;
|
|
473
|
+
|
|
471
474
|
this.tokenRenewalInterval = options.tokenRenewalInterval || 0;
|
|
472
475
|
assert(isFinite(this.tokenRenewalInterval) && this.tokenRenewalInterval >= 0);
|
|
473
476
|
this.securityMode = coerceMessageSecurityMode(options.securityMode);
|
|
@@ -686,7 +689,8 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
686
689
|
serverCertificate: this.serverCertificate,
|
|
687
690
|
tokenRenewalInterval: this.tokenRenewalInterval,
|
|
688
691
|
transportSettings: this._transportSettings,
|
|
689
|
-
transportTimeout: this._transportTimeout
|
|
692
|
+
transportTimeout: this._transportTimeout,
|
|
693
|
+
defaultTransactionTimeout: this.defaultTransactionTimeout
|
|
690
694
|
});
|
|
691
695
|
secureChannel.on("backoff", (count: number, delay: number) => {
|
|
692
696
|
this.emit("backoff", count, delay);
|
|
@@ -700,6 +704,8 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
700
704
|
|
|
701
705
|
this._secureChannel = secureChannel;
|
|
702
706
|
|
|
707
|
+
this.emit("secure_channel_created", secureChannel);
|
|
708
|
+
|
|
703
709
|
async.series(
|
|
704
710
|
[
|
|
705
711
|
// ------------------------------------------------- STEP 2 : OpenSecureChannel
|
|
@@ -980,10 +986,6 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
980
986
|
});
|
|
981
987
|
}
|
|
982
988
|
|
|
983
|
-
public getClientNonce(): Nonce | null {
|
|
984
|
-
return this._secureChannel ? this._secureChannel.getClientNonce() : null;
|
|
985
|
-
}
|
|
986
|
-
|
|
987
989
|
public performMessageTransaction(request: Request, callback: ResponseCallback<Response>): void {
|
|
988
990
|
if (!this._secureChannel) {
|
|
989
991
|
// this may happen if the Server has closed the connection abruptly for some unknown reason
|
|
@@ -1595,9 +1597,9 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1595
1597
|
this.emit("lifetime_75", token, secureChannel);
|
|
1596
1598
|
});
|
|
1597
1599
|
|
|
1598
|
-
secureChannel.on("security_token_renewed", () => {
|
|
1600
|
+
secureChannel.on("security_token_renewed", (token: ChannelSecurityToken) => {
|
|
1599
1601
|
// forward message to upper level
|
|
1600
|
-
this.emit("security_token_renewed", secureChannel);
|
|
1602
|
+
this.emit("security_token_renewed", secureChannel, token);
|
|
1601
1603
|
});
|
|
1602
1604
|
|
|
1603
1605
|
secureChannel.on("close", (err?: Error | null) => {
|
|
@@ -281,7 +281,7 @@ export class ClientSidePublishEngine {
|
|
|
281
281
|
// the server tells us that there is no subscription for this session
|
|
282
282
|
// but the client have some active subscription left.
|
|
283
283
|
// This could happen if the client has missed or not received the StatusChange Notification
|
|
284
|
-
debugLog(chalk.bgWhite.red(" WARNING
|
|
284
|
+
debugLog(chalk.bgWhite.red(" WARNING: server tells that there is no Subscription, but client disagree"));
|
|
285
285
|
debugLog("this.activeSubscriptionCount =", this.activeSubscriptionCount);
|
|
286
286
|
active = false;
|
|
287
287
|
}
|
|
@@ -292,7 +292,7 @@ export class ClientSidePublishEngine {
|
|
|
292
292
|
// may be the session timeout is shorted than the subscription life time
|
|
293
293
|
// and the client does not send intermediate keepAlive request to keep the connection working.
|
|
294
294
|
//
|
|
295
|
-
debugLog(chalk.bgWhite.red(" WARNING :
|
|
295
|
+
debugLog(chalk.bgWhite.red(" WARNING : Server tells that the session has closed ..."));
|
|
296
296
|
debugLog(
|
|
297
297
|
" the ClientSidePublishEngine shall now be disabled," + " as server will reject any further request"
|
|
298
298
|
);
|
|
@@ -313,10 +313,11 @@ export class ClientSidePublishEngine {
|
|
|
313
313
|
this.nbMaxPublishRequestsAcceptedByServer
|
|
314
314
|
);
|
|
315
315
|
active = false;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
316
|
+
if (this.nbPendingPublishRequests < 10) {
|
|
317
|
+
warningLog(chalk.bgWhite.red(" warning : server tells that too many publish request has been send ..."));
|
|
318
|
+
warningLog(" On our side nbPendingPublishRequests = ", this.nbPendingPublishRequests);
|
|
319
|
+
warningLog(" => nbMaxPublishRequestsAcceptedByServer =", this.nbMaxPublishRequestsAcceptedByServer);
|
|
320
|
+
}
|
|
320
321
|
}
|
|
321
322
|
} else {
|
|
322
323
|
// istanbul ignore next
|
|
@@ -96,9 +96,11 @@ import { WriteRequest, WriteResponse, WriteValue } from "node-opcua-service-writ
|
|
|
96
96
|
import { StatusCode, StatusCodes, Callback, CallbackT } from "node-opcua-status-code";
|
|
97
97
|
import { ErrorCallback } from "node-opcua-status-code";
|
|
98
98
|
import {
|
|
99
|
+
ActivateSessionRequest,
|
|
99
100
|
AggregateConfigurationOptions,
|
|
100
101
|
BrowseNextRequest,
|
|
101
102
|
BrowseNextResponse,
|
|
103
|
+
CloseSessionRequest,
|
|
102
104
|
HistoryReadValueIdOptions,
|
|
103
105
|
UserTokenType,
|
|
104
106
|
WriteValueOptions
|
|
@@ -129,11 +131,11 @@ import { UserIdentityInfo } from "../user_identity_info";
|
|
|
129
131
|
import { ClientSessionKeepAliveManager } from "../client_session_keepalive_manager";
|
|
130
132
|
import { ClientSubscription } from "../client_subscription";
|
|
131
133
|
import { Request, Response } from "../common";
|
|
132
|
-
import { repair_client_session } from "./reconnection/reconnection";
|
|
133
134
|
|
|
134
135
|
import { ClientSidePublishEngine } from "./client_publish_engine";
|
|
135
136
|
import { ClientSubscriptionImpl } from "./client_subscription_impl";
|
|
136
137
|
import { IClientBase } from "./i_private_client";
|
|
138
|
+
import { repair_client_session } from "./reconnection/reconnection";
|
|
137
139
|
|
|
138
140
|
const helpAPIChange = process.env.DEBUG && process.env.DEBUG.match(/API/);
|
|
139
141
|
const debugLog = make_debugLog(__filename);
|
|
@@ -182,17 +184,18 @@ export interface Reconnectable {
|
|
|
182
184
|
_reconnecting: {
|
|
183
185
|
reconnecting: boolean;
|
|
184
186
|
pendingCallbacks: EmptyCallback[];
|
|
187
|
+
pendingTransactions: { request: Request, callback: (err: Error | null, response?: Response) => void }[];
|
|
185
188
|
};
|
|
186
|
-
pendingTransactions: any[];
|
|
187
|
-
pendingTransactionsCount: number;
|
|
188
189
|
}
|
|
190
|
+
|
|
189
191
|
/**
|
|
190
192
|
* @class ClientSession
|
|
191
193
|
* @param client {OPCUAClientImpl}
|
|
192
194
|
* @constructor
|
|
193
195
|
* @private
|
|
194
196
|
*/
|
|
195
|
-
export class ClientSessionImpl extends EventEmitter implements ClientSession {
|
|
197
|
+
export class ClientSessionImpl extends EventEmitter implements ClientSession, Reconnectable {
|
|
198
|
+
static reconnectingElement: WeakMap<ClientSessionImpl, Reconnectable> = new WeakMap();
|
|
196
199
|
public timeout: number;
|
|
197
200
|
public authenticationToken?: NodeId;
|
|
198
201
|
public requestedMaxReferencesPerNode: number;
|
|
@@ -202,18 +205,16 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession {
|
|
|
202
205
|
public serverCertificate: Certificate;
|
|
203
206
|
public userIdentityInfo?: UserIdentityInfo;
|
|
204
207
|
public name = "";
|
|
205
|
-
|
|
206
208
|
public serverNonce?: Nonce;
|
|
207
209
|
public serverSignature?: SignatureData; // todo : remove ?
|
|
208
210
|
public serverEndpoints: EndpointDescription[] = [];
|
|
209
211
|
public _client: IClientBase | null;
|
|
210
212
|
public _closed: boolean;
|
|
211
213
|
|
|
212
|
-
|
|
214
|
+
public _reconnecting: {
|
|
213
215
|
reconnecting: boolean;
|
|
214
216
|
pendingCallbacks: EmptyCallback[];
|
|
215
217
|
pendingTransactions: any[];
|
|
216
|
-
pendingTransactionsCount: number;
|
|
217
218
|
};
|
|
218
219
|
|
|
219
220
|
/**
|
|
@@ -241,8 +242,7 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession {
|
|
|
241
242
|
this._reconnecting = {
|
|
242
243
|
reconnecting: false,
|
|
243
244
|
pendingCallbacks: [],
|
|
244
|
-
pendingTransactions: []
|
|
245
|
-
pendingTransactionsCount: 0
|
|
245
|
+
pendingTransactions: []
|
|
246
246
|
};
|
|
247
247
|
|
|
248
248
|
this.requestedMaxReferencesPerNode = 10000;
|
|
@@ -1166,7 +1166,6 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession {
|
|
|
1166
1166
|
* @param args
|
|
1167
1167
|
*/
|
|
1168
1168
|
public read(...args: any[]): any {
|
|
1169
|
-
|
|
1170
1169
|
if (args.length === 2) {
|
|
1171
1170
|
return this.read(args[0], 0, args[1]);
|
|
1172
1171
|
}
|
|
@@ -1502,16 +1501,11 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession {
|
|
|
1502
1501
|
// session may have been closed by user ... but is still in used !!
|
|
1503
1502
|
return callback(new Error("Session has been closed and should not be used to perform a transaction anymore"));
|
|
1504
1503
|
}
|
|
1505
|
-
|
|
1506
|
-
this._reconnecting.pendingTransactions = this._reconnecting.pendingTransactions || [];
|
|
1507
|
-
this._reconnecting.pendingTransactionsCount = this._reconnecting.pendingTransactionsCount || 0;
|
|
1508
|
-
|
|
1509
|
-
const isPublishRequest = request instanceof PublishRequest;
|
|
1510
|
-
if (isPublishRequest) {
|
|
1504
|
+
if (request instanceof PublishRequest || request instanceof ActivateSessionRequest || request instanceof CloseSessionRequest) {
|
|
1511
1505
|
return this._performMessageTransaction(request, callback);
|
|
1512
1506
|
}
|
|
1513
1507
|
|
|
1514
|
-
if (this._reconnecting.
|
|
1508
|
+
if (this._reconnecting.pendingTransactions.length > 0) {
|
|
1515
1509
|
/* istanbul ignore next */
|
|
1516
1510
|
if (this._reconnecting.pendingTransactions.length > 10) {
|
|
1517
1511
|
if (!pendingTransactionMessageDisplayed) {
|
|
@@ -1542,33 +1536,32 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession {
|
|
|
1542
1536
|
this._reconnecting.pendingTransactions.push({ request, callback });
|
|
1543
1537
|
return;
|
|
1544
1538
|
}
|
|
1545
|
-
this
|
|
1539
|
+
this.#reprocessRequest(0, request, callback);
|
|
1546
1540
|
}
|
|
1547
|
-
|
|
1548
|
-
this._reconnecting.pendingTransactionsCount = this._reconnecting.pendingTransactionsCount || 0;
|
|
1549
|
-
this._reconnecting.pendingTransactionsCount++;
|
|
1541
|
+
#reprocessRequest = (attemptCount: number, request: Request, callback: (err: Error | null, response?: Response) => void): void => {
|
|
1550
1542
|
|
|
1543
|
+
(attemptCount>0) && warningLog("reprocessRequest => ", request.constructor.name, this._reconnecting.pendingTransactions.length);
|
|
1551
1544
|
this._performMessageTransaction(request, (err: null | Error, response?: Response) => {
|
|
1552
|
-
this._reconnecting.pendingTransactionsCount--;
|
|
1553
|
-
|
|
1554
1545
|
if (err && err.message.match(/BadSessionIdInvalid/) && request.constructor.name !== "ActivateSessionRequest") {
|
|
1555
|
-
|
|
1546
|
+
warningLog("Transaction on Invalid Session ", request.constructor.name, err.message, "isReconnecting?=", this.isReconnecting, "q=", this._reconnecting.pendingTransactions.length);
|
|
1556
1547
|
request.requestHeader.requestHandle = requestHandleNotSetValue;
|
|
1557
|
-
|
|
1558
|
-
|
|
1548
|
+
if (this.isReconnecting) {
|
|
1549
|
+
this.once("session_restored", () => {
|
|
1550
|
+
warningLog("redoing", request.constructor.name, this.isReconnecting);
|
|
1551
|
+
this.#reprocessRequest(attemptCount+1,request, callback);
|
|
1552
|
+
});
|
|
1553
|
+
} else {
|
|
1554
|
+
this.#_recreate_session_and_reperform_transaction(request, callback);
|
|
1555
|
+
}
|
|
1559
1556
|
return;
|
|
1560
1557
|
}
|
|
1561
1558
|
callback(err, response);
|
|
1562
1559
|
const length = this._reconnecting.pendingTransactions.length; // record length before callback is called !
|
|
1563
1560
|
if (length > 0) {
|
|
1564
|
-
debugLog(
|
|
1565
|
-
"processTransactionQueue => ",
|
|
1566
|
-
this._reconnecting.pendingTransactions.length,
|
|
1567
|
-
" transaction(s) left in queue"
|
|
1568
|
-
);
|
|
1561
|
+
debugLog("reprocessRequest => ", this._reconnecting.pendingTransactions.length, " transaction(s) left in queue");
|
|
1569
1562
|
// tslint:disable-next-line: no-shadowed-variable
|
|
1570
1563
|
const { request, callback } = this._reconnecting.pendingTransactions.shift();
|
|
1571
|
-
this
|
|
1564
|
+
this.#reprocessRequest(0, request, callback);
|
|
1572
1565
|
}
|
|
1573
1566
|
});
|
|
1574
1567
|
};
|
|
@@ -2001,8 +1994,8 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession {
|
|
|
2001
1994
|
str += "\n remaining life time...... " + this.evaluateRemainingLifetime();
|
|
2002
1995
|
str += "\n subscription count....... " + this.subscriptionCount;
|
|
2003
1996
|
if (this._client && this._client._secureChannel) {
|
|
2004
|
-
if (this._client._secureChannel.
|
|
2005
|
-
str += "\n reviseTokenLifetime...... " + this._client._secureChannel.
|
|
1997
|
+
if (this._client._secureChannel.activeSecurityToken) {
|
|
1998
|
+
str += "\n reviseTokenLifetime...... " + this._client._secureChannel.activeSecurityToken.revisedLifetime;
|
|
2006
1999
|
}
|
|
2007
2000
|
}
|
|
2008
2001
|
str += "\n keepAlive ................ " + this._keepAliveManager ? true : false;
|
|
@@ -2180,29 +2173,29 @@ export class ClientSessionImpl extends EventEmitter implements ClientSession {
|
|
|
2180
2173
|
callback(null, response);
|
|
2181
2174
|
});
|
|
2182
2175
|
}
|
|
2183
|
-
|
|
2184
|
-
private recreate_session_and_reperform_transaction(
|
|
2176
|
+
#_recreate_session_and_reperform_transaction(
|
|
2185
2177
|
request: Request,
|
|
2186
2178
|
callback: (err: Error | null, response?: Response) => void
|
|
2187
2179
|
) {
|
|
2188
|
-
warningLog("attempt to recreate session to reperform a
|
|
2180
|
+
warningLog("attempt to recreate session to reperform a transaction ", request.constructor.name);
|
|
2189
2181
|
if (this.recursive_repair_detector >= 1) {
|
|
2190
2182
|
// tslint:disable-next-line: no-console
|
|
2191
2183
|
warningLog("recreate_session_and_reperform_transaction => Already in Progress");
|
|
2192
2184
|
return callback(new Error("Cannot recreate session"));
|
|
2193
2185
|
}
|
|
2194
2186
|
this.recursive_repair_detector += 1;
|
|
2195
|
-
|
|
2187
|
+
warningLog(chalk.red("----------------> Repairing Client Session as Server believes it is invalid now "));
|
|
2196
2188
|
repair_client_session(this._client!, this, (err?: Error) => {
|
|
2197
2189
|
this.recursive_repair_detector -= 1;
|
|
2198
2190
|
if (err) {
|
|
2199
|
-
|
|
2191
|
+
warningLog(chalk.red("----------------> session Repaired has failed with error", err.message));
|
|
2200
2192
|
return callback(err);
|
|
2201
2193
|
}
|
|
2202
|
-
|
|
2194
|
+
warningLog(chalk.red("----------------> session Repaired, now redoing original transaction "));
|
|
2203
2195
|
this._performMessageTransaction(request, callback);
|
|
2204
2196
|
});
|
|
2205
2197
|
}
|
|
2198
|
+
|
|
2206
2199
|
}
|
|
2207
2200
|
|
|
2208
2201
|
type promoteOpaqueStructure3WithCallbackFunc = (
|
|
@@ -371,10 +371,6 @@ function _adjustRevisedSessionTimeout(revisedSessionTimeout: number, requestedTi
|
|
|
371
371
|
return revisedSessionTimeout;
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
-
/***
|
|
375
|
-
* @constructor
|
|
376
|
-
* @internal
|
|
377
|
-
*/
|
|
378
374
|
export class OPCUAClientImpl extends ClientBaseImpl implements OPCUAClient {
|
|
379
375
|
public static minimumRevisedSessionTimeout = 100.0;
|
|
380
376
|
private _retryCreateSessionTimer?: NodeJS.Timeout;
|
|
@@ -216,19 +216,19 @@ function repair_client_session_by_recreating_a_new_session(
|
|
|
216
216
|
doDebug && debugLog(chalk.red(" => RECREATING SUBSCRIPTION "), subscriptionId);
|
|
217
217
|
assert(subscription.session === newSession, "must have the new session");
|
|
218
218
|
|
|
219
|
-
recreateSubscriptionAndMonitoredItem(subscription)
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
219
|
+
recreateSubscriptionAndMonitoredItem(subscription)
|
|
220
|
+
.then(() => {
|
|
221
|
+
doDebug &&
|
|
222
|
+
debugLog(
|
|
223
|
+
chalk.cyan(" => RECREATING SUBSCRIPTION AND MONITORED ITEM DONE subscriptionId="),
|
|
224
|
+
subscriptionId
|
|
225
|
+
);
|
|
226
|
+
next();
|
|
227
|
+
})
|
|
228
|
+
.catch((err) => {
|
|
229
|
+
doDebug && debugLog("_recreateSubscription failed !" + (err as Error).message);
|
|
230
|
+
next();
|
|
231
|
+
});
|
|
232
232
|
},
|
|
233
233
|
(err1?: Error | null) => {
|
|
234
234
|
// prettier-ignore
|
|
@@ -310,18 +310,25 @@ function repair_client_session_by_recreating_a_new_session(
|
|
|
310
310
|
if (!client.beforeSubscriptionRecreate) {
|
|
311
311
|
innerCallback();
|
|
312
312
|
return;
|
|
313
|
-
|
|
314
313
|
}
|
|
315
|
-
client
|
|
314
|
+
client
|
|
315
|
+
.beforeSubscriptionRecreate(newSession)
|
|
316
316
|
.then((err) => {
|
|
317
|
-
{
|
|
317
|
+
{
|
|
318
|
+
const err = _shouldNotContinue(session);
|
|
319
|
+
if (err) {
|
|
320
|
+
return innerCallback(err);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
318
323
|
if (!err) {
|
|
319
324
|
innerCallback();
|
|
320
325
|
} else {
|
|
321
326
|
innerCallback(err);
|
|
322
327
|
}
|
|
323
328
|
})
|
|
324
|
-
.catch((err) => {
|
|
329
|
+
.catch((err) => {
|
|
330
|
+
innerCallback(err);
|
|
331
|
+
});
|
|
325
332
|
},
|
|
326
333
|
|
|
327
334
|
function attempt_subscription_transfer(innerCallback: ErrorCallback) {
|
|
@@ -506,7 +513,7 @@ export function repair_client_session(client: IClientBase, session: ClientSessio
|
|
|
506
513
|
privateSession._reconnecting.reconnecting = true;
|
|
507
514
|
|
|
508
515
|
// get old transaction queue ...
|
|
509
|
-
const transactionQueue =
|
|
516
|
+
const transactionQueue = privateSession._reconnecting.pendingTransactions.splice(0);
|
|
510
517
|
|
|
511
518
|
const repeatedAction = (callback: EmptyCallback) => {
|
|
512
519
|
// prettier-ignore
|
|
@@ -527,6 +534,10 @@ export function repair_client_session(client: IClientBase, session: ClientSessio
|
|
|
527
534
|
const delay = 2000;
|
|
528
535
|
errorLog(chalk.red(`... will retry session repair... in ${delay} ms`));
|
|
529
536
|
setTimeout(() => {
|
|
537
|
+
{ const err = _shouldNotContinue(session); if (err) {
|
|
538
|
+
warningLog("cancelling session repair");
|
|
539
|
+
return callback(err);
|
|
540
|
+
} }
|
|
530
541
|
errorLog(chalk.red("Retrying session repair..."));
|
|
531
542
|
repeatedAction(callback);
|
|
532
543
|
}, delay);
|
|
@@ -547,13 +558,14 @@ export function repair_client_session(client: IClientBase, session: ClientSessio
|
|
|
547
558
|
};
|
|
548
559
|
repeatedAction((err) => {
|
|
549
560
|
privateSession._reconnecting.reconnecting = false;
|
|
550
|
-
|
|
551
|
-
const otherCallbacks = privateSession._reconnecting.pendingCallbacks;
|
|
552
|
-
privateSession._reconnecting.pendingCallbacks = [];
|
|
561
|
+
const otherCallbacks = privateSession._reconnecting.pendingCallbacks.splice(0);
|
|
553
562
|
// re-inject element in queue
|
|
563
|
+
|
|
554
564
|
// istanbul ignore next
|
|
555
|
-
|
|
556
|
-
|
|
565
|
+
if (transactionQueue.length > 0) {
|
|
566
|
+
doDebug && debugLog(chalk.yellow("re-injecting transaction queue"), transactionQueue.length);
|
|
567
|
+
transactionQueue.forEach((e: any) => privateSession._reconnecting.pendingTransactions.push(e));
|
|
568
|
+
}
|
|
557
569
|
otherCallbacks.forEach((c: EmptyCallback) => c(err));
|
|
558
570
|
callback(err);
|
|
559
571
|
});
|