Skip to content

fix: await async session removal in cleanupExpiredSessions#615

Closed
ashsolei wants to merge 1 commit intoczlonkowski:mainfrom
ashsolei:fix/await-session-cleanup
Closed

fix: await async session removal in cleanupExpiredSessions#615
ashsolei wants to merge 1 commit intoczlonkowski:mainfrom
ashsolei:fix/await-session-cleanup

Conversation

@ashsolei
Copy link

@ashsolei ashsolei commented Mar 1, 2026

Problem

cleanupExpiredSessions() calls removeSession() — an async method — without awaiting it. This creates fire-and-forget promises that silently swallow errors and allow race conditions when multiple sessions expire simultaneously.

Fix

  • Changed cleanupExpiredSessions() from void to async Promise<void>
  • Added await before each removeSession() call in the cleanup loop

This ensures each expired session is properly removed (and errors surfaced) before proceeding to the next one.

Validation

  • TypeCheck: 0 new errors
  • Unit tests: all http-server tests pass (30 passed, 12 skipped)

cleanupExpiredSessions() called the async removeSession() method
without awaiting it, causing fire-and-forget promises that could
silently fail. Changed the method to async and added await to
ensure each expired session is properly removed before proceeding
to the next one.
Copilot AI review requested due to automatic review settings March 1, 2026 04:52
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes session cleanup behavior in SingleSessionHTTPServer by ensuring expired sessions are removed deterministically, instead of creating “fire-and-forget” removal promises during periodic cleanup.

Changes:

  • Converted cleanupExpiredSessions() to async Promise<void>.
  • Awaited removeSession() for each expired session during cleanup.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 172 to 174
for (const sessionId of expiredSessions) {
this.removeSession(sessionId, 'expired');
await this.removeSession(sessionId, 'expired');
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although this now awaits removeSession, removeSession() catches and swallows all errors internally, so failures won’t reject back to cleanupExpiredSessions (and the outer cleanup try/catch won’t see them). If the goal is to surface errors to the caller, consider rethrowing after logging (or returning a result/using Promise.allSettled and reporting failures explicitly).

Copilot uses AI. Check for mistakes.
Comment on lines +150 to 152
private async cleanupExpiredSessions(): Promise<void> {
const now = Date.now();
const expiredSessions: string[] = [];
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleanupExpiredSessions is now async and can take non-trivial time (especially since it awaits each removal). Because it’s run from setInterval, a new tick can start while a previous cleanup is still in progress, leading to overlapping cleanups and reintroducing race conditions. Consider adding an in-progress guard/lock (or switching to a self-scheduling setTimeout loop) so only one cleanup runs at a time.

Copilot uses AI. Check for mistakes.
@ashsolei
Copy link
Author

ashsolei commented Mar 1, 2026

Closing — will maintain fixes in a private mirror instead. Thank you for the review.

@ashsolei ashsolei closed this Mar 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants