Skip to content

fix: FDv2 - Support dynamic reconnect URL for streaming. Handle 'error' event types for SSE.#1252

Open
kinyoklion wants to merge 2 commits intomainfrom
rlamb/fdv2-contract-test-updates
Open

fix: FDv2 - Support dynamic reconnect URL for streaming. Handle 'error' event types for SSE.#1252
kinyoklion wants to merge 2 commits intomainfrom
rlamb/fdv2-contract-test-updates

Conversation

@kinyoklion
Copy link
Copy Markdown
Member

@kinyoklion kinyoklion commented Apr 7, 2026

Note

Medium Risk
Changes streaming reconnection behavior and browser SSE error handling, which could affect connection stability and update delivery if the new URL-building or error classification is incorrect. Scope is limited to streaming/EventSource plumbing plus contract-test config tweaks.

Overview
Improves FDv2 streaming reconnect behavior by adding an optional urlBuilder to EventSourceInitDict and wiring FDv2 streaming to rebuild the stream URL (including dynamic query params like basis) on each reconnect attempt.

Updates the browser DefaultBrowserEventSource to use urlBuilder when reopening connections and to ignore server-sent SSE event: error messages in onerror (treating them as non-connection failures).

Contract-test tooling is adjusted to better support Data System configs without explicit connection modes (wrapping top-level initializers/synchronizers into a single streaming mode), plus minor repo hygiene (.mcp.json ignored; adds start:headless script).

Reviewed by Cursor Bugbot for commit fdf83b0. Bugbot is set up for automated code reviews on this repo. Configure here.

- Add start:headless script for running contract test entity without
  auto-opening a browser window
- Handle top-level dataSystem initializers/synchronizers in the contract
  test entity by wrapping them into a streaming connection mode
- Fix browser EventSource onerror firing for server-sent "error" SSE
  events by checking for MessageEvent instances
- Add urlBuilder to EventSourceInitDict so the browser EventSource can
  refresh the URL (including basis param) on reconnection
- Pass buildStreamUri as urlBuilder in StreamingFDv2Base
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

@launchdarkly/js-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 25661 bytes
Compressed size limit: 29000
Uncompressed size: 126143 bytes

"scripts": {
"install-playwright-browsers": "playwright install --with-deps chromium",
"start": "tsc --noEmit && vite --open=true",
"start:headless": "tsc --noEmit && vite",
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Helper for LLMs to run contract tests.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

@launchdarkly/browser size report
This is the brotli compressed size of the ESM build.
Compressed size: 179348 bytes
Compressed size limit: 200000
Uncompressed size: 830127 bytes

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

@launchdarkly/js-client-sdk size report
This is the brotli compressed size of the ESM build.
Compressed size: 31736 bytes
Compressed size limit: 34000
Uncompressed size: 112937 bytes

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

@launchdarkly/js-client-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 37181 bytes
Compressed size limit: 38000
Uncompressed size: 204409 bytes

@kinyoklion
Copy link
Copy Markdown
Member Author

Change Summary

This PR fixes the browser SDK to pass FDv2 contract tests. Here's what each change does:

.gitignore

Adds .mcp.json to gitignore — this is a local MCP server configuration file that shouldn't be checked in.

packages/sdk/browser/contract-tests/entity/package.json

Adds a start:headless script that runs the Vite dev server without --open=true. This prevents a second browser window from auto-opening when running contract tests via Chrome DevTools MCP or other headless approaches.

packages/sdk/browser/contract-tests/entity/src/ClientEntity.ts

Two changes:

  1. Extracted applyEndpointOverrides helper — refactors the endpoint URI extraction logic (previously inline in the connectionModeConfig branch) into a reusable function.
  2. Added support for top-level dataSystem.initializers/synchronizers — Some FDv2 contract tests send initializers and synchronizers at the top level of dataSystem (without connectionModeConfig). The browser SDK requires connection modes, so the entity now wraps top-level initializers/synchronizers into a single 'streaming' connection mode. This fixes the polling initializer tests (e.g. "initializes from polling initializer") and the multi-synchronizer tests (e.g. "disconnects on goodbye").

packages/sdk/browser/src/platform/DefaultBrowserEventSource.ts

Two fixes:

  1. instanceof MessageEvent guard in onerror — In Chrome, when the server sends an SSE event with event: error, the native EventSource fires BOTH addEventListener('error', ...) AND onerror. The onerror handler was unconditionally closing the connection and reconnecting, which prevented the FDv2 protocol handler from processing server-sent error events. A server-sent error arrives as a MessageEvent, while a real connection error is a plain Event — so we skip _handleError for MessageEvent instances.
  2. urlBuilder support for reconnection — The browser's native EventSource reconnects to the same URL. For FDv2, the basis query parameter needs to be updated on each reconnection to reflect the most recently received selector/state. The _openConnection method now calls urlBuilder() (if provided) to get a fresh URL before creating a new EventSource.

packages/shared/common/src/api/platform/EventSource.ts

Adds an optional urlBuilder callback to EventSourceInitDict. Platform EventSource implementations can call this on reconnection to get an updated URL (e.g. with a refreshed basis query parameter).

packages/shared/sdk-client/src/datasource/fdv2/StreamingFDv2Base.ts

Passes buildStreamUri as the urlBuilder when creating the EventSource. This ensures that when the browser EventSource reconnects, it calls buildStreamUri() which reads the current selector via selectorGetter() and includes the correct basis parameter.

@kinyoklion kinyoklion changed the title fix: Fixes for browser FDv2 contract tests. fix: FDv2 - Support dynamic reconnect URL for streaming. Handle 'error' event types for SSE. Apr 7, 2026
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The jank in here may be temporary as @tanderson-ld and @aaron-zeisler are adjusting the tests.

@kinyoklion
Copy link
Copy Markdown
Member Author

bugbot review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit fdf83b0. Configure here.

@kinyoklion kinyoklion marked this pull request as ready for review April 7, 2026 22:21
@kinyoklion kinyoklion requested a review from a team as a code owner April 7, 2026 22:21
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