node-opcua-client 2.123.0 → 2.124.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 (49) hide show
  1. package/dist/alarms_and_conditions/client_alarm_tools.js.map +1 -1
  2. package/dist/alarms_and_conditions/client_tools.js.map +1 -1
  3. package/dist/client_monitored_item_toolbox.js.map +1 -1
  4. package/dist/client_session_keepalive_manager.js.map +1 -1
  5. package/dist/client_utils.js.map +1 -1
  6. package/dist/private/client_base_impl.d.ts +11 -4
  7. package/dist/private/client_base_impl.js +130 -70
  8. package/dist/private/client_base_impl.js.map +1 -1
  9. package/dist/private/client_monitored_item_group_impl.js.map +1 -1
  10. package/dist/private/client_monitored_item_impl.js.map +1 -1
  11. package/dist/private/client_publish_engine.d.ts +9 -4
  12. package/dist/private/client_publish_engine.js +5 -99
  13. package/dist/private/client_publish_engine.js.map +1 -1
  14. package/dist/private/client_session_impl.d.ts +20 -4
  15. package/dist/private/client_session_impl.js +5 -24
  16. package/dist/private/client_session_impl.js.map +1 -1
  17. package/dist/private/client_subscription_impl.d.ts +5 -8
  18. package/dist/private/client_subscription_impl.js +83 -174
  19. package/dist/private/client_subscription_impl.js.map +1 -1
  20. package/dist/private/i_private_client.d.ts +0 -1
  21. package/dist/private/opcua_client_impl.js +1 -1
  22. package/dist/private/opcua_client_impl.js.map +1 -1
  23. package/dist/private/performance.js.map +1 -1
  24. package/dist/private/reconnection/client_publish_engine_reconnection.d.ts +2 -0
  25. package/dist/private/reconnection/client_publish_engine_reconnection.js +118 -0
  26. package/dist/private/reconnection/client_publish_engine_reconnection.js.map +1 -0
  27. package/dist/private/reconnection/client_reconnection.d.ts +2 -0
  28. package/dist/private/reconnection/client_reconnection.js +20 -0
  29. package/dist/private/reconnection/client_reconnection.js.map +1 -0
  30. package/dist/private/reconnection/client_subscription_reconnection.d.ts +7 -0
  31. package/dist/private/reconnection/client_subscription_reconnection.js +124 -0
  32. package/dist/private/reconnection/client_subscription_reconnection.js.map +1 -0
  33. package/dist/private/reconnection/reconnection.d.ts +12 -0
  34. package/dist/private/reconnection/reconnection.js +564 -0
  35. package/dist/private/reconnection/reconnection.js.map +1 -0
  36. package/dist/tools/findservers.js.map +1 -1
  37. package/dist/tools/read_history_server_capabilities.js.map +1 -1
  38. package/dist/verify.js.map +1 -1
  39. package/package.json +8 -8
  40. package/source/private/client_base_impl.ts +136 -81
  41. package/source/private/client_publish_engine.ts +13 -129
  42. package/source/private/client_session_impl.ts +23 -30
  43. package/source/private/client_subscription_impl.ts +85 -207
  44. package/source/private/i_private_client.ts +0 -2
  45. package/source/private/opcua_client_impl.ts +1 -1
  46. package/source/private/reconnection/client_publish_engine_reconnection.ts +146 -0
  47. package/source/private/reconnection/client_reconnection.ts +17 -0
  48. package/source/private/reconnection/client_subscription_reconnection.ts +147 -0
  49. package/source/{reconnection.ts → private/reconnection/reconnection.ts} +120 -72
@@ -0,0 +1,147 @@
1
+ import async from "async";
2
+ import assert from "node-opcua-assert";
3
+ import { TimestampsToReturn } from "node-opcua-data-value";
4
+ import { make_debugLog, checkDebugFlag } from "node-opcua-debug";
5
+ import { warningLog } from "node-opcua-pki";
6
+ import { MonitoredItemCreateRequestOptions, CreateMonitoredItemsRequest, CreateMonitoredItemsResponse } from "node-opcua-types";
7
+ import { ErrorCallback } from "node-opcua-status-code";
8
+
9
+ import {
10
+ IBasicSessionReadAsync,
11
+ IBasicSessionWithSubscription,
12
+ createMonitoredItemsLimit,
13
+ readOperationLimits
14
+ } from "node-opcua-pseudo-session";
15
+ import { ClientSubscription } from "../../client_subscription";
16
+ import { ClientMonitoredItemImpl } from "../client_monitored_item_impl";
17
+ import { ClientSubscriptionImpl, TERMINATED_SUBSCRIPTION_ID, __create_subscription } from "../client_subscription_impl";
18
+ import { _shouldNotContinue } from "./reconnection";
19
+
20
+ const debugLog = make_debugLog("RECONNECTION");
21
+ const doDebug = checkDebugFlag("RECONNECTION");
22
+
23
+ function createMonitoredItemsAndRespectOperationalLimits(
24
+ session: IBasicSessionReadAsync & IBasicSessionWithSubscription,
25
+ createMonitorItemsRequest: CreateMonitoredItemsRequest,
26
+ callback: (err: Error | null, response?: CreateMonitoredItemsResponse) => void
27
+ ) {
28
+ readOperationLimits(session)
29
+ .then((operationalLimits) => {
30
+ createMonitoredItemsLimit(operationalLimits.maxMonitoredItemsPerCall || 0, session, createMonitorItemsRequest)
31
+ .then((createMonitoredItemResponse) => callback(null, createMonitoredItemResponse))
32
+ .catch(callback);
33
+ })
34
+ .catch(callback);
35
+ }
36
+
37
+ /**
38
+ * utility function to recreate new subscription
39
+ * @method recreateSubscriptionAndMonitoredItem
40
+ */
41
+ export function recreateSubscriptionAndMonitoredItem(_subscription: ClientSubscription, callback: ErrorCallback): void {
42
+ debugLog("recreateSubscriptionAndMonitoredItem", _subscription.subscriptionId.toString());
43
+
44
+ const subscription = _subscription as ClientSubscriptionImpl;
45
+ if (subscription.subscriptionId === TERMINATED_SUBSCRIPTION_ID) {
46
+ debugLog("Subscription is not in a valid state");
47
+ return callback();
48
+ }
49
+
50
+ const oldMonitoredItems = subscription.monitoredItems;
51
+ const oldSubscriptionId = subscription.subscriptionId;
52
+
53
+
54
+
55
+ subscription.publishEngine.unregisterSubscription(oldSubscriptionId);
56
+
57
+ async.series(
58
+ [
59
+ (innerCallback: ErrorCallback) => {
60
+ __create_subscription(subscription, innerCallback);
61
+ },
62
+ (innerCallback: ErrorCallback) => {
63
+ // prettier-ignore
64
+ { const _err = _shouldNotContinue(subscription.session); if (_err) { return innerCallback(_err); } }
65
+
66
+ const test = subscription.publishEngine.getSubscription(subscription.subscriptionId);
67
+
68
+ debugLog("recreating ", Object.keys(oldMonitoredItems).length, " monitored Items");
69
+ // re-create monitored items
70
+ const itemsToCreate: MonitoredItemCreateRequestOptions[] = [];
71
+
72
+ for (const monitoredItem of Object.values(oldMonitoredItems)) {
73
+ assert(monitoredItem.monitoringParameters.clientHandle > 0);
74
+ itemsToCreate.push({
75
+ itemToMonitor: monitoredItem.itemToMonitor,
76
+ monitoringMode: monitoredItem.monitoringMode,
77
+ requestedParameters: monitoredItem.monitoringParameters
78
+ });
79
+ }
80
+
81
+ const createMonitorItemsRequest = new CreateMonitoredItemsRequest({
82
+ itemsToCreate,
83
+ subscriptionId: subscription.subscriptionId,
84
+ timestampsToReturn: TimestampsToReturn.Both // this.timestampsToReturn,
85
+ });
86
+
87
+ const session = subscription.session;
88
+ // istanbul ignore next
89
+ if (!session) {
90
+ return innerCallback(new Error("no session"));
91
+ }
92
+
93
+ debugLog("Recreating ", itemsToCreate.length, " monitored items");
94
+
95
+ createMonitoredItemsAndRespectOperationalLimits(
96
+ session,
97
+ createMonitorItemsRequest,
98
+ (err: Error | null, response?: CreateMonitoredItemsResponse) => {
99
+ if (err) {
100
+ debugLog("Recreating monitored item has failed with ", err.message);
101
+ return innerCallback(err);
102
+ }
103
+ /* istanbul ignore next */
104
+ if (!response) {
105
+ return innerCallback(new Error("Internal Error"));
106
+ }
107
+ const monitoredItemResults = response.results || [];
108
+
109
+ let _errCount = 0;
110
+ monitoredItemResults.forEach((monitoredItemResult, index) => {
111
+ const itemToCreate = itemsToCreate[index];
112
+ /* istanbul ignore next */
113
+ if (!itemToCreate || !itemToCreate.requestedParameters) {
114
+ _errCount++;
115
+ return;
116
+ }
117
+ const clientHandle = itemToCreate.requestedParameters.clientHandle;
118
+ /* istanbul ignore next */
119
+ if (!clientHandle) {
120
+ _errCount++;
121
+ return;
122
+ }
123
+ const monitoredItem = subscription.monitoredItems[clientHandle] as ClientMonitoredItemImpl;
124
+ if (monitoredItem) {
125
+ monitoredItem._applyResult(monitoredItemResult);
126
+ } else {
127
+ _errCount++;
128
+ warningLog("cannot find monitored item for clientHandle !:", clientHandle);
129
+ warningLog("itemsToCreate = ", itemsToCreate[index].toString());
130
+ }
131
+ });
132
+ if (_errCount > 0) {
133
+ warningLog("Warning: some monitored items have not been recreated properly");
134
+ }
135
+ innerCallback();
136
+ }
137
+ );
138
+ }
139
+ ],
140
+ (err) => {
141
+ if (err) {
142
+ warningLog("!!recreateSubscriptionAndMonitoredItem has failed", err.message);
143
+ }
144
+ callback(err!);
145
+ }
146
+ );
147
+ }
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  // tslint:disable:only-arrow-functions
6
- import * as async from "async";
6
+ import async from "async";
7
7
  import chalk from "chalk";
8
8
  import { assert } from "node-opcua-assert";
9
9
  import { checkDebugFlag, make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
@@ -13,16 +13,37 @@ import { ErrorCallback } from "node-opcua-status-code";
13
13
  import { CloseSessionRequest } from "node-opcua-types";
14
14
  import { invalidateExtraDataTypeManager } from "node-opcua-client-dynamic-extension-object";
15
15
 
16
- import { SubscriptionId } from "./client_session";
17
- import { ClientSessionImpl, Reconnectable } from "./private/client_session_impl";
18
- import { ClientSubscriptionImpl } from "./private/client_subscription_impl";
19
- import { IClientBase } from "./private/i_private_client";
16
+ import { SubscriptionId } from "../../client_session";
17
+ import { ClientSessionImpl, Reconnectable } from "../client_session_impl";
18
+ import { ClientSubscriptionImpl } from "../client_subscription_impl";
19
+ import { IClientBase } from "../i_private_client";
20
+ import { republish } from "./client_publish_engine_reconnection";
21
+ import { recreateSubscriptionAndMonitoredItem } from "./client_subscription_reconnection";
20
22
 
21
23
  const debugLog = make_debugLog("RECONNECTION");
22
24
  const doDebug = checkDebugFlag("RECONNECTION");
23
25
  const errorLog = make_errorLog("RECONNECTION");
24
26
  const warningLog = make_warningLog("RECONNECTION");
25
27
 
28
+ function _shouldNotContinue3(client: IClientBase) {
29
+ if (!client._secureChannel) {
30
+ return new Error("Failure during reconnection : client or session is not usable anymore");
31
+ }
32
+ return null;
33
+ }
34
+
35
+ export function _shouldNotContinue(session: ClientSessionImpl) {
36
+ if (!session._client || session.hasBeenClosed() || !session._client._secureChannel || session._client.isUnusable()) {
37
+ return new Error("Failure during reconnection : client or session is not usable anymore");
38
+ }
39
+ return null;
40
+ }
41
+ export function _shouldNotContinue2(subscription: ClientSubscriptionImpl) {
42
+ if (!subscription.hasSession) {
43
+ return new Error("Failure during reconnection : client or session is not usable anymore");
44
+ }
45
+ return _shouldNotContinue(subscription.session);
46
+ }
26
47
  //
27
48
  // a new secure channel has be created, we need to reactivate the corresponding session,
28
49
  // and reestablish the subscription and restart the publish engine.
@@ -109,29 +130,26 @@ const warningLog = make_warningLog("RECONNECTION");
109
130
  // +-------------------------------+
110
131
 
111
132
  function _ask_for_subscription_republish(session: ClientSessionImpl, callback: (err?: Error) => void) {
112
- if (session.hasBeenClosed()) {
113
- doDebug && debugLog("_ask_for_subscription_republish : session is closed");
114
- return callback(new Error("askForSubscriptionRepublish => canceled because session is closed"));
115
- }
133
+ // prettier-ignore
134
+ { const err = _shouldNotContinue(session); if (err) { return callback(err); } }
116
135
 
117
136
  doDebug && debugLog(chalk.bgCyan.yellow.bold("_ask_for_subscription_republish "));
118
137
  // assert(session.getPublishEngine().nbPendingPublishRequests === 0,
119
138
  // "at this time, publish request queue shall still be empty");
120
139
 
121
- session.getPublishEngine().republish((err?: Error) => {
140
+ const engine = session.getPublishEngine();
141
+ republish(engine, (err?: Error) => {
122
142
  doDebug && debugLog("_ask_for_subscription_republish : republish sent");
123
- if (session.hasBeenClosed()) {
124
- return callback(new Error("Cannot complete subscription republish due to session termination"));
125
- }
143
+ // prettier-ignore
144
+ { const err = _shouldNotContinue(session); if (err) { return callback(err); } }
145
+
126
146
  doDebug && debugLog(chalk.bgCyan.green.bold("_ask_for_subscription_republish done "), err ? err.message : "OK");
127
147
  if (err) {
128
148
  warningLog("republish has failed with error :", err.message);
129
-
130
149
  doDebug && debugLog("_ask_for_subscription_republish has : recreating subscription");
131
150
  return repair_client_session_by_recreating_a_new_session(session._client!, session, callback);
132
151
  }
133
- // xx assert(session.getPublishEngine().nbPendingPublishRequests === 0);
134
- session.resumePublishEngine();
152
+
135
153
  callback(err);
136
154
  });
137
155
  }
@@ -141,18 +159,16 @@ function create_session_and_repeat_if_failed(
141
159
  session: ClientSessionImpl,
142
160
  callback: CallbackT<ClientSessionImpl>
143
161
  ) {
144
- if (session.hasBeenClosed()) {
145
- doDebug && debugLog("Cannot complete subscription republish due to session termination");
146
- return callback(new Error("Cannot complete subscription republish due to session termination"));
147
- }
162
+ // prettier-ignore
163
+ { const err = _shouldNotContinue(session); if (err) { return callback(err); } }
164
+
148
165
  doDebug && debugLog(chalk.bgWhite.red(" => creating a new session ...."));
149
166
  // create new session, based on old session,
150
167
  // so we can reuse subscriptions data
151
168
  client.__createSession_step2(session, (err: Error | null, session1?: ClientSessionImpl) => {
152
- if (err && session.hasBeenClosed()) {
153
- doDebug && debugLog("Cannot complete subscription republish due to session termination");
154
- return callback(new Error("Cannot complete subscription republish due to session termination"));
155
- }
169
+ // prettier-ignore
170
+ { const err = _shouldNotContinue(session); if (err) { return callback(err); } }
171
+
156
172
  if (!err && session1) {
157
173
  assert(session === session1, "session should have been recycled");
158
174
  callback(err, session);
@@ -169,9 +185,9 @@ function repair_client_session_by_recreating_a_new_session(
169
185
  session: ClientSessionImpl,
170
186
  callback: (err?: Error) => void
171
187
  ) {
172
- if (session._client && session._client.isUnusable()) {
173
- return callback(new Error("Client is unusable"));
174
- }
188
+ // prettier-ignore
189
+ { const err = _shouldNotContinue(session); if (err) { return callback(err); } }
190
+
175
191
  // As we don"t know if server has been rebooted or not,
176
192
  // and may be upgraded in between, we have to invalidate the extra data type manager
177
193
  invalidateExtraDataTypeManager(session);
@@ -181,13 +197,6 @@ function repair_client_session_by_recreating_a_new_session(
181
197
  debugLog(" repairing client session by_recreating a new session for old session ", session.sessionId.toString());
182
198
  }
183
199
 
184
- // TO DO : it is possible that session is already closed while we get there
185
- if (session.hasBeenClosed()) {
186
- // istanbul ignore next
187
- doDebug && debugLog(chalk.bgWhite.red("Aborting reactivation of old session because user requested session to be closed"));
188
- return callback(new Error("reconnection cancelled due to session termination"));
189
- }
190
-
191
200
  let newSession: ClientSessionImpl;
192
201
 
193
202
  const listenerCountBefore = session.listenerCount("");
@@ -196,27 +205,40 @@ function repair_client_session_by_recreating_a_new_session(
196
205
  async.forEach(
197
206
  subscriptionsToRecreate,
198
207
  (subscriptionId: SubscriptionId, next: ErrorCallback) => {
208
+ // prettier-ignore
209
+ { const err = _shouldNotContinue(session); if (err) { return next(err); } }
210
+
199
211
  if (!session.getPublishEngine().hasSubscription(subscriptionId)) {
200
212
  doDebug && debugLog(chalk.red(" => CANNOT RECREATE SUBSCRIPTION "), subscriptionId);
201
213
  return next();
202
214
  }
203
215
  const subscription = session.getPublishEngine().getSubscription(subscriptionId);
204
- assert(subscription.constructor.name === "ClientSubscriptionImpl");
205
216
  doDebug && debugLog(chalk.red(" => RECREATING SUBSCRIPTION "), subscriptionId);
206
- assert(subscription.session === newSession, "must have the session");
217
+ assert(subscription.session === newSession, "must have the new session");
218
+
219
+ recreateSubscriptionAndMonitoredItem(subscription, (err1?: Error) => {
220
+ // prettier-ignore
221
+ { const err = _shouldNotContinue(session); if (err) { return next(err); } }
207
222
 
208
- (subscription as ClientSubscriptionImpl).recreateSubscriptionAndMonitoredItem((err1?: Error) => {
209
223
  if (err1) {
210
224
  doDebug && debugLog("_recreateSubscription failed !" + err1.message);
211
225
  }
212
226
 
213
227
  doDebug &&
214
- debugLog(chalk.cyan(" => RECREATING SUBSCRIPTION AND MONITORED ITEM DONE "), subscriptionId);
228
+ debugLog(
229
+ chalk.cyan(" => RECREATING SUBSCRIPTION AND MONITORED ITEM DONE subscriptionId="),
230
+ subscriptionId
231
+ );
215
232
 
216
233
  next();
217
234
  });
218
235
  },
219
236
  (err1?: Error | null) => {
237
+ // prettier-ignore
238
+ { const err = _shouldNotContinue(session); if (err) { return innerCallback(err); } }
239
+ if (!err1) {
240
+ // prettier-ignore
241
+ }
220
242
  innerCallback(err1!);
221
243
  }
222
244
  );
@@ -225,9 +247,9 @@ function repair_client_session_by_recreating_a_new_session(
225
247
  async.series(
226
248
  [
227
249
  function suspend_old_session_publish_engine(innerCallback: ErrorCallback) {
228
- if (session.hasBeenClosed()) {
229
- return innerCallback(new Error("Cannot complete subscription republish due to session termination"));
230
- }
250
+ // prettier-ignore
251
+ { const err = _shouldNotContinue(session); if (err) { return innerCallback(err); } }
252
+
231
253
  // istanbul ignore next
232
254
  doDebug && debugLog(chalk.bgWhite.red(" => suspend old session publish engine...."));
233
255
  session.getPublishEngine().suspend(true);
@@ -236,6 +258,9 @@ function repair_client_session_by_recreating_a_new_session(
236
258
 
237
259
  function create_new_session(innerCallback: ErrorCallback) {
238
260
  create_session_and_repeat_if_failed(client, session, (err?: Error | null, _newSession?: ClientSessionImpl) => {
261
+ // prettier-ignore
262
+ { const err = _shouldNotContinue(session); if (err) { return innerCallback(err); } }
263
+
239
264
  if (_newSession) {
240
265
  newSession = _newSession;
241
266
  }
@@ -244,9 +269,9 @@ function repair_client_session_by_recreating_a_new_session(
244
269
  },
245
270
 
246
271
  function activate_new_session(innerCallback: ErrorCallback) {
247
- if (session.hasBeenClosed()) {
248
- return innerCallback(new Error("Cannot complete subscription republish due to session termination"));
249
- }
272
+ // prettier-ignore
273
+ { const err = _shouldNotContinue(session); if (err) { return innerCallback(err); } }
274
+
250
275
  doDebug && debugLog(chalk.bgWhite.red(" => activating a new session ...."));
251
276
 
252
277
  client._activateSession(
@@ -285,9 +310,9 @@ function repair_client_session_by_recreating_a_new_session(
285
310
  },
286
311
 
287
312
  function attempt_subscription_transfer(innerCallback: ErrorCallback) {
288
- if (session.hasBeenClosed()) {
289
- return innerCallback(new Error("Cannot complete subscription republish due to session termination"));
290
- }
313
+ // prettier-ignore
314
+ { const err = _shouldNotContinue(session); if (err) { return innerCallback(err); } }
315
+
291
316
  // get the old subscriptions id from the old session
292
317
  const subscriptionsIds = session.getPublishEngine().getSubscriptionIds();
293
318
 
@@ -310,8 +335,11 @@ function repair_client_session_by_recreating_a_new_session(
310
335
  newSession.transferSubscriptions(
311
336
  subscriptionsToTransfer,
312
337
  (err: Error | null, transferSubscriptionsResponse?: TransferSubscriptionsResponse) => {
338
+ // may be the connection with server has been disconnected
339
+ // prettier-ignore
340
+ { const err = _shouldNotContinue(session); if (err) { return innerCallback(err); } }
341
+
313
342
  if (err || !transferSubscriptionsResponse) {
314
- warningLog(chalk.bgCyan("Warning TransferSubscription has failed " + err?.message));
315
343
  warningLog(chalk.bgCyan("May be the server is not supporting this feature"));
316
344
  // when transfer subscription has failed, we have no other choice but
317
345
  // recreate the subscriptions on the server side
@@ -367,9 +395,9 @@ function repair_client_session_by_recreating_a_new_session(
367
395
  },
368
396
 
369
397
  function ask_for_subscription_republish(innerCallback: ErrorCallback) {
370
- if (session.hasBeenClosed()) {
371
- return innerCallback(new Error("Cannot complete subscription republish due to session termination"));
372
- }
398
+ // prettier-ignore
399
+ { const err = _shouldNotContinue(session); if (err) { return innerCallback(err); } }
400
+
373
401
  // assert(newSession.getPublishEngine().nbPendingPublishRequests === 0, "we should not be publishing here");
374
402
  // call Republish
375
403
  return _ask_for_subscription_republish(newSession, (err) => {
@@ -381,10 +409,11 @@ function repair_client_session_by_recreating_a_new_session(
381
409
  },
382
410
 
383
411
  function start_publishing_as_normal(innerCallback: ErrorCallback) {
384
- if (session.hasBeenClosed()) {
385
- return innerCallback(new Error("Cannot complete subscription republish due to session termination"));
386
- }
412
+ // prettier-ignore
413
+ { const err = _shouldNotContinue(session); if (err) { return innerCallback(err); } }
414
+
387
415
  newSession.getPublishEngine().suspend(false);
416
+
388
417
  const listenerCountAfter = session.listenerCount("");
389
418
  assert(newSession === session);
390
419
  doDebug && debugLog("listenerCountBefore =", listenerCountBefore, "listenerCountAfter = ", listenerCountAfter);
@@ -404,6 +433,8 @@ function _repair_client_session(client: IClientBase, session: ClientSessionImpl,
404
433
  debugLog("Session repair completed with err: ", err2 ? err2.message : "<no error>", session.sessionId.toString());
405
434
  if (!err2) {
406
435
  session.emit("session_repaired");
436
+ } else {
437
+ session.emit("session_repaired_failed", err2);
407
438
  }
408
439
  callback(err2);
409
440
  };
@@ -412,7 +443,13 @@ function _repair_client_session(client: IClientBase, session: ClientSessionImpl,
412
443
  doDebug && debugLog(chalk.yellow(" TRYING TO REACTIVATE EXISTING SESSION"), session.sessionId.toString());
413
444
  doDebug && debugLog(" SubscriptionIds :", session.getPublishEngine().getSubscriptionIds());
414
445
  }
446
+
447
+ // prettier-ignore
448
+ { const err = _shouldNotContinue(session); if (err) { return callback(err); } }
449
+
415
450
  client._activateSession(session, session.userIdentityInfo!, (err: Error | null, session2?: ClientSessionImpl) => {
451
+ // prettier-ignore
452
+ { const err = _shouldNotContinue(session); if (err) { return callback(err); } }
416
453
  //
417
454
  // Note: current limitation :
418
455
  // - The reconnection doesn't work yet, if connection break is caused by a server that crashes and restarts.
@@ -435,14 +472,18 @@ export function repair_client_session(client: IClientBase, session: ClientSessio
435
472
  doDebug && debugLog("Aborting reactivation of old session because user requested session to be close");
436
473
  return callback();
437
474
  }
438
-
439
475
  doDebug && debugLog(chalk.yellow("Starting client session repair"));
440
476
 
441
477
  const privateSession = session as any as Reconnectable;
442
478
  privateSession._reconnecting = privateSession._reconnecting || { reconnecting: false, pendingCallbacks: [] };
443
479
 
480
+ if (session.hasBeenClosed()) {
481
+ privateSession._reconnecting.reconnecting = false;
482
+ doDebug && debugLog("Aborting reactivation of old session because session has been closed");
483
+ return callback();
484
+ }
444
485
  if (privateSession._reconnecting.reconnecting) {
445
- doDebug && debugLog(chalk.bgCyan("Reconnecting already happening for session"), session.sessionId.toString());
486
+ doDebug && debugLog(chalk.bgCyan("Reconnection is already happening for session"), session.sessionId.toString());
446
487
  privateSession._reconnecting.pendingCallbacks.push(callback);
447
488
  return;
448
489
  }
@@ -453,7 +494,13 @@ export function repair_client_session(client: IClientBase, session: ClientSessio
453
494
  const transactionQueue = privateSession.pendingTransactions ? privateSession.pendingTransactions.splice(0) : [];
454
495
 
455
496
  const repeatedAction = (callback: EmptyCallback) => {
497
+ // prettier-ignore
498
+ { const err = _shouldNotContinue(session); if (err) { return callback(err); }}
499
+
456
500
  _repair_client_session(client, session, (err) => {
501
+ // prettier-ignore
502
+ { const err = _shouldNotContinue(session); if (err) { return callback(err); } }
503
+
457
504
  if (err) {
458
505
  errorLog(
459
506
  chalk.red("session restoration has failed! err ="),
@@ -471,32 +518,30 @@ export function repair_client_session(client: IClientBase, session: ClientSessio
471
518
  return;
472
519
  } else {
473
520
  errorLog(chalk.red("session restoration should be interrupted because session has been closed forcefully"));
474
- // session does not need to be repaired anymore
475
- callback();
476
521
  }
522
+ // session does not need to be repaired anymore
523
+ callback();
477
524
  return;
478
525
  }
479
526
 
480
- privateSession._reconnecting.reconnecting = false;
481
-
482
527
  // istanbul ignore next
483
528
  doDebug && debugLog(chalk.yellow("session has been restored"), session.sessionId.toString());
484
-
485
529
  session.emit("session_restored");
486
- const otherCallbacks = privateSession._reconnecting.pendingCallbacks;
487
- privateSession._reconnecting.pendingCallbacks = [];
488
-
489
- // re-inject element in queue
490
-
491
- // istanbul ignore next
492
- doDebug && debugLog(chalk.yellow("re-injecting transaction queue"), transactionQueue.length);
493
-
494
- transactionQueue.forEach((e: any) => privateSession.pendingTransactions.push(e));
495
- otherCallbacks.forEach((c: EmptyCallback) => c(err));
496
530
  callback(err);
497
531
  });
498
532
  };
499
- repeatedAction(callback);
533
+ repeatedAction((err) => {
534
+ privateSession._reconnecting.reconnecting = false;
535
+
536
+ const otherCallbacks = privateSession._reconnecting.pendingCallbacks;
537
+ privateSession._reconnecting.pendingCallbacks = [];
538
+ // re-inject element in queue
539
+ // istanbul ignore next
540
+ doDebug && debugLog(chalk.yellow("re-injecting transaction queue"), transactionQueue.length);
541
+ transactionQueue.forEach((e: any) => privateSession.pendingTransactions.push(e));
542
+ otherCallbacks.forEach((c: EmptyCallback) => c(err));
543
+ callback(err);
544
+ });
500
545
  }
501
546
 
502
547
  export function repair_client_sessions(client: IClientBase, callback: (err?: Error) => void): void {
@@ -512,6 +557,9 @@ export function repair_client_sessions(client: IClientBase, callback: (err?: Err
512
557
  },
513
558
  (err, allErrors: (undefined | Error | null)[] | undefined) => {
514
559
  err && errorLog("sessions reactivation completed with err: err ", err ? err.message : "null");
560
+ // prettier-ignore
561
+ { const err = _shouldNotContinue3(client); if (err) { return callback(err); } }
562
+
515
563
  return callback(err!);
516
564
  }
517
565
  );