Skip to content

Commit

Permalink
net: server add asyncDispose
Browse files Browse the repository at this point in the history
PR-URL: nodejs#48717
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
  • Loading branch information
atlowChemi authored and Ceres6 committed Aug 14, 2023
1 parent d5eee2a commit 5b256c8
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
11 changes: 11 additions & 0 deletions doc/api/net.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,17 @@ The optional `callback` will be called once the `'close'` event occurs. Unlike
that event, it will be called with an `Error` as its only argument if the server
was not open when it was closed.

### `server[Symbol.asyncDispose]()`

<!-- YAML
added: REPLACEME
-->

> Stability: 1 - Experimental
Calls [`server.close()`][] and returns a promise that fulfills when the
server has closed.

### `server.getConnections(callback)`

<!-- YAML
Expand Down
11 changes: 10 additions & 1 deletion lib/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ const {
ArrayPrototypePush,
Boolean,
FunctionPrototypeBind,
FunctionPrototypeCall,
MathMax,
Number,
NumberIsNaN,
NumberParseInt,
ObjectDefineProperty,
ObjectSetPrototypeOf,
Symbol,
SymbolAsyncDispose,
SymbolDispose,
} = primordials;

Expand Down Expand Up @@ -112,7 +114,7 @@ const {
} = require('internal/errors');
const { isUint8Array } = require('internal/util/types');
const { queueMicrotask } = require('internal/process/task_queues');
const { kEmptyObject, guessHandleType } = require('internal/util');
const { kEmptyObject, guessHandleType, promisify } = require('internal/util');
const {
validateAbortSignal,
validateBoolean,
Expand Down Expand Up @@ -2243,6 +2245,13 @@ Server.prototype.close = function(cb) {
return this;
};

Server.prototype[SymbolAsyncDispose] = async function() {
if (!this._handle) {
return;
}
return FunctionPrototypeCall(promisify(this.close), this);
};

Server.prototype._emitCloseIfDrained = function() {
debug('SERVER _emitCloseIfDrained');

Expand Down
30 changes: 30 additions & 0 deletions test/parallel/test-net-server-async-dispose.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as common from '../common/index.mjs';
import assert from 'node:assert';
import net from 'node:net';
import { describe, it } from 'node:test';

describe('net.Server[Symbol.asyncDispose]()', () => {
it('should close the server', async () => {
const server = net.createServer();
const timeoutRef = setTimeout(common.mustNotCall(), 2 ** 31 - 1);

server.listen(0, common.mustCall(async () => {
await server[Symbol.asyncDispose]().then(common.mustCall());
assert.strictEqual(server.address(), null);
clearTimeout(timeoutRef);
}));

server.on('close', common.mustCall());
});

it('should resolve even if the server is already closed', async () => {
const server = net.createServer();
const timeoutRef = setTimeout(common.mustNotCall(), 2 ** 31 - 1);

server.listen(0, common.mustCall(async () => {
await server[Symbol.asyncDispose]().then(common.mustCall());
await server[Symbol.asyncDispose]().then(common.mustCall(), common.mustNotCall());
clearTimeout(timeoutRef);
}));
});
});

0 comments on commit 5b256c8

Please sign in to comment.