Skip to content

feat(appkit): scan upward from preferred port in development#349

Merged
MarioCadenas merged 2 commits intomainfrom
mario/dev-dynamic-listen-port
May 6, 2026
Merged

feat(appkit): scan upward from preferred port in development#349
MarioCadenas merged 2 commits intomainfrom
mario/dev-dynamic-listen-port

Conversation

@MarioCadenas
Copy link
Copy Markdown
Collaborator

Summary

  • In NODE_ENV=development, the server plugin now picks the first free TCP port by scanning upward from the preferred port (server({ port }), DATABRICKS_APP_PORT, or default 8000) using get-port's portNumbers(from, to) helper, bounded to 100 attempts.
  • Avoids EADDRINUSE failures when running multiple AppKit dev servers locally (e.g. two playgrounds at once).
  • Production / non-development behavior is unchanged: the plugin binds the configured / env / default port and lets listen errors surface as before.
  • Startup log already prints the bound URL via the existing Server running on http://… line; no extra fallback log is emitted.

Implementation

  • New private ServerPlugin.resolveListenPort() returns:
    • In development: await getPort({ host, port: portNumbers(requested, requested + 99) }).
    • Otherwise: the requested port (no scan).
  • start() awaits the resolved port before app.listen(...).
  • logStartupInfo() reads the resolved port so logs match the actual socket.
  • Adds get-port@7.2.0 to @databricks/appkit dependencies.

Test plan

  • pnpm --filter @databricks/appkit typecheck
  • pnpm exec vitest run packages/appkit/src/plugins/server/tests/server.test.ts packages/appkit/src/plugins/server/tests/server.integration.test.ts (37 tests pass; new dev/prod cases cover the resolution branches via a partial get-port mock)
  • pnpm exec biome check --write on touched files
  • Manual: start two dev playgrounds back-to-back; confirm second one binds 8001 (or next free port) and the URL line reflects it

When NODE_ENV is development, the server plugin now picks the first
available TCP port starting from the preferred port (server({ port }),
DATABRICKS_APP_PORT, or default 8000) and scanning upward using
get-port's portNumbers() helper (bounded to 100 ports). This avoids
EADDRINUSE failures when running multiple AppKit dev servers locally.

Production / non-development behavior is unchanged: the plugin binds
the configured/env/default port and surfaces listen errors as before.

Logging now reflects the actually bound port on the existing
"Server running on http://..." line; no extra fallback line is emitted.

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
@MarioCadenas MarioCadenas requested a review from a team as a code owner May 6, 2026 10:13
@MarioCadenas MarioCadenas requested a review from atilafassina May 6, 2026 10:13
Comment thread packages/appkit/src/plugins/server/index.ts
Address review feedback on #349: when the preferred dev listen port is
busy and the server binds a different port from the scan range, emit a
single info log "Port {requested} was busy, picking {bound}". Silent
when the preferred port was free.

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
@MarioCadenas MarioCadenas merged commit 12598dc into main May 6, 2026
8 checks passed
@MarioCadenas MarioCadenas deleted the mario/dev-dynamic-listen-port branch May 6, 2026 11:01
MarioCadenas added a commit that referenced this pull request May 7, 2026
Biome import collapsing on agent loader, run-agent, and tests after
rebasing onto main. Lockfile and synced plugin manifest reflect the
current main state (including get-port from #349 already on main).

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
MarioCadenas added a commit that referenced this pull request May 7, 2026
Biome import collapsing on agent loader, run-agent, and tests after
rebasing onto main. Lockfile and synced plugin manifest reflect the
current main state (including get-port from #349 already on main).

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
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