node-opcua-client 2.105.1 → 2.107.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.js +1 -1
- package/dist/client_base.js.map +1 -1
- package/dist/client_subscription.js +1 -1
- package/dist/client_subscription.js.map +1 -1
- package/dist/private/client_base_impl.d.ts +1 -0
- package/dist/private/client_base_impl.js +3 -0
- package/dist/private/client_base_impl.js.map +1 -1
- package/dist/private/client_publish_engine.js +1 -1
- package/dist/private/client_publish_engine.js.map +1 -1
- package/dist/private/client_session_impl.js.map +1 -1
- package/dist/private/i_private_client.d.ts +1 -0
- package/dist/private/opcua_client_impl.d.ts +1 -0
- package/dist/private/opcua_client_impl.js +11 -4
- package/dist/private/opcua_client_impl.js.map +1 -1
- package/dist/reconnection.js +58 -36
- package/dist/reconnection.js.map +1 -1
- package/package.json +24 -24
- package/source/private/client_base_impl.ts +5 -1
- package/source/private/client_session_impl.ts +1 -0
- package/source/private/i_private_client.ts +2 -0
- package/source/private/opcua_client_impl.ts +12 -3
- package/source/reconnection.ts +72 -46
package/source/reconnection.ts
CHANGED
|
@@ -18,10 +18,10 @@ import { ClientSessionImpl, Reconnectable } from "./private/client_session_impl"
|
|
|
18
18
|
import { ClientSubscriptionImpl } from "./private/client_subscription_impl";
|
|
19
19
|
import { IClientBase } from "./private/i_private_client";
|
|
20
20
|
|
|
21
|
-
const debugLog = make_debugLog(
|
|
22
|
-
const doDebug = checkDebugFlag(
|
|
23
|
-
const errorLog = make_errorLog(
|
|
24
|
-
const warningLog = make_warningLog(
|
|
21
|
+
const debugLog = make_debugLog("RECONNECTION");
|
|
22
|
+
const doDebug = checkDebugFlag("RECONNECTION");
|
|
23
|
+
const errorLog = make_errorLog("RECONNECTION");
|
|
24
|
+
const warningLog = make_warningLog("RECONNECTION");
|
|
25
25
|
|
|
26
26
|
//
|
|
27
27
|
// a new secure channel has be created, we need to reactivate the corresponding session,
|
|
@@ -167,6 +167,9 @@ function repair_client_session_by_recreating_a_new_session(
|
|
|
167
167
|
session: ClientSessionImpl,
|
|
168
168
|
callback: (err?: Error) => void
|
|
169
169
|
) {
|
|
170
|
+
if (session._client && session._client.isUnusable()) {
|
|
171
|
+
return callback(new Error("Client is unusable"));
|
|
172
|
+
}
|
|
170
173
|
// As we don"t know if server has been rebooted or not,
|
|
171
174
|
// and may be upgraded in between, we have to invalidate the extra data type manager
|
|
172
175
|
invalidateExtraDataTypeManager(session);
|
|
@@ -215,25 +218,25 @@ function repair_client_session_by_recreating_a_new_session(
|
|
|
215
218
|
newSession,
|
|
216
219
|
newSession.userIdentityInfo!,
|
|
217
220
|
(err: Error | null, session1?: ClientSessionImpl) => {
|
|
218
|
-
doDebug &&
|
|
219
|
-
debugLog(
|
|
220
|
-
chalk.bgWhite.cyan(" => activating a new session .... Done err=", err ? err.message : "null")
|
|
221
|
-
);
|
|
221
|
+
doDebug && debugLog(" => activating a new session .... Done err=", err ? err.message : "null");
|
|
222
222
|
if (err) {
|
|
223
223
|
doDebug &&
|
|
224
224
|
debugLog(
|
|
225
|
-
|
|
226
|
-
"reactivation of the new session has failed: let be smart and close it before failing this repair attempt"
|
|
227
|
-
)
|
|
225
|
+
"reactivation of the new session has failed: let be smart and close it before failing this repair attempt"
|
|
228
226
|
);
|
|
229
227
|
// but just on the server side, not on the client side
|
|
230
228
|
const closeSessionRequest = new CloseSessionRequest({
|
|
229
|
+
requestHeader: {
|
|
230
|
+
authenticationToken: newSession.authenticationToken
|
|
231
|
+
},
|
|
231
232
|
deleteSubscriptions: true
|
|
232
233
|
});
|
|
233
|
-
|
|
234
|
+
newSession._client!.performMessageTransaction(closeSessionRequest, (err2?: Error | null) => {
|
|
234
235
|
if (err2) {
|
|
235
236
|
warningLog("closing session", err2.message);
|
|
236
237
|
}
|
|
238
|
+
doDebug && debugLog("the temporary replacement session is now closed");
|
|
239
|
+
doDebug && debugLog(" err ", err.message, "propagated upwards");
|
|
237
240
|
innerCallback(err);
|
|
238
241
|
});
|
|
239
242
|
} else {
|
|
@@ -384,6 +387,7 @@ function repair_client_session_by_recreating_a_new_session(
|
|
|
384
387
|
}
|
|
385
388
|
],
|
|
386
389
|
(err) => {
|
|
390
|
+
doDebug && err && debugLog("repair_client_session_by_recreating_a_new_session failed with ", err.message);
|
|
387
391
|
callback(err!);
|
|
388
392
|
}
|
|
389
393
|
);
|
|
@@ -393,7 +397,9 @@ function _repair_client_session(client: IClientBase, session: ClientSessionImpl,
|
|
|
393
397
|
const callback2 = (err2?: Error) => {
|
|
394
398
|
doDebug &&
|
|
395
399
|
debugLog("Session repair completed with err: ", err2 ? err2.message : "<no error>", session.sessionId.toString());
|
|
396
|
-
|
|
400
|
+
if (!err2) {
|
|
401
|
+
session.emit("session_repaired");
|
|
402
|
+
}
|
|
397
403
|
callback(err2);
|
|
398
404
|
};
|
|
399
405
|
|
|
@@ -420,53 +426,71 @@ function _repair_client_session(client: IClientBase, session: ClientSessionImpl,
|
|
|
420
426
|
type EmptyCallback = (err?: Error) => void;
|
|
421
427
|
|
|
422
428
|
export function repair_client_session(client: IClientBase, session: ClientSessionImpl, callback: EmptyCallback): void {
|
|
429
|
+
|
|
423
430
|
if (!client) {
|
|
424
431
|
doDebug && debugLog("Aborting reactivation of old session because user requested session to be close");
|
|
425
432
|
return callback();
|
|
426
433
|
}
|
|
434
|
+
|
|
427
435
|
doDebug && debugLog(chalk.yellow("Starting client session repair"));
|
|
436
|
+
|
|
428
437
|
const privateSession = session as any as Reconnectable;
|
|
429
438
|
privateSession._reconnecting = privateSession._reconnecting || { reconnecting: false, pendingCallbacks: [] };
|
|
439
|
+
|
|
430
440
|
if (privateSession._reconnecting.reconnecting) {
|
|
431
441
|
doDebug && debugLog(chalk.bgCyan("Reconnecting already happening for session"), session.sessionId.toString());
|
|
432
442
|
privateSession._reconnecting.pendingCallbacks.push(callback);
|
|
433
443
|
return;
|
|
434
444
|
}
|
|
445
|
+
|
|
435
446
|
privateSession._reconnecting.reconnecting = true;
|
|
436
447
|
|
|
437
448
|
// get old transaction queue ...
|
|
438
449
|
const transactionQueue = privateSession.pendingTransactions ? privateSession.pendingTransactions.splice(0) : [];
|
|
439
450
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
451
|
+
|
|
452
|
+
const repeatedAction = (callback: EmptyCallback) => {
|
|
453
|
+
_repair_client_session(client, session, (err) => {
|
|
454
|
+
if (err) {
|
|
455
|
+
errorLog(
|
|
456
|
+
chalk.red("session restoration has failed! err ="),
|
|
457
|
+
err.message,
|
|
458
|
+
session.sessionId.toString(),
|
|
459
|
+
" => Let's retry"
|
|
460
|
+
);
|
|
461
|
+
if (!session.hasBeenClosed()) {
|
|
462
|
+
|
|
463
|
+
const delay = 2000;
|
|
464
|
+
errorLog(chalk.red(`... will retry session repair... in ${delay} ms`));
|
|
465
|
+
setTimeout(() => {
|
|
466
|
+
errorLog(chalk.red("Retrying session repair..."));
|
|
467
|
+
repeatedAction(callback);
|
|
468
|
+
}, delay);
|
|
469
|
+
return;
|
|
470
|
+
} else {
|
|
471
|
+
console.log(chalk.red("session restoration should be interrupted because session has been closed forcefully"));
|
|
472
|
+
// session does not need to be repaired anymore
|
|
473
|
+
callback();
|
|
474
|
+
}
|
|
475
|
+
return;
|
|
456
476
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
477
|
+
|
|
478
|
+
console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DELETE ME");
|
|
479
|
+
privateSession._reconnecting.reconnecting = false;
|
|
480
|
+
errorLog("Session has been restored");
|
|
481
|
+
doDebug && debugLog(chalk.yellow("session has been restored"), session.sessionId.toString());
|
|
482
|
+
session.emit("session_restored");
|
|
483
|
+
const otherCallbacks = privateSession._reconnecting.pendingCallbacks;
|
|
484
|
+
privateSession._reconnecting.pendingCallbacks = [];
|
|
485
|
+
|
|
486
|
+
// re-inject element in queue
|
|
487
|
+
doDebug && debugLog(chalk.yellow("re-injecting transaction queue"), transactionQueue.length);
|
|
488
|
+
transactionQueue.forEach((e: any) => privateSession.pendingTransactions.push(e));
|
|
489
|
+
otherCallbacks.forEach((c: EmptyCallback) => c(err));
|
|
490
|
+
callback(err);
|
|
491
|
+
});
|
|
492
|
+
};
|
|
493
|
+
repeatedAction(callback);
|
|
470
494
|
}
|
|
471
495
|
|
|
472
496
|
export function repair_client_sessions(client: IClientBase, callback: (err?: Error) => void): void {
|
|
@@ -475,11 +499,13 @@ export function repair_client_sessions(client: IClientBase, callback: (err?: Err
|
|
|
475
499
|
doDebug && debugLog(chalk.red.bgWhite(" Starting sessions reactivation", sessions.length));
|
|
476
500
|
async.map(
|
|
477
501
|
sessions,
|
|
478
|
-
(session, next: (err
|
|
479
|
-
repair_client_session(client, session as ClientSessionImpl,
|
|
502
|
+
(session, next: (err: Error | null, err2: Error | null | undefined) => void) => {
|
|
503
|
+
repair_client_session(client, session as ClientSessionImpl, (err) => {
|
|
504
|
+
next(null, err);
|
|
505
|
+
});
|
|
480
506
|
},
|
|
481
|
-
(err) => {
|
|
482
|
-
err && errorLog("sessions reactivation completed: err ", err ? err.message : "null");
|
|
507
|
+
(err, allErrors: (undefined | Error | null)[] | undefined) => {
|
|
508
|
+
err && errorLog("sessions reactivation completed with err: err ", err ? err.message : "null");
|
|
483
509
|
return callback(err!);
|
|
484
510
|
}
|
|
485
511
|
);
|