Skip to content

Commit c199191

Browse files
authored
Getting Ready for 5.6.0 Release (#1571)
* Set client version to 5.6.0 * Require Node.js 20 as the minimum. It's the currently minimum manintend Node,js LTS * Fixed leaks with some socket callbacks * Use `clearTimeout` for `setTimeout` instead of `clearInterval`.
1 parent 7ca2e69 commit c199191

6 files changed

Lines changed: 60 additions & 18 deletions

File tree

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.PHONY: build lint test test-all
2+
3+
build:
4+
npm run compile
5+
6+
lint:
7+
npm run lint
8+
9+
test: build lint
10+
npm test
11+
12+
test-all: build lint
13+
env HAZELCAST_ENTERPRISE_KEY=1 npm test
14+

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,6 @@ This command will only run the tests matching the pattern. The pattern can be a
210210

211211
## Copyright
212212

213-
Copyright (c) 2008-2022, Hazelcast, Inc. All Rights Reserved.
213+
Copyright (c) 2008-2026, Hazelcast, Inc. All Rights Reserved.
214214

215215
Visit [www.hazelcast.com](http://www.hazelcast.com) for more information.

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hazelcast-client",
3-
"version": "5.3.0",
3+
"version": "5.6.0",
44
"description": "Hazelcast - a real-time stream processing platform - Node.js Client",
55
"main": "lib/index.js",
66
"types": "lib/index.d.ts",
@@ -9,7 +9,7 @@
99
"lib/**/*.d.ts"
1010
],
1111
"dependencies": {
12-
"@types/long": "4.0.0",
12+
"@types/long": "4.0.2",
1313
"long": "4.0.0"
1414
},
1515
"devDependencies": {
@@ -23,9 +23,9 @@
2323
"eslint-plugin-mocha": "~9.0.0",
2424
"husky": "~6.0.0",
2525
"jsonschema": "~1.5.0",
26-
"markdown-link-check": "~3.13.7",
26+
"markdown-link-check": "^3.14.2",
2727
"markdownlint-cli": "~0.32.2",
28-
"mocha": "~9.2.2",
28+
"mocha": "^11.7.5",
2929
"mousse": "~0.3.1",
3030
"nyc": "~15.1.0",
3131
"path-exists-cli": "~2.0.0",
@@ -41,7 +41,7 @@
4141
"yargs": "~17.5.1"
4242
},
4343
"engines": {
44-
"node": ">=10.4.0"
44+
"node": ">=20.20.0"
4545
},
4646
"scripts": {
4747
"clean": "rimraf lib *.jar *.log *.xml coverage",

src/invocation/InvocationService.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,7 @@ export class InvocationService {
684684
+ invocation.request.getCorrelationId() + ') reached its deadline.', error));
685685
return true;
686686
}
687+
return false;
687688
}
688689

689690
private registerInvocation(invocation: Invocation): void {
@@ -703,7 +704,7 @@ export class InvocationService {
703704
deregisterInvocation(correlationId: number): void {
704705
this.pending.delete(correlationId);
705706
}
706-
707+
707708
/**
708709
* Returns `true` if we need to check the urgent invocations, by
709710
* examining the local registry of the schema service.
@@ -743,7 +744,7 @@ export class InvocationService {
743744
+ 'data and it is not safe to invoke it when the client is not '
744745
+ 'yet initialized on the cluster');
745746
}
746-
747+
747748
return null;
748749
}
749750
}

src/network/Connection.ts

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export class PipelinedWriter extends Writer {
6262
private canWrite = true;
6363
// reusable buffer for coalescing
6464
private readonly coalesceBuf: Buffer;
65+
private readonly drainListener: () => void;
6566

6667
constructor(
6768
private readonly socket: net.Socket,
@@ -72,11 +73,13 @@ export class PipelinedWriter extends Writer {
7273
super();
7374
this.coalesceBuf = Buffer.allocUnsafe(threshold);
7475

75-
// write queued items on drain event
76-
socket.on('drain', () => {
76+
this.drainListener = () => {
7777
this.canWrite = true;
7878
this.schedule();
79-
});
79+
}
80+
81+
// write queued items on drain event
82+
socket.on('drain', this.drainListener);
8083
}
8184

8285
write(message: ClientMessage, resolver: DeferredPromise<void>): void {
@@ -94,6 +97,7 @@ export class PipelinedWriter extends Writer {
9497
}
9598
this.error = this.makeIOError(error);
9699
this.canWrite = false;
100+
this.socket.off('drain', this.drainListener);
97101
// If we pass an error to destroy, an unhandled error will be thrown because we don't handle the error event
98102
// So we don't pass anything to the socket. It is internal anyway.
99103
this.socket.destroy();
@@ -214,6 +218,8 @@ export class DirectWriter extends Writer {
214218
}
215219

216220
close(cause: Error): void {
221+
// Remove all listeners from this emitter
222+
this.removeAllListeners('write');
217223
this.socket.destroy();
218224
}
219225
}
@@ -351,6 +357,8 @@ export class Connection {
351357
private readonly writer: Writer;
352358
private readonly reader: ClientMessageReader;
353359
private readonly fragmentedMessageHandler: FragmentedClientMessageHandler;
360+
private dataListener: ((buffer: Buffer) => void) | null = null;
361+
private writeListener: (() => void) | null = null;
354362

355363
constructor(
356364
private readonly connectionManager: ConnectionManager,
@@ -374,9 +382,10 @@ export class Connection {
374382
this.connectedServerVersion = BuildInfo.UNKNOWN_VERSION_ID;
375383
this.writer = enablePipelining ? new PipelinedWriter(this.socket, pipeliningThreshold, this.incrementBytesWrittenFn)
376384
: new DirectWriter(this.socket, this.incrementBytesWrittenFn);
377-
this.writer.on('write', () => {
385+
this.writeListener = () => {
378386
this.lastWriteTimeMillis = Date.now();
379-
});
387+
}
388+
this.writer.on('write', this.writeListener);
380389
this.reader = new ClientMessageReader();
381390
this.fragmentedMessageHandler = new FragmentedClientMessageHandler(this.logger);
382391
}
@@ -437,11 +446,28 @@ export class Connection {
437446

438447
this.logClose();
439448

449+
// Remove socket listeners before closing
450+
this.removeListeners();
451+
440452
this.writer.close(this.closedCause ? this.closedCause : new Error(reason ? reason : 'Connection closed'));
441453

442454
this.connectionManager.onConnectionClose(this);
443455
}
444456

457+
/**
458+
* Removes all registered listeners from the socket and writer.
459+
*/
460+
private removeListeners(): void {
461+
if (this.dataListener !== null) {
462+
this.socket.off('data', this.dataListener);
463+
this.dataListener = null;
464+
}
465+
if (this.writeListener !== null) {
466+
this.writer.off('write', this.writeListener);
467+
this.writeListener = null;
468+
}
469+
}
470+
445471
isAlive(): boolean {
446472
return this.closedTime === 0;
447473
}
@@ -483,7 +509,7 @@ export class Connection {
483509
* @param callback
484510
*/
485511
registerResponseCallback(callback: ClientMessageHandler): void {
486-
this.socket.on('data', (buffer: Buffer) => {
512+
this.dataListener = (buffer: Buffer) => {
487513
this.lastReadTimeMillis = Date.now();
488514
this.reader.append(buffer);
489515
let clientMessage = this.reader.read();
@@ -496,14 +522,15 @@ export class Connection {
496522
clientMessage = this.reader.read();
497523
}
498524
this.incrementBytesReadFn(buffer.length);
499-
});
525+
}
526+
this.socket.on('data', this.dataListener);
500527
}
501528

502529
setClusterUuid(uuid: UUID): void {
503530
this.clusterUuid = uuid;
504531
}
505532

506-
getClusterUuid(): UUID {
533+
getClusterUuid(): UUID {
507534
return this.clusterUuid;
508535
}
509536

src/network/ConnectionManager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,11 +665,11 @@ export class ConnectionManager extends EventEmitter implements MembershipListene
665665
}, this.connectionTimeoutMillis);
666666

667667
socket.once('secureConnect', () => {
668-
clearInterval(connectTimeoutTimer);
668+
clearTimeout(connectTimeoutTimer);
669669
connectionResolver.resolve(socket);
670670
});
671671
socket.once('error', (err) => {
672-
clearInterval(connectTimeoutTimer);
672+
clearTimeout(connectTimeoutTimer);
673673
connectionResolver.reject(err);
674674
});
675675

0 commit comments

Comments
 (0)