Skip to content

feat: Stop waiting for initialization after the configured start wait time - #60

Merged
kinyoklion merged 3 commits into
mainfrom
devin/dotnet-start-wait-timeout
Aug 20, 2026
Merged

feat: Stop waiting for initialization after the configured start wait time#60
kinyoklion merged 3 commits into
mainfrom
devin/dotnet-start-wait-timeout

Conversation

@kinyoklion

@kinyoklion kinyoklion commented Aug 19, 2026

Copy link
Copy Markdown
Member

SetProviderAsync never completed while LaunchDarkly was unreachable, so applications that await it could not start; the provider now gives up waiting after the configured StartWaitTime.

Closes #50.

  • Provider(Configuration) uses config.StartWaitTime as an initialization timeout; on expiry InitializeAsync fails with LaunchDarklyProviderInitException and logs a warning
  • The client keeps connecting, so a later successful connection emits a ProviderReady event and the provider recovers — matching the direction in Use StartWaitTime from configuration as provider blocking initialization timeout #50 ("transition to a provider error state and then continue to attempt to recover")
  • Evaluations during the error state are unaffected: the LaunchDarkly client serves whatever data it has, or falls back to defaults
  • Provider(ILdClient) (internal, and used by tests) still waits indefinitely, since there is no configuration to read a timeout from

@cursor review

Implementation details

Mechanism

InitializeAsync schedules a Task.Delay(StartWaitTime) continuation that, if _initCompletion has not completed, sets the provider status to Error and faults the task. Setting the status also consumes StatusProvider's "first event" suppression, which is what allows the subsequent Valid status to emit a real ProviderReady event instead of being swallowed as a duplicate of initialization.

Semantics worth a reviewer's opinion

new LdClient(config) already blocks for up to StartWaitTime in the provider constructor, and this timeout starts when InitializeAsync runs, so a totally offline start can now wait up to two StartWaitTime intervals before SetProviderAsync returns. Measuring the timeout from the constructor instead would require threading a start timestamp through, and would make StartWaitTime mean something different for the provider than for the SDK. Happy to change it if the doubled worst case is not acceptable.

Alternatives considered

Testing

dotnet test test/LaunchDarkly.OpenFeature.ServerProvider.Tests -f net8.0 — 62 tests pass, including a timeout test, a test that a client which becomes ready before the timeout does not fail, and a test that the provider still emits ProviderReady after a timed-out initialization. dotnet build src/LaunchDarkly.OpenFeature.ServerProvider -f netstandard2.0 succeeds with no warnings.

No visual preview applies — this is a server-side provider change.

Link to Devin session: https://app.devin.ai/sessions/0c452d209ec54b068ba120b4c92b8f6c
Requested by: @kinyoklion


Note

Overview
Stops InitializeAsync / SetProviderAsync from hanging forever when LaunchDarkly never becomes ready. The provider now treats Configuration.StartWaitTime as an init timeout (unless it is zero, which still means wait indefinitely).

On expiry it logs a warning, sets provider status to Error, and faults init with LaunchDarklyProviderInitException. The SDK client keeps connecting, so a later Valid data source still emits Ready and evaluations are not blocked. Ready/timeout completion is serialized with _initLock.

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

@kinyoklion kinyoklion self-assigned this Aug 19, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 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

@kinyoklion

Copy link
Copy Markdown
Member Author

If the provider later becomes ready will the OpenFeature SDK evaluate correctly? Or will it bypass the provider.

@devin-ai-integration

Copy link
Copy Markdown
Contributor

If the provider later becomes ready will the OpenFeature SDK evaluate correctly? Or will it bypass the provider.

Evaluations keep going through the provider, both while it is in the error state and after it recovers.

The OpenFeature .NET SDK only short-circuits on NotReady and Fatal; Error still calls the provider, so the LaunchDarkly client serves whatever data it has (or its own defaults). Setting the status to Error on timeout also consumes StatusProvider's first-event suppression, so the later Valid data source status emits a real ProviderReady event instead of being swallowed as a duplicate of initialization.

I extended ItBecomesReadyAfterInitializationTimesOut to assert exactly that: a flag evaluates through the provider immediately after the timeout, a ProviderReady event is emitted when the data source becomes valid, and evaluation still works afterwards.

@kinyoklion
kinyoklion marked this pull request as ready for review August 19, 2026 17:29
@kinyoklion
kinyoklion requested a review from a team as a code owner August 19, 2026 17:29

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8867055. Configure here.

Comment thread src/LaunchDarkly.OpenFeature.ServerProvider/Provider.cs Outdated
Comment thread src/LaunchDarkly.OpenFeature.ServerProvider/Provider.cs Outdated
devin-ai-integration Bot and others added 3 commits August 20, 2026 22:17
… time

Co-Authored-By: rlamb@launchdarkly.com <4955475+kinyoklion@users.noreply.github.com>
Co-Authored-By: rlamb@launchdarkly.com <4955475+kinyoklion@users.noreply.github.com>
Co-Authored-By: rlamb@launchdarkly.com <4955475+kinyoklion@users.noreply.github.com>
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/dotnet-start-wait-timeout branch from 935b351 to 5a7f3ed Compare August 20, 2026 22:17
@kinyoklion
kinyoklion merged commit 86e3d27 into main Aug 20, 2026
8 checks passed
@kinyoklion
kinyoklion deleted the devin/dotnet-start-wait-timeout branch August 20, 2026 22:24
kinyoklion pushed a commit that referenced this pull request Aug 20, 2026
🤖 I have created a release *beep* *boop*
---


##
[2.2.0](2.1.2...2.2.0)
(2026-08-20)


### Features

* Stop waiting for initialization after the configured start wait time
([#60](#60))
([86e3d27](86e3d27))


### Bug Fixes

* Do not report a permanent data source failure as fatal
([#59](#59))
([ed29935](ed29935))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> Release Please bump from **2.1.2** to **2.2.0**. Updates the package
`Version`, `.release-please-manifest.json`, and `CHANGELOG.md`.
> 
> The changelog documents stopping initialization wait after the
configured start wait time (#60) and not treating a permanent data
source failure as fatal (#59). No runtime code is changed in this PR.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d648a25. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use StartWaitTime from configuration as provider blocking initialization timeout

2 participants