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.
@@ -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(__filename);
22
- const doDebug = checkDebugFlag(__filename);
23
- const errorLog = make_errorLog(__filename);
24
- const warningLog = make_warningLog(__filename);
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
- chalk.bgWhite.cyan(
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
- session.performMessageTransaction(closeSessionRequest, (err2?: Error | null) => {
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
- session.emit("session_repaired");
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
- _repair_client_session(client, session, (err) => {
441
- privateSession._reconnecting.reconnecting = false;
442
- if (err) {
443
- errorLog(
444
- chalk.red("session restoration has failed! err ="),
445
- err.message,
446
- session.sessionId.toString(),
447
- " => Let's retry"
448
- );
449
- if (!session.hasBeenClosed()) {
450
- setTimeout(() => {
451
- _repair_client_session(client, session, callback);
452
- }, 2000);
453
- } else {
454
- // session does not need to be repaired anymore
455
- callback();
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
- return;
458
- }
459
- doDebug && debugLog(chalk.yellow("session has been restored"), session.sessionId.toString());
460
- session.emit("session_restored");
461
- const otherCallbacks = privateSession._reconnecting.pendingCallbacks;
462
- privateSession._reconnecting.pendingCallbacks = [];
463
-
464
- // re-inject element in queue
465
- doDebug && debugLog(chalk.yellow("re-injecting transaction queue"), transactionQueue.length);
466
- transactionQueue.forEach((e: any) => privateSession.pendingTransactions.push(e));
467
- otherCallbacks.forEach((c: EmptyCallback) => c(err));
468
- callback(err);
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?: Error) => void) => {
479
- repair_client_session(client, session as ClientSessionImpl, next);
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
  );