Skip to content

Commit 57e1ba8

Browse files
committed
fix: improve server lifecycle handling with proper startup/shutdown and port management
1 parent ac6db07 commit 57e1ba8

2 files changed

Lines changed: 67 additions & 22 deletions

File tree

src/webhook-server.js

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -380,15 +380,30 @@ export class WebhookServer {
380380
async start() {
381381
return new Promise((resolve, reject) => {
382382
try {
383-
this.server = serve({
383+
const serverOptions = {
384384
fetch: this.app.fetch,
385385
port: this.config.port
386-
});
387-
388-
console.log(`🎣 Webhook server listening on port ${this.config.port}`);
389-
console.log(`📡 Webhook URL: http://localhost:${this.config.port}/webhook`);
390-
391-
resolve(this.server);
386+
};
387+
388+
this.server = serve(serverOptions);
389+
390+
// Handle server startup
391+
if (this.server && typeof this.server.then === 'function') {
392+
// If serve returns a promise, wait for it
393+
this.server
394+
.then((actualServer) => {
395+
this.server = actualServer;
396+
console.log(`🎣 Webhook server listening on port ${this.config.port}`);
397+
console.log(`📡 Webhook URL: http://localhost:${this.config.port}/webhook`);
398+
resolve(this.server);
399+
})
400+
.catch(reject);
401+
} else {
402+
// If serve returns synchronously
403+
console.log(`🎣 Webhook server listening on port ${this.config.port}`);
404+
console.log(`📡 Webhook URL: http://localhost:${this.config.port}/webhook`);
405+
resolve(this.server);
406+
}
392407

393408
} catch (error) {
394409
console.error('❌ Webhook server error:', error);
@@ -403,12 +418,22 @@ export class WebhookServer {
403418
*/
404419
async stop() {
405420
return new Promise((resolve) => {
406-
if (this.server) {
407-
// Note: Hono's serve doesn't have a direct close method
408-
// In production, you'd handle this differently
409-
console.log('🛑 Webhook server stopped');
410-
resolve();
421+
if (this.server && this.server.close) {
422+
this.server.close(() => {
423+
console.log('🛑 Webhook server stopped');
424+
this.server = null;
425+
resolve();
426+
});
427+
} else if (this.server && this.server.server) {
428+
// Handle case where server is wrapped
429+
this.server.server.close(() => {
430+
console.log('🛑 Webhook server stopped');
431+
this.server = null;
432+
resolve();
433+
});
411434
} else {
435+
console.log('🛑 Webhook server stopped (no active server)');
436+
this.server = null;
412437
resolve();
413438
}
414439
});

test/webhook-server.test.js

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,42 @@ const __dirname = path.dirname(__filename);
1515

1616
describe('Webhook Server', () => {
1717
let server;
18-
const testPort = 3002; // Use different port for testing
18+
let currentTestPort = 3002; // Base port for testing
1919
const testLogFile = path.join(__dirname, 'temp', 'test-webhook-logs.json');
2020

21-
beforeEach(() => {
21+
// Helper function to get unique port for each test
22+
const getNextPort = () => ++currentTestPort;
23+
24+
beforeEach(async () => {
2225
// Clean up test files
2326
if (fs.existsSync(testLogFile)) {
2427
fs.unlinkSync(testLogFile);
2528
}
29+
30+
// Ensure temp directory exists
31+
const tempDir = path.dirname(testLogFile);
32+
if (!fs.existsSync(tempDir)) {
33+
fs.mkdirSync(tempDir, { recursive: true });
34+
}
2635
});
2736

2837
afterEach(async () => {
2938
if (server) {
30-
await server.stop();
39+
try {
40+
await server.stop();
41+
} catch (error) {
42+
console.warn('Warning: Error stopping server:', error.message);
43+
}
3144
server = null;
3245
}
3346

3447
// Clean up test files
3548
if (fs.existsSync(testLogFile)) {
3649
fs.unlinkSync(testLogFile);
3750
}
51+
52+
// Small delay to ensure port is released
53+
await new Promise(resolve => setTimeout(resolve, 100));
3854
});
3955

4056
describe('WebhookServer class', () => {
@@ -48,15 +64,16 @@ describe('Webhook Server', () => {
4864
});
4965

5066
it('should initialize with custom configuration', () => {
67+
const testPortForConfig = getNextPort();
5168
const config = {
52-
port: testPort,
69+
port: testPortForConfig,
5370
logFile: testLogFile,
5471
calendlyLink: 'https://calendly.com/test'
5572
};
5673

5774
const webhookServer = new WebhookServer(config);
5875

59-
expect(webhookServer.config.port).to.equal(testPort);
76+
expect(webhookServer.config.port).to.equal(testPortForConfig);
6077
expect(webhookServer.config.logFile).to.equal(testLogFile);
6178
expect(webhookServer.config.calendlyLink).to.equal('https://calendly.com/test');
6279
});
@@ -73,7 +90,7 @@ describe('Webhook Server', () => {
7390

7491
beforeEach(() => {
7592
webhookServer = new WebhookServer({
76-
port: testPort,
93+
port: getNextPort(),
7794
logFile: testLogFile
7895
});
7996
});
@@ -387,21 +404,24 @@ describe('Webhook Server', () => {
387404

388405
describe('Server lifecycle', () => {
389406
it('should start server successfully', async () => {
390-
server = new WebhookServer({ port: testPort });
407+
const testPortForStart = getNextPort();
408+
server = new WebhookServer({ port: testPortForStart });
391409

392410
const startedServer = await server.start();
393411
expect(startedServer).to.exist;
394412
});
395413

396414
it('should start server with startWebhookServer function', async () => {
397-
server = await startWebhookServer({ port: testPort + 1 });
415+
const testPortForFunction = getNextPort();
416+
server = await startWebhookServer({ port: testPortForFunction });
398417

399418
expect(server).to.be.instanceOf(WebhookServer);
400-
expect(server.config.port).to.equal(testPort + 1);
419+
expect(server.config.port).to.equal(testPortForFunction);
401420
});
402421

403422
it('should stop server gracefully', async () => {
404-
server = new WebhookServer({ port: testPort + 2 });
423+
const testPortForStop = getNextPort();
424+
server = new WebhookServer({ port: testPortForStop });
405425
await server.start();
406426

407427
// This should not throw an error

0 commit comments

Comments
 (0)