@celerispay/hazelcast-client 3.12.5 → 3.12.7-2

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.
@@ -1,180 +1,260 @@
1
- # Hazelcast Node.js Client 3.12.5 - Release Summary
2
-
3
- ## 🎯 **Release Overview**
4
-
5
- **Version**: 3.12.5
6
- **Type**: Patch Release with Critical Fixes
7
- **Package Name**: `@celerispay/hazelcast-client`
8
- **Publisher**: CelerisPay
9
- **Compatibility**: 100% Backward Compatible with 3.12.x
10
-
11
- ## 🚨 **Critical Issues Fixed**
12
-
13
- This release addresses the critical connection failover problems that were causing production issues:
14
-
15
- 1. **Connection Bombardment** - Fixed increasing connection counts to failed nodes
16
- 2. **Hanging Invocations** - Fixed operations that would never complete or fail
17
- 3. **Poor Failover** - Fixed inability to switch to healthy nodes when partition owners go down
18
- 4. **Connection Leakage** - Fixed memory leaks from failed connections
19
- 5. **No Health Monitoring** - Added active connection health checking
20
- 6. **Repeated Failures** - Fixed repeated connection attempts to known failed nodes
21
-
22
- ## **What's New**
23
-
24
- ### **Connection Health Monitoring**
25
- - Active health checks every 5 seconds
26
- - Automatic detection and cleanup of broken connections
27
- - Prevention of using unhealthy connections
28
-
29
- ### **Enhanced Failover Logic**
30
- - Proper failover cooldown (5 seconds between attempts)
31
- - Structured failover process with error handling
32
- - Automatic partition table refresh on failures
33
-
34
- ### **Smart Retry Mechanism**
35
- - Connection retry with exponential backoff
36
- - Maximum retry limits to prevent infinite loops
37
- - Partition-specific failure handling
38
-
39
- ### **Address Blocking System**
40
- - Temporary blocking of failed addresses (30 seconds)
41
- - Prevents repeated connection attempts to failed nodes
42
- - Automatic unblocking after block duration
43
- - Intelligent tracking of down addresses
44
-
45
- ### **Improved Configuration**
46
- - Better default values for production use
47
- - Enhanced connection management properties
48
- - Configurable failover behavior
49
-
50
- ## 🔧 **Technical Improvements**
51
-
52
- ### **Files Modified**
53
- - `ClientConnectionManager.ts` - Connection health monitoring & retry logic
54
- - `ClusterService.ts` - Improved failover handling with address blocking
55
- - `PartitionService.ts` - Partition table management
56
- - `InvocationService.ts` - Enhanced retry logic
57
- - `Config.ts` - New configuration properties
58
- - `ClientNetworkConfig.ts` - Better network defaults
59
-
60
- ### **New Configuration Properties**
61
- ```javascript
62
- properties: {
63
- // Enhanced connection management
64
- 'hazelcast.client.connection.health.check.interval': 5000,
65
- 'hazelcast.client.connection.max.retries': 3,
66
- 'hazelcast.client.connection.retry.delay': 1000,
67
- 'hazelcast.client.failover.cooldown': 5000,
68
- 'hazelcast.client.partition.refresh.min.interval': 2000,
69
- 'hazelcast.client.invocation.max.retries': 10,
70
- 'hazelcast.client.partition.failure.backoff': 2000
71
- }
1
+ # Hazelcast Node.js Client - Release Summary
2
+
3
+ ## Version 3.12.5-1 (@celerispay)
4
+
5
+ ### Release Overview
6
+ This is a critical patch release that resolves severe failover and connection management issues in the Hazelcast Node.js client 3.12.x. The fixes address production stability problems that were causing application crashes and connection bombardment.
7
+
8
+ ### Package Information
9
+ - **Package Name**: `@celerispay/hazelcast-client`
10
+ - **Version**: `3.12.5-1`
11
+ - **Publisher**: CelerisPay
12
+ - **Base Version**: 3.12.5 (Hazelcast Inc.)
13
+ - **Release Date**: 2025-08-27
14
+
15
+ ## Critical Issues Fixed
16
+
17
+ ### 1. **Near Cache Crashes**
18
+ - **Problem**: `TypeError: Cannot read properties of undefined (reading 'getUuid')`
19
+ - **Impact**: Application crashes during failover
20
+ - **Fix**: Comprehensive null checks and error handling
21
+
22
+ ### 2. **Connection Bombardment**
23
+ - **Problem**: Repeated connection attempts to failed nodes
24
+ - **Impact**: Network spam and increasing connection counts
25
+ - **Fix**: Intelligent address blocking system (30 seconds)
26
+
27
+ ### 3. **Incomplete Reconnection**
28
+ - **Problem**: Only unblocked addresses without connection attempts
29
+ - **Impact**: Failed nodes never reconnected when they came back
30
+ - **Fix**: Actual connection establishment with ownership evaluation
31
+
32
+ ### 4. **Connection Leakage**
33
+ - **Problem**: Failed connections weren't properly cleaned up
34
+ - **Impact**: Memory leaks and resource exhaustion
35
+ - **Fix**: Periodic connection cleanup and health monitoring
36
+
37
+ ### 5. **Hanging Operations** ✅
38
+ - **Problem**: Operations hung indefinitely during failures
39
+ - **Impact**: Application unresponsiveness
40
+ - **Fix**: Maximum retry limits and proper error handling
41
+
42
+ ### 6. **Repeated Failures**
43
+ - **Problem**: Client kept trying failed addresses
44
+ - **Impact**: Poor performance and stability
45
+ - **Fix**: Address blocking with automatic unblocking
46
+
47
+ ## What's New
48
+
49
+ ### 1. **Address Blocking System**
50
+ - **Temporary Blocking**: Failed addresses blocked for 30 seconds
51
+ - **Automatic Unblocking**: Addresses automatically unblocked after duration
52
+ - **Reconnection Logic**: Periodic attempts to reconnect to unblocked addresses
53
+ - **Adaptive Blocking**: Shorter blocks for reconnection failures (15 seconds max)
54
+
55
+ ### 2. **Enhanced Failover Process**
56
+ - **Structured Failover**: Organized failover with proper state management
57
+ - **Failover Cooldown**: 5-second cooldown between attempts
58
+ - **Partition Management**: Automatic partition table clearing and refresh
59
+ - **Owner Switching**: Intelligent switching between owner connections
60
+
61
+ ### 3. **Connection Health Monitoring**
62
+ - **Health Checks**: Every 5 seconds for all connections
63
+ - **Stale Cleanup**: Every 15 seconds for failed connections
64
+ - **Failover Support**: Special cleanup during failover scenarios
65
+ - **Resource Management**: Proper cleanup of intervals and timeouts
66
+
67
+ ### 4. **Intelligent Reconnection**
68
+ - **Periodic Attempts**: Every 10 seconds to check for reconnection opportunities
69
+ - **Ownership Evaluation**: Smart logic for promoting reconnected nodes
70
+ - **Health Monitoring**: Continuous monitoring of connection health
71
+ - **Graceful Transitions**: Smooth ownership changes during recovery
72
+
73
+ ## Technical Improvements
74
+
75
+ ### ClusterService
76
+ - Added `downAddresses` Map for tracking failed addresses
77
+ - Added `failoverInProgress` flag to prevent concurrent failovers
78
+ - Added `failoverCooldown` mechanism (5 seconds)
79
+ - Added reconnection task with intelligent logic
80
+ - Added ownership evaluation and promotion
81
+
82
+ ### ClientConnectionManager
83
+ - Added connection health monitoring (5-second intervals)
84
+ - Added stale connection cleanup (15-second intervals)
85
+ - Added failover-specific cleanup methods
86
+ - Enhanced connection destruction with error handling
87
+
88
+ ### PartitionService
89
+ - Added refresh rate limiting (2-second minimum)
90
+ - Added retry logic (3 attempts maximum)
91
+ - Added state management to prevent concurrent refreshes
92
+ - Added health monitoring and debugging methods
93
+
94
+ ### StaleReadDetectorImpl
95
+ - Added comprehensive null checks for metadata
96
+ - Added try-catch blocks for partition operations
97
+ - Added safe fallback values during failover
98
+ - Enhanced error handling for production stability
99
+
100
+ ## Configuration Properties
101
+
102
+ ### New Properties Added
103
+ ```typescript
104
+ // Connection Management
105
+ 'hazelcast.client.connection.health.check.interval': 5000, // 5 seconds
106
+ 'hazelcast.client.connection.max.retries': 3, // Max 3 retries
107
+ 'hazelcast.client.connection.retry.delay': 1000, // 1 second delay
108
+
109
+ // Failover Management
110
+ 'hazelcast.client.failover.cooldown': 5000, // 5 seconds cooldown
111
+ 'hazelcast.client.partition.refresh.min.interval': 2000, // 2 seconds minimum
112
+
113
+ // Retry and Backoff
114
+ 'hazelcast.client.invocation.max.retries': 10, // Max 10 retries
115
+ 'hazelcast.client.partition.failure.backoff': 2000, // 2 seconds backoff
72
116
  ```
73
117
 
74
- ### **Network Configuration Improvements**
75
- ```javascript
76
- networkConfig: {
77
- connectionAttemptLimit: 5, // Increased from 2
78
- connectionTimeout: 10000, // Increased from 5000
79
- redoOperation: true, // Changed from false
80
- smartRouting: true
81
- }
82
- ```
118
+ ### Enhanced Defaults
119
+ - `connectionAttemptLimit`: Increased from 2 to 5
120
+ - `connectionTimeout`: Increased from 5000ms to 10000ms
121
+ - `redoOperation`: Changed from false to true
122
+
123
+ ## Files Modified
124
+
125
+ ### Core Services
126
+ - `src/invocation/ClusterService.ts` - Enhanced failover and reconnection
127
+ - `src/invocation/ClientConnectionManager.ts` - Connection health and cleanup
128
+ - `src/PartitionService.ts` - Rate limiting and retry logic
129
+ - `src/nearcache/StaleReadDetectorImpl.ts` - Error handling and null checks
83
130
 
84
- ## 📦 **Installation**
131
+ ### Configuration
132
+ - `src/config/Config.ts` - New configuration properties
133
+ - `src/config/ClientNetworkConfig.ts` - Enhanced network defaults
85
134
 
135
+ ### Documentation
136
+ - `FAILOVER_FIXES.md` - Technical implementation details
137
+ - `QUICK_START.md` - Usage guide and examples
138
+ - `CHANGELOG.md` - Comprehensive change log
139
+ - `RELEASE_SUMMARY.md` - This summary document
140
+
141
+ ### Testing
142
+ - `test/ConnectionFailoverTest.js` - Test suite for new features
143
+
144
+ ## Installation
145
+
146
+ ### Install the Fixed Version
86
147
  ```bash
87
- # Install the fixed version
88
- npm install @celerispay/hazelcast-client@3.12.5
148
+ npm install @celerispay/hazelcast-client@3.12.5-1
149
+ ```
89
150
 
90
- # Or if you're using yarn
91
- yarn add @celerispay/hazelcast-client@3.12.5
151
+ ### Verify Installation
152
+ ```bash
153
+ npm list @celerispay/hazelcast-client
154
+ # Should show version 3.12.5-1
92
155
  ```
93
156
 
94
- ## 🔄 **Migration Guide**
157
+ ## Migration
158
+
159
+ ### From Original 3.12.x
160
+ ```bash
161
+ # Remove original
162
+ npm uninstall hazelcast-client
95
163
 
96
- ### **From 3.12.4 to 3.12.5**
164
+ # Install fixed version
165
+ npm install @celerispay/hazelcast-client@3.12.5-1
166
+ ```
97
167
 
98
- 1. **Update package.json**:
99
- ```json
100
- {
101
- "dependencies": {
102
- "@celerispay/hazelcast-client": "3.12.5"
103
- }
104
- }
105
- ```
168
+ ```javascript
169
+ // Update import statement
170
+ // Before
171
+ const { ClientConfig } = require('hazelcast-client');
106
172
 
107
- 2. **Update import statement**:
108
- ```javascript
109
- // Before
110
- const { HazelcastClient } = require('hazelcast-client');
111
-
112
- // After
113
- const { HazelcastClient } = require('@celerispay/hazelcast-client');
114
- ```
173
+ // After
174
+ const { ClientConfig } = require('@celerispay/hazelcast-client');
175
+ ```
115
176
 
116
- 3. **No other code changes required** - All fixes are backward compatible
177
+ ### No Code Changes Required
178
+ - All existing code works unchanged
179
+ - Enhanced behavior automatically enabled
180
+ - Optional configuration for fine-tuning
117
181
 
118
- 4. **Optional**: Configure enhanced properties for better control
182
+ ## Testing
119
183
 
120
- ## 🧪 **Testing**
184
+ ### Run Test Suite
185
+ ```bash
186
+ npm test
187
+ ```
121
188
 
122
- All tests pass successfully:
189
+ ### Verify Configuration
123
190
  ```bash
124
- npm test -- --grep "Connection Failover Test"
191
+ node -e "
192
+ const { ClientConfig } = require('@celerispay/hazelcast-client');
193
+ const config = new ClientConfig();
194
+ console.log('Enhanced properties:', Object.keys(config.properties).filter(p => p.includes('connection') || p.includes('failover')));
195
+ "
125
196
  ```
126
197
 
127
- **Results**: 5 passing tests (4ms)
198
+ ## Expected Results
128
199
 
129
- ## 📊 **Expected Results**
200
+ After implementing this fixed version:
130
201
 
131
- After upgrading to 3.12.5, your application will:
202
+ 1. **Stable Connections**: No more connection bombardment to failed nodes
203
+ 2. **Automatic Failover**: Seamless switching to healthy nodes when failures occur
204
+ 3. **Better Performance**: Reduced network traffic and improved response times
205
+ 4. **Cleaner Logs**: Fewer error messages and better failure information
206
+ 5. **Production Stability**: Reliable operation even during cluster topology changes
132
207
 
133
- - **Automatically failover** to healthy nodes when partition owners go down
134
- - ✅ **Clean up failed connections** instead of accumulating them
135
- - ✅ **Handle failures gracefully** with proper retry limits
136
- - ✅ **Monitor connection health** actively
137
- - ✅ **Refresh partition information** automatically on failures
138
- - ✅ **Block failed addresses** temporarily to prevent repeated failures
208
+ ## Production Deployment
139
209
 
140
- ## 🚀 **Production Deployment**
210
+ ### Ready for Production
211
+ This version is **100% production-ready** with:
212
+ - **Critical failover fixes** for production stability
213
+ - **Enhanced connection management** for better reliability
214
+ - **Comprehensive error handling** for graceful degradation
215
+ - **Intelligent reconnection logic** for automatic recovery
216
+ - **Professional support** from CelerisPay
141
217
 
142
- 1. **Compile**: `npm run compile` ✅
143
- 2. **Test**: `npm test`
144
- 3. **Update dependency**: `@celerispay/hazelcast-client@3.12.5`
145
- 4. **Deploy**: No code changes required (except import statement)
146
- 5. **Monitor**: Watch for improved failover behavior and address blocking
218
+ ### Monitoring Recommendations
219
+ - Enable statistics: `'hazelcast.client.statistics.enabled': true`
220
+ - Watch for failover events in logs
221
+ - Monitor connection health metrics
222
+ - Test failover scenarios under load
147
223
 
148
- ## 📚 **Documentation**
224
+ ## Support
149
225
 
150
- - **FAILOVER_FIXES.md** - Detailed technical documentation
151
- - **QUICK_START.md** - Usage guide with examples
152
- - **CHANGELOG.md** - Complete change history
153
- - **RELEASE_SUMMARY.md** - This summary document
226
+ ### Package Information
227
+ - **Name**: `@celerispay/hazelcast-client`
228
+ - **Version**: `3.12.5-1`
229
+ - **Publisher**: CelerisPay
154
230
 
155
- ## 🔍 **Verification**
231
+ ### Documentation
232
+ - **Technical Details**: See `FAILOVER_FIXES.md`
233
+ - **Quick Start**: See `QUICK_START.md`
234
+ - **Change Log**: See `CHANGELOG.md`
156
235
 
157
- - **Compilation**: Success (no TypeScript errors)
158
- - **Tests**: ✅ All 5 tests passing
159
- - **Backward Compatibility**: 100% compatible
160
- - **Runtime Safety**: ✅ All method calls verified
236
+ ### Issues and Support
237
+ - **GitHub Issues**: https://github.com/celerispay/hazelcast-nodejs-client/issues
238
+ - **Professional Support**: Available from CelerisPay
161
239
 
162
- ## ⚠️ **Important Notes**
240
+ ## Important Notes
163
241
 
164
- 1. **No Breaking Changes** - Your existing code will work unchanged
165
- 2. **Production Ready** - Thoroughly tested and verified
166
- 3. **Performance Impact** - Minimal overhead (5-second health checks)
167
- 4. **Memory Usage** - Will improve due to better connection management
168
- 5. **Network Traffic** - Will reduce due to address blocking
242
+ ### Backward Compatibility
243
+ - **100% Backward Compatible**: No breaking changes
244
+ - All existing code works unchanged
245
+ - Enhanced behavior automatically enabled
169
246
 
170
- ## 🎉 **Conclusion**
247
+ ### Performance Impact
248
+ - **Minimal Overhead**: Health checks every 5-15 seconds
249
+ - **Improved Performance**: Better connection management
250
+ - **Reduced Memory Usage**: Proper connection cleanup
251
+ - **Reduced Network Traffic**: Address blocking prevents spam
171
252
 
172
- Version 3.12.5 is a **production-ready patch release** that fixes critical connection failover issues while maintaining 100% backward compatibility. Your application will now handle node failures as gracefully as the Java clients do.
253
+ ### Future Considerations
254
+ - Consider upgrading to Hazelcast 4.x or 5.x for long-term support
255
+ - This version provides stability for 3.12.x environments
256
+ - Professional support available for production deployments
173
257
 
174
- **Key Benefits**:
175
- - **Immediate Resolution** of connection bombardment issues
176
- - **Intelligent Address Blocking** to prevent repeated failures
177
- - **Enhanced Monitoring** and health checking
178
- - **Professional Support** from CelerisPay
258
+ ---
179
259
 
180
- **Recommendation**: Deploy this version immediately to resolve the connection failover issues you were experiencing in production.
260
+ **Production Ready**: Version 3.12.5-1 is thoroughly tested and ready for production deployment with professional support from CelerisPay.
@@ -55,10 +55,19 @@ var Heartbeat = /** @class */ (function () {
55
55
  if (estConnections[address]) {
56
56
  var conn_1 = estConnections[address];
57
57
  var now = Date.now();
58
+ // More resilient heartbeat timeout check - only mark as stopped if REALLY stale
58
59
  if (now - conn_1.getLastReadTimeMillis() > this_1.heartbeatTimeout) {
59
60
  if (conn_1.isHeartbeating()) {
60
- conn_1.setHeartbeating(false);
61
- this_1.onHeartbeatStopped(conn_1);
61
+ this_1.logger.debug('HeartbeatService', "Connection " + conn_1 + " appears to have stopped heartbeating, but will verify before marking as stopped");
62
+ // Add a grace period before marking as stopped
63
+ setTimeout(function () {
64
+ // Re-check if still not heartbeating
65
+ if (conn_1.isHeartbeating() && (Date.now() - conn_1.getLastReadTimeMillis() > _this.heartbeatTimeout)) {
66
+ conn_1.setHeartbeating(false);
67
+ _this.onHeartbeatStopped(conn_1);
68
+ _this.logger.warn('HeartbeatService', "Connection " + conn_1 + " confirmed to have stopped heartbeating after grace period");
69
+ }
70
+ }, 5000); // 5 second grace period
62
71
  }
63
72
  }
64
73
  if (now - conn_1.getLastWriteTimeMillis() > this_1.heartbeatInterval) {
@@ -35,4 +35,18 @@ export declare class PartitionService {
35
35
  */
36
36
  getPartitionId(key: any): number;
37
37
  getPartitionCount(): number;
38
+ /**
39
+ * Checks if the partition service is healthy
40
+ * @returns true if partition table is populated, false otherwise
41
+ */
42
+ isHealthy(): boolean;
43
+ /**
44
+ * Gets information about the current partition table state
45
+ * @returns object with partition information
46
+ */
47
+ getPartitionTableInfo(): {
48
+ partitionCount: number;
49
+ isHealthy: boolean;
50
+ lastRefreshTime: number;
51
+ };
38
52
  }
@@ -74,9 +74,7 @@ var PartitionService = /** @class */ (function () {
74
74
  }).catch(function (e) {
75
75
  if (_this.client.getLifecycleService().isRunning()) {
76
76
  _this.logger.warn('PartitionService', 'Error while fetching cluster partition table from '
77
- + _this.client.getClusterService().ownerUuid, e);
78
- // If refresh fails, clear the table to force refresh on next operation
79
- _this.clearPartitionTable();
77
+ + _this.client.getClusterService().ownerUuid || 'unknown', e);
80
78
  }
81
79
  });
82
80
  };
@@ -101,18 +99,43 @@ var PartitionService = /** @class */ (function () {
101
99
  * @returns the partition id.
102
100
  */
103
101
  PartitionService.prototype.getPartitionId = function (key) {
104
- var partitionHash;
105
- if (typeof key === 'object' && 'getPartitionHash' in key) {
106
- partitionHash = key.getPartitionHash();
102
+ try {
103
+ var partitionHash = void 0;
104
+ if (typeof key === 'object' && 'getPartitionHash' in key) {
105
+ partitionHash = key.getPartitionHash();
106
+ }
107
+ else {
108
+ partitionHash = this.client.getSerializationService().toData(key).getPartitionHash();
109
+ }
110
+ return Math.abs(partitionHash) % this.partitionCount;
107
111
  }
108
- else {
109
- partitionHash = this.client.getSerializationService().toData(key).getPartitionHash();
112
+ catch (error) {
113
+ this.logger.warn('PartitionService', "Error computing partition ID for key:", error);
114
+ // Return a safe default partition ID
115
+ return 0;
110
116
  }
111
- return Math.abs(partitionHash) % this.partitionCount;
112
117
  };
113
118
  PartitionService.prototype.getPartitionCount = function () {
114
119
  return this.partitionCount;
115
120
  };
121
+ /**
122
+ * Checks if the partition service is healthy
123
+ * @returns true if partition table is populated, false otherwise
124
+ */
125
+ PartitionService.prototype.isHealthy = function () {
126
+ return this.partitionCount > 0 && Object.keys(this.partitionMap).length > 0;
127
+ };
128
+ /**
129
+ * Gets information about the current partition table state
130
+ * @returns object with partition information
131
+ */
132
+ PartitionService.prototype.getPartitionTableInfo = function () {
133
+ return {
134
+ partitionCount: this.partitionCount,
135
+ isHealthy: this.isHealthy(),
136
+ lastRefreshTime: this.lastRefreshTime
137
+ };
138
+ };
116
139
  return PartitionService;
117
140
  }());
118
141
  exports.PartitionService = PartitionService;
@@ -46,7 +46,12 @@ export declare class ClientConnection {
46
46
  private readonly socket;
47
47
  private readonly writer;
48
48
  private readonly reader;
49
+ private readonly logger;
49
50
  constructor(client: HazelcastClient, address: Address, socket: net.Socket);
51
+ /**
52
+ * Sets up socket event handlers for proper connection state tracking
53
+ */
54
+ private setupSocketEventHandlers();
50
55
  /**
51
56
  * Returns the address of local port that is associated with this connection.
52
57
  * @returns
@@ -65,7 +70,16 @@ export declare class ClientConnection {
65
70
  * Closes this connection.
66
71
  */
67
72
  close(): void;
73
+ /**
74
+ * Checks if the connection is alive and healthy
75
+ * @returns true if connection is alive, false otherwise
76
+ */
68
77
  isAlive(): boolean;
78
+ /**
79
+ * Performs a more thorough health check of the connection
80
+ * @returns true if connection is healthy, false otherwise
81
+ */
82
+ isHealthy(): boolean;
69
83
  isHeartbeating(): boolean;
70
84
  setHeartbeating(heartbeating: boolean): void;
71
85
  isAuthenticatedAsOwner(): boolean;