Skip to content

fix(db): detect WSL2 and adjust pgserve startup timeout - #1044

Closed
rafaelcalassara wants to merge 10 commits into
automagik-dev:devfrom
rafaelcalassara:fix/pgserve-wsl2-timeout
Closed

rafaelcalassara wants to merge 10 commits into
automagik-dev:devfrom
rafaelcalassara:fix/pgserve-wsl2-timeout

Conversation

@rafaelcalassara

Copy link
Copy Markdown

Add WSL2 detection via /proc/version check and increase pgserve startup timeout from 15s to 30s on WSL2 systems. Use exponential backoff polling with 2s initial bootstrap delay to accommodate slower I/O during database initialization. Non-WSL2 systems (Mac, Linux, Windows) unchanged.

Changes:

  • New module: src/lib/wsl2-detect.ts with memoized isWSL2() detection
  • Modified: src/lib/db.ts to use conditional timeout and bootstrap delay

Testing:

  • ✅ Builds without errors
  • ✅ No regressions (22/22 db tests pass)
  • ✅ TypeScript clean
  • ✅ Works on WSL2 (pgserve starts within 3 seconds)
  • ✅ Mac/Linux behavior unchanged

Fixes #1043

namastex888 and others added 10 commits April 2, 2026 20:19
chore: rolling promotion dev -> main
fix(ci): hardcoded v3 prefix in version and release workflows
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pg-listen-notify-migration-should-b

Fix automagik-dev#1004: docs: PG LISTEN/NOTIFY migration should be documented in s...
chore: rolling promotion dev -> main
release: v4.260404 — Claude Agent SDK executor + Omni bridge
Add WSL2 detection via /proc/version check and increase pgserve startup
timeout from 15s to 30s on WSL2 systems. Use exponential backoff polling
with 2s initial bootstrap delay to accommodate slower I/O during database
initialization. Non-WSL2 systems (Mac, Linux, Windows) unchanged.

- New module: src/lib/wsl2-detect.ts with memoized isWSL2() detection
- Modified: src/lib/db.ts to use conditional timeout and bootstrap delay
- Fixes pgserve timeout failures on WSL2 without affecting other platforms
Copilot AI review requested due to automatic review settings April 4, 2026 19:49
@coderabbitai

coderabbitai Bot commented Apr 4, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 10acbf25-6e90-4cbc-b7b7-d98f936cff98

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc0de38538

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/lib/db.ts
mkdirSync(DATA_DIR, { recursive: true });

const isWsl = isWSL2();
const timeoutMs = isWsl ? 30000 : 15000;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Align client wait window with extended WSL startup timeout

Increasing daemon-side startup timeout to 30s on WSL2 here creates a mismatch with the CLI path in _ensurePgserve() that still gives up after 16s (const deadline = Date.now() + 16000). On slower WSL2 setups, the daemon can now succeed between 16–30s, but the initiating CLI command will still throw a timeout error even though pgserve comes up shortly after, which makes normal command execution fail spuriously in the target environment.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown

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 addresses WSL2-specific pgserve startup timeouts by detecting WSL2 at runtime and adjusting pgserve startup waiting behavior to better tolerate slower initialization on WSL2, while also updating mailbox module header documentation.

Changes:

  • Added a memoized WSL2 detection helper (isWSL2()) based on /proc/version.
  • Updated pgserve startup logic to use a longer timeout on WSL2 and exponential backoff polling with an initial bootstrap delay.
  • Expanded mailbox.ts header comment with a migration note describing the move from file-based polling to PostgreSQL LISTEN/NOTIFY.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
src/lib/wsl2-detect.ts Introduces WSL detection helper used to gate WSL-specific timeout behavior.
src/lib/db.ts Applies WSL-aware pgserve startup timeout and adjusts health-check polling strategy.
src/lib/mailbox.ts Updates module-level documentation about mailbox storage/delivery migration.

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

Comment thread src/lib/wsl2-detect.ts
Comment on lines +12 to +25
/**
* Detect if running on WSL2 by checking /proc/version for "microsoft" or "wsl".
* Result is memoized for performance.
*
* @returns true if running on WSL2, false otherwise
*/
export function isWSL2(): boolean {
// Return memoized result if already computed
if (memoized !== null) return memoized;

try {
const procVersion = readFileSync('/proc/version', 'utf-8');
memoized = procVersion.toLowerCase().includes('microsoft') || procVersion.toLowerCase().includes('wsl');
return memoized;

Copilot AI Apr 4, 2026

Copy link

Choose a reason for hiding this comment

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

isWSL2() currently checks /proc/version for "microsoft" or "wsl", which identifies WSL in general but does not distinguish WSL2 vs WSL1. Since the function name/docs are WSL2-specific, this can return true on WSL1 as well. Consider switching to a WSL2-specific signal (e.g., /proc/sys/kernel/osrelease containing "WSL2") or renaming the API to reflect what it actually detects.

Copilot uses AI. Check for mistakes.
Comment thread src/lib/db.ts
Comment on lines +362 to +364
const initialBootstrapMs = isWsl ? 2000 : 100;
await new Promise((r) => setTimeout(r, initialBootstrapMs));

Copilot AI Apr 4, 2026

Copy link

Choose a reason for hiding this comment

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

This introduces a 100ms bootstrap delay on non-WSL platforms (initialBootstrapMs = ... : 100), which is a behavior change (previously health checks started immediately). If the intent is “Non-WSL2 systems unchanged” per the PR description, consider using 0 (or leaving the old behavior) for the non-WSL branch.

Copilot uses AI. Check for mistakes.
Comment thread src/lib/db.ts
Comment on lines +362 to +366
const initialBootstrapMs = isWsl ? 2000 : 100;
await new Promise((r) => setTimeout(r, initialBootstrapMs));

const deadline = Date.now() + timeoutMs;
let retryDelayMs = 100;

Copilot AI Apr 4, 2026

Copy link

Choose a reason for hiding this comment

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

deadline is computed after the initial bootstrap sleep, so the total wait from spawn → timeout becomes initialBootstrapMs + timeoutMs, but the thrown error reports only timeoutMs seconds. Consider starting the deadline before the bootstrap delay, or include the bootstrap delay in the reported timeout to keep the error message accurate.

Copilot uses AI. Check for mistakes.
Comment thread src/lib/db.ts
Comment on lines +337 to +340
const isWsl = isWSL2();
const timeoutMs = isWsl ? 30000 : 15000;
const timeoutSec = timeoutMs / 1000;

Copilot AI Apr 4, 2026

Copy link

Choose a reason for hiding this comment

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

WSL2 gets a longer pgserve startup timeout here, but the CLI path (_ensurePgserve step 4b) still times out waiting for the lockfile after 16s. If pgserve initialization ever takes >16s on WSL2, CLI commands can still fail even though the daemon continues starting successfully. Consider applying the same WSL2-aware timeout to the lockfile wait path as well.

Copilot uses AI. Check for mistakes.
Comment thread src/lib/mailbox.ts
Comment on lines +17 to +18
* - A 30-second fallback poll catches any notifications missed during
* reconnects or daemon restarts.

Copilot AI Apr 4, 2026

Copy link

Choose a reason for hiding this comment

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

The header comment claims “A 30-second fallback poll catches any notifications missed…”, but this module doesn’t implement a fallback poll (subscribeDelivery only registers LISTEN/NOTIFY). Either remove that statement or move/clarify it to wherever the fallback polling is actually implemented so the docs match the code.

Suggested change
* - A 30-second fallback poll catches any notifications missed during
* reconnects or daemon restarts.

Copilot uses AI. Check for mistakes.
Comment thread src/lib/mailbox.ts
*
* The current implementation replaced file-based polling with PostgreSQL:
* - Messages are persisted to the `mailbox` table (durable, queryable).
* - A `AFTER INSERT` trigger fires `pg_notify('genie_mailbox_delivery', …)`

Copilot AI Apr 4, 2026

Copy link

Choose a reason for hiding this comment

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

Grammar: “A AFTER INSERT trigger” should be “An AFTER INSERT trigger”.

Suggested change
* - A `AFTER INSERT` trigger fires `pg_notify('genie_mailbox_delivery', …)`
* - An `AFTER INSERT` trigger fires `pg_notify('genie_mailbox_delivery', …)`

Copilot uses AI. Check for mistakes.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces WSL2 environment detection to adjust pgserve startup timeouts, addressing slower I/O performance in that environment. It also includes documentation updates regarding the migration from file-based polling to PostgreSQL-based messaging in the mailbox module. The reviewer suggested a minor refactoring of the WSL2 detection logic to improve readability and efficiency.

Comment thread src/lib/wsl2-detect.ts
Comment on lines +22 to +30
try {
const procVersion = readFileSync('/proc/version', 'utf-8');
memoized = procVersion.toLowerCase().includes('microsoft') || procVersion.toLowerCase().includes('wsl');
return memoized;
} catch {
// /proc/version not readable (non-Linux or permission issue) — assume not WSL2
memoized = false;
return false;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

For improved readability and slightly better performance, you can refactor this block. Calling toLowerCase() once is more efficient, and the catch block can be made more concise.

  try {
    const procVersion = readFileSync('/proc/version', 'utf-8').toLowerCase();
    memoized = procVersion.includes('microsoft') || procVersion.includes('wsl');
    return memoized;
  } catch {
    // /proc/version not readable (non-Linux or permission issue) — assume not WSL2
    return (memoized = false);
  }

@namastex888

Copy link
Copy Markdown
Contributor

Closing — superseded by PR #1050

Issue #1043 was fixed in PR #1050 (merged), which:

  • Raised the default pgserve timeout from 15s → 30s on all platforms
  • Added GENIE_PGSERVE_TIMEOUT env var override so WSL2 users (or anyone) can set any value they need (e.g. GENIE_PGSERVE_TIMEOUT=60000)

This is simpler and more flexible than WSL2 auto-detection — no new module needed, works for any slow-I/O environment.

Why this PR can't be rebased/merged

Beyond being superseded, this PR's db.ts diff was branched before the test-pg-ram-isolation work (PR #1051) and would remove the resolveTestPort() function and the GENIE_TEST_PG_PORT short-circuit in ensurePgserve(). Those are critical to the new test isolation infrastructure that prevents PG deadlock flakiness. Merging would regress test reliability.

Thanks @rafaelcalassara for the investigation — the WSL2 detection approach was solid, the simpler fix just landed first.

@namastex888 namastex888 closed this Apr 5, 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.

5 participants