Skip to content

Commit 1dcf1fd

Browse files
authored
Fix Streaming Lambda Socket Hang (#732)
1 parent 02f3a00 commit 1dcf1fd

2 files changed

Lines changed: 11 additions & 0 deletions

File tree

src/metrics/dogstatsd.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ jest.mock("node:dgram", () => ({
77

88
describe("LambdaDogStatsD", () => {
99
let mockSend: jest.Mock;
10+
let mockUnref: jest.Mock;
1011

1112
beforeEach(() => {
1213
// A send() that immediately calls its callback
1314
mockSend = jest.fn((msg, port, host, cb) => cb());
15+
mockUnref = jest.fn();
1416
(dgram.createSocket as jest.Mock).mockReturnValue({
1517
send: mockSend,
18+
unref: mockUnref,
1619
getSendBufferSize: jest.fn().mockReturnValue(64 * 1024),
1720
setSendBufferSize: jest.fn(),
1821
bind: jest.fn(),
@@ -63,10 +66,17 @@ describe("LambdaDogStatsD", () => {
6366
await expect(client.flush()).resolves.toBeUndefined();
6467
});
6568

69+
it("unrefs socket on client creation", () => {
70+
// Constructor should avoid keeping Node's event loop alive.
71+
new LambdaDogStatsD();
72+
expect(mockUnref).toHaveBeenCalledTimes(1);
73+
});
74+
6675
it("flush() times out if a send never invokes its callback", async () => {
6776
// replace socket.send with a never‐calling callback
6877
(dgram.createSocket as jest.Mock).mockReturnValue({
6978
send: jest.fn(), // never calls callback
79+
unref: jest.fn(),
7080
getSendBufferSize: jest.fn(),
7181
setSendBufferSize: jest.fn(),
7282
bind: jest.fn(),

src/metrics/dogstatsd.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export class LambdaDogStatsD {
1818

1919
constructor() {
2020
this.socket = dgram.createSocket(LambdaDogStatsD.SOCKET_TYPE);
21+
this.socket.unref?.();
2122
}
2223

2324
/**

0 commit comments

Comments
 (0)