@celerispay/hazelcast-client 3.12.7-4 → 3.12.7-6
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.
|
@@ -139,6 +139,13 @@ export declare class ClientConnectionManager extends EventEmitter {
|
|
|
139
139
|
* Clears all stored credentials - used for single-node cluster reset
|
|
140
140
|
*/
|
|
141
141
|
clearAllCredentials(): void;
|
|
142
|
+
/**
|
|
143
|
+
* Clears the failed connections blocklist so previously failed addresses
|
|
144
|
+
* can be retried immediately. Called after a cluster reset to ensure
|
|
145
|
+
* async destroyConnection() calls don't re-block addresses that were
|
|
146
|
+
* just unblocked for reconnection.
|
|
147
|
+
*/
|
|
148
|
+
clearFailedConnections(): void;
|
|
142
149
|
/**
|
|
143
150
|
* Handles authentication errors by clearing failed connections and allowing retry
|
|
144
151
|
* @param address The address that had authentication issues
|
|
@@ -137,8 +137,10 @@ var ClientConnectionManager = /** @class */ (function (_super) {
|
|
|
137
137
|
_this.failedConnections.delete(address.toString());
|
|
138
138
|
return connection;
|
|
139
139
|
}).catch(function (error) {
|
|
140
|
-
// Check if it's an authentication error
|
|
141
|
-
|
|
140
|
+
// Check if it's an authentication error.
|
|
141
|
+
// error.message may be null when the server sends a null-message protocol error
|
|
142
|
+
// (e.g. ReferenceError: null from ErrorFactory), so we check for null explicitly.
|
|
143
|
+
var isAuthError = (error.message == null) || (error.message.includes('Invalid Credentials') ||
|
|
142
144
|
error.message.includes('authentication') ||
|
|
143
145
|
error.message.includes('credentials'));
|
|
144
146
|
if (isAuthError) {
|
|
@@ -486,6 +488,17 @@ var ClientConnectionManager = /** @class */ (function (_super) {
|
|
|
486
488
|
this.failedConnections.clear();
|
|
487
489
|
this.logger.info('ClientConnectionManager', '✅ All credentials cleared, ready for fresh authentication');
|
|
488
490
|
};
|
|
491
|
+
/**
|
|
492
|
+
* Clears the failed connections blocklist so previously failed addresses
|
|
493
|
+
* can be retried immediately. Called after a cluster reset to ensure
|
|
494
|
+
* async destroyConnection() calls don't re-block addresses that were
|
|
495
|
+
* just unblocked for reconnection.
|
|
496
|
+
*/
|
|
497
|
+
ClientConnectionManager.prototype.clearFailedConnections = function () {
|
|
498
|
+
var count = this.failedConnections.size;
|
|
499
|
+
this.failedConnections.clear();
|
|
500
|
+
this.logger.info('ClientConnectionManager', "\uD83D\uDD13 Cleared " + count + " failed connection entries, all addresses unblocked");
|
|
501
|
+
};
|
|
489
502
|
/**
|
|
490
503
|
* Handles authentication errors by clearing failed connections and allowing retry
|
|
491
504
|
* @param address The address that had authentication issues
|
|
@@ -98,9 +98,20 @@ export declare class ClusterService {
|
|
|
98
98
|
private onHeartbeatStopped(connection);
|
|
99
99
|
private triggerFailover();
|
|
100
100
|
/**
|
|
101
|
-
* Handles single-node
|
|
101
|
+
* Handles single-node node loss. Tears down all state immediately and starts
|
|
102
|
+
* a TCP probe loop. Only once the port accepts a raw TCP connection do we
|
|
103
|
+
* attempt the full Hazelcast handshake — eliminating the race between
|
|
104
|
+
* destroyConnection() re-adding failedConnections and our attempts to clear them.
|
|
102
105
|
*/
|
|
103
106
|
private handleSingleNodeClusterReset();
|
|
107
|
+
/**
|
|
108
|
+
* Probes the single-node address with a raw TCP socket every probeIntervalMs.
|
|
109
|
+
* When the port responds (connect event), destroys the probe socket and
|
|
110
|
+
* calls connectToCluster() to perform the full Hazelcast authentication.
|
|
111
|
+
* If connectToCluster() fails (server still warming up), retries the probe.
|
|
112
|
+
* Stops if the client is shut down.
|
|
113
|
+
*/
|
|
114
|
+
private startSingleNodeProbeLoop(address);
|
|
104
115
|
/**
|
|
105
116
|
* Handles multi-node failover - preserves existing logic
|
|
106
117
|
*/
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
var net = require("net");
|
|
18
19
|
var Promise = require("bluebird");
|
|
19
20
|
var ClientAddMembershipListenerCodec_1 = require("../codec/ClientAddMembershipListenerCodec");
|
|
20
21
|
var ClientInfo_1 = require("../ClientInfo");
|
|
@@ -264,43 +265,78 @@ var ClusterService = /** @class */ (function () {
|
|
|
264
265
|
}
|
|
265
266
|
};
|
|
266
267
|
/**
|
|
267
|
-
* Handles single-node
|
|
268
|
+
* Handles single-node node loss. Tears down all state immediately and starts
|
|
269
|
+
* a TCP probe loop. Only once the port accepts a raw TCP connection do we
|
|
270
|
+
* attempt the full Hazelcast handshake — eliminating the race between
|
|
271
|
+
* destroyConnection() re-adding failedConnections and our attempts to clear them.
|
|
268
272
|
*/
|
|
269
273
|
ClusterService.prototype.handleSingleNodeClusterReset = function () {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
// Clear all stored credentials - node restart means fresh cluster
|
|
273
|
-
this.client.getConnectionManager().clearAllCredentials();
|
|
274
|
-
// Reset client UUIDs - will be assigned fresh by server
|
|
274
|
+
this.logger.info('ClusterService', 'SINGLE-NODE: Node lost. Tearing down state and starting TCP probe loop.');
|
|
275
|
+
// Full state teardown
|
|
275
276
|
this.uuid = null;
|
|
276
277
|
this.ownerUuid = null;
|
|
277
|
-
|
|
278
|
-
this.
|
|
279
|
-
|
|
278
|
+
this.members = [];
|
|
279
|
+
this.client.getConnectionManager().clearAllCredentials();
|
|
280
|
+
this.client.getConnectionManager().clearFailedConnections();
|
|
280
281
|
this.client.getConnectionManager().forceCleanupDeadConnections();
|
|
281
|
-
// Clear partition information
|
|
282
282
|
this.client.getPartitionService().clearPartitionTable();
|
|
283
|
-
// IMPORTANT: Unblock all down addresses before attempting reconnection.
|
|
284
|
-
// The address was just marked as down by onConnectionClosed/onHeartbeatStopped,
|
|
285
|
-
// but connectToCluster() skips blocked addresses — so without clearing the block
|
|
286
|
-
// it will immediately fail with "Unable to connect to any address".
|
|
287
|
-
// clearAllCredentials() already clears failedConnections inside ConnectionManager.
|
|
288
|
-
this.logger.info('ClusterService', '🔓 SINGLE-NODE RESET: Unblocking all addresses for fresh reconnection...');
|
|
289
283
|
this.downAddresses.clear();
|
|
290
|
-
//
|
|
291
|
-
|
|
292
|
-
this.
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
284
|
+
// Start probing — reconnect only when the port actually accepts TCP
|
|
285
|
+
var address = this.knownAddresses[0];
|
|
286
|
+
this.startSingleNodeProbeLoop(address);
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* Probes the single-node address with a raw TCP socket every probeIntervalMs.
|
|
290
|
+
* When the port responds (connect event), destroys the probe socket and
|
|
291
|
+
* calls connectToCluster() to perform the full Hazelcast authentication.
|
|
292
|
+
* If connectToCluster() fails (server still warming up), retries the probe.
|
|
293
|
+
* Stops if the client is shut down.
|
|
294
|
+
*/
|
|
295
|
+
ClusterService.prototype.startSingleNodeProbeLoop = function (address) {
|
|
296
|
+
var _this = this;
|
|
297
|
+
var probeIntervalMs = 3000;
|
|
298
|
+
var host = address.host;
|
|
299
|
+
var port = address.port;
|
|
300
|
+
this.logger.info('ClusterService', "SINGLE-NODE PROBE: Waiting for " + host + ":" + port + " to accept connections (probing every " + probeIntervalMs + "ms)...");
|
|
301
|
+
var attempt = function () {
|
|
302
|
+
if (!_this.client.getLifecycleService().isRunning()) {
|
|
303
|
+
_this.logger.info('ClusterService', 'SINGLE-NODE PROBE: Client is shutting down, stopping probe loop.');
|
|
304
|
+
_this.failoverInProgress = false;
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
var socket = net.createConnection({ host: host, port: port });
|
|
308
|
+
socket.once('connect', function () {
|
|
309
|
+
socket.destroy();
|
|
310
|
+
_this.logger.info('ClusterService', "SINGLE-NODE PROBE: " + host + ":" + port + " is accepting connections. Reinitialising Hazelcast connection...");
|
|
311
|
+
// Clear both blocklists right before connecting — destroyConnection()
|
|
312
|
+
// may have re-added the address to failedConnections since the teardown above.
|
|
313
|
+
_this.downAddresses.clear();
|
|
314
|
+
_this.client.getConnectionManager().clearFailedConnections();
|
|
315
|
+
_this.connectToCluster()
|
|
316
|
+
.then(function () {
|
|
317
|
+
_this.logger.info('ClusterService', 'SINGLE-NODE: Reconnected successfully.');
|
|
318
|
+
_this.logCurrentState();
|
|
319
|
+
_this.failoverInProgress = false;
|
|
320
|
+
})
|
|
321
|
+
.catch(function (err) {
|
|
322
|
+
_this.logger.warn('ClusterService', "SINGLE-NODE: connectToCluster failed after probe success (" + err.message + "). Retrying probe...");
|
|
323
|
+
// Server accepted TCP but Hazelcast not fully ready yet — probe again
|
|
324
|
+
_this.downAddresses.clear();
|
|
325
|
+
_this.client.getConnectionManager().clearFailedConnections();
|
|
326
|
+
setTimeout(attempt, probeIntervalMs);
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
socket.once('error', function () {
|
|
330
|
+
socket.destroy();
|
|
331
|
+
setTimeout(attempt, probeIntervalMs);
|
|
332
|
+
});
|
|
333
|
+
// Guard against hung sockets that produce neither connect nor error
|
|
334
|
+
socket.setTimeout(2000, function () {
|
|
335
|
+
socket.destroy();
|
|
336
|
+
setTimeout(attempt, probeIntervalMs);
|
|
337
|
+
});
|
|
338
|
+
};
|
|
339
|
+
attempt();
|
|
304
340
|
};
|
|
305
341
|
/**
|
|
306
342
|
* Handles multi-node failover - preserves existing logic
|
package/package.json
CHANGED