Skip to content

fix: resolve traceroute race condition for fast-responding nodes (#2364)#2366

Merged
Yeraze merged 1 commit intomainfrom
fix/traceroute-race-condition
Mar 22, 2026
Merged

fix: resolve traceroute race condition for fast-responding nodes (#2364)#2366
Yeraze merged 1 commit intomainfrom
fix/traceroute-race-condition

Conversation

@Yeraze
Copy link
Copy Markdown
Owner

@Yeraze Yeraze commented Mar 21, 2026

Summary

Fixes #2364 — traceroutes showed "No response received" for nearby/fast-responding nodes despite the response being visible in logs and packet monitor.

Root Cause

recordTracerouteRequest() for PostgreSQL/MySQL fired an un-awaited async IIFE to insert the pending traceroute record. For nearby nodes, the traceroute response arrived before the DB insert completed:

  1. sendTraceroute() → sends packet, calls await recordTracerouteRequestAsync()
  2. But the async wrapper called the inner method without await → returned immediately
  3. Fast response arrives → processTracerouteMessage() runs
  4. DB insert for the pending record is still in flight
  5. Frontend reads stale DB state → shows "No response received"

Fix

Made recordTracerouteRequest() properly async — removed the fire-and-forget IIFE and directly awaits the DB operations. The async wrapper now correctly awaits the inner method.

Files Changed

File Change
src/services/database.ts Make recordTracerouteRequest async, remove un-awaited IIFE, await in async wrapper

Test plan

  • 3052 tests pass, 0 failures
  • SQLite path unchanged (already synchronous)
  • PostgreSQL/MySQL path now properly awaited

🤖 Generated with Claude Code

recordTracerouteRequest() for PostgreSQL/MySQL fired an un-awaited async
IIFE to insert the pending traceroute record. For nearby nodes, the
response arrived before the DB insert completed, causing "No response
received" in the UI despite the response being in logs/packet monitor.

Fix: make recordTracerouteRequest() async and properly await the DB
operations, ensuring the pending record is written before the response
can be processed.

Closes #2364

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
}

recordTracerouteRequest(fromNodeNum: number, toNodeNum: number): void {
async recordTracerouteRequest(fromNodeNum: number, toNodeNum: number): Promise<void> {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Great fix! Making this method properly async resolves the race condition. The previous fire-and-forget IIFE meant fast traceroute responses could arrive before the pending record was inserted into the database.

Consider adding a brief comment here explaining why the await is critical:

Suggested change
async recordTracerouteRequest(fromNodeNum: number, toNodeNum: number): Promise<void> {
async recordTracerouteRequest(fromNodeNum: number, toNodeNum: number): Promise<void> {
// NOTE: This MUST be awaited to prevent race conditions with fast-responding nodes
const now = Date.now();

Comment on lines 5320 to 5321
// For PostgreSQL/MySQL, use async repository
if (this.drizzleDbType === 'postgres' || this.drizzleDbType === 'mysql') {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Perfect removal of the problematic pattern. The fire-and-forget IIFE was the root cause of the race condition. Now the database operations are properly awaited before the method returns, ensuring the pending traceroute record exists when fast responses arrive.

// Group 4: Traceroutes
async recordTracerouteRequestAsync(fromNodeNum: number, toNodeNum: number): Promise<void> {
this.recordTracerouteRequest(fromNodeNum, toNodeNum);
await this.recordTracerouteRequest(fromNodeNum, toNodeNum);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Critical fix! This change from fire-and-forget to properly awaited call is essential. The async wrapper pattern throughout the codebase expects the inner method to be awaited, and this was the missing piece causing the race condition.

This now properly aligns with the multi-database architecture requirement that "ALL database methods in DatabaseService must be async".

@Yeraze Yeraze merged commit fd22e57 into main Mar 22, 2026
17 checks passed
@Yeraze Yeraze deleted the fix/traceroute-race-condition branch March 22, 2026 00:13
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.

[BUG] Traceroute Problems

1 participant