Skip to content

feat: Add goodbye-event FDv1 fallback directive test (SDK-2511)#359

Draft
devin-ai-integration[bot] wants to merge 2 commits into
v3from
devin/1781297931-sdk-2511-goodbye-fdv1-fallback
Draft

feat: Add goodbye-event FDv1 fallback directive test (SDK-2511)#359
devin-ai-integration[bot] wants to merge 2 commits into
v3from
devin/1781297931-sdk-2511-goodbye-fdv1-fallback

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

Related issues

SDK-2511 — Strengthen FDv1 fallback contract test to validate flag delivery

Describe the solution you've provided

The existing FDv1FallbackDirective tests exercise the X-LD-FD-Fallback HTTP response header form of the directive. This PR adds coverage for the in-band goodbye SSE event form (protocolFallbackTTL field on the goodbye event), per FDV2PL spec §3.7 and CSFDV2 spec §8.3.4.

This transport is essential for browser SDKs using native EventSource, which cannot read HTTP response headers on streaming connections.

Changes:

  • framework/types.go: Add ProtocolFallbackTTL *int field to Goodbye struct (matches goodbye.json schema)
  • mockld/streaming_service.go: Add PushGoodbyeWithFallback(reason, ttlSeconds) helper
  • sdktests/common_tests_stream_fdv2.go: Add DirectiveViaGoodbyeEngagesFDv1 test — delivers a full FDv2 streaming basis, pushes a goodbye with protocolFallbackTTL: 0, then asserts the SDK transitions to FDv1 and evaluates flag values from FDv1 data

Describe alternatives you've considered

Could have added the protocolFallbackTTL field directly to PushGoodbye, but a separate method keeps the existing goodbye-without-fallback call sites clean and makes the intent explicit.

Additional context

The unparam lint warning on fdv1FallbackBody's flagKey parameter (all callers pass "flag-key") was suppressed with a //nolint directive since the parameter exists for API flexibility.

Link to Devin session: https://app.devin.ai/sessions/2d369b0a4d114c6d9fd948cc39f26a9c

Add a test that exercises the in-band goodbye SSE event form of the FDv1
Fallback Directive (protocolFallbackTTL field on the goodbye event), per
FDV2PL spec §3.7 and CSFDV2 spec §8.3.4.

This transport is essential for browser SDKs using native EventSource,
which cannot read HTTP response headers on the streaming connection.

Changes:
- Add ProtocolFallbackTTL field to framework.Goodbye struct
- Add PushGoodbyeWithFallback to StreamingService
- Add DirectiveViaGoodbyeEngagesFDv1 test to the FDv1FallbackDirective suite

Co-Authored-By: Bee Klimt <bklimt@launchdarkly.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot added the devin-pr PRs created by Devin label Jun 12, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

@cursor review

Comment thread sdktests/common_tests_stream_fdv2.go Outdated
// Send the goodbye event with protocolFallbackTTL to trigger FDv1 fallback.
// TTL 0 means indefinite fallback — the SDK must not attempt FDv2 recovery.
dataSystem.Synchronizers[0].streaming.PushGoodbyeWithFallback("fdv1-fallback-directed", 0)
conn.Cancel()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am a little concerned that the dropped connection and the SDK processing the fallback might race?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — removed conn.Cancel() entirely. The test now waits for the SDK to close the streaming connection itself (via conn.Context.Done()), which proves the SDK actually processed the goodbye event before transitioning. Force-cancelling could have raced the SDK's event processing and masked bugs where the goodbye is ignored.

…oodbye

Instead of force-cancelling the connection (which races the SDK's goodbye
event processing), wait for the SDK to close the streaming connection
itself via context cancellation. This proves the SDK actually processed
the protocolFallbackTTL directive rather than just seeing a dropped
connection.

Co-Authored-By: Bee Klimt <bklimt@launchdarkly.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

devin-pr PRs created by Devin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant