Skip to content

fix: initialize lifecycle on hosts without IHostedLifecycleService support#787

Open
askpt wants to merge 3 commits into
mainfrom
askpt/redesigned-fortnight
Open

fix: initialize lifecycle on hosts without IHostedLifecycleService support#787
askpt wants to merge 3 commits into
mainfrom
askpt/redesigned-fortnight

Conversation

@askpt

@askpt askpt commented Jul 17, 2026

Copy link
Copy Markdown
Member

This PR

Fixes provider initialization and shutdown never running on hosts that only support IHostedService, such as the legacy ASP.NET Core WebHost/WebHostBuilder.

Why

The legacy WebHost never invokes the IHostedLifecycleService callbacks (StartingAsync/StartedAsync/StoppingAsync/StoppedAsync), and upstream support was declined (dotnet/aspnetcore#60176). Since FeatureLifecycleStateOptions defaults to StartState = Starting and StopState = Stopped, HostedFeatureLifecycleService waited for callbacks that never fired, so providers were never registered nor gracefully shut down on such hosts.

How

  • HostedFeatureLifecycleService now records whether the host invoked StartingAsync (the generic host always calls it before StartAsync). When it was never invoked, StartAsync/StopAsync fall back to running the configured initialization/shutdown, covering all FeatureStartState/FeatureStopState values. An informational log is emitted when the fallback engages.
  • Behavior on the generic host (WebApplication.CreateBuilder, Host.CreateDefaultBuilder) is unchanged, and initialization still runs at most once.
  • Added HostedFeatureLifecycleServiceTests covering generic-host callback sequences and IHostedService-only sequences for every start/stop state.
  • Documented lifecycle management, the automatic fallback, and explicit FeatureLifecycleStateOptions configuration in the Hosting README.

Notes

Fixes #773

Related Issues: dotnet/aspnetcore#60176

Follow-up Tasks

N/A

How to test

Run the hosting test suite: dotnet test test/OpenFeature.Hosting.Tests. To reproduce the original bug, host OpenFeature in an app built with WebHost.CreateDefaultBuilder and observe that providers now initialize with default options.

…pport

The legacy ASP.NET Core WebHost only invokes IHostedService.StartAsync and
StopAsync, never the IHostedLifecycleService callbacks. With the default
FeatureLifecycleStateOptions (StartState=Starting, StopState=Stopped),
providers were never initialized nor shut down on such hosts.

HostedFeatureLifecycleService now detects whether the host invoked
StartingAsync and, when it did not, falls back to StartAsync/StopAsync to
run the configured initialization and shutdown.

Fixes #773

Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4623f36a-d6ec-427c-b6cf-525f60d3077e

📥 Commits

Reviewing files that changed from the base of the PR and between 1fe490f and 36469d6.

📒 Files selected for processing (3)
  • src/OpenFeature.Hosting/HostedFeatureLifecycleService.cs
  • src/OpenFeature.Hosting/README.md
  • test/OpenFeature.Hosting.Tests/HostedFeatureLifecycleServiceTests.cs

📝 Walkthrough

Walkthrough

HostedFeatureLifecycleService now detects whether hosted lifecycle callbacks are supported, falls back to configured StartAsync/StopAsync states when needed, logs that fallback, and adds tests and documentation for generic-host and web-host behavior.

Changes

Hosted lifecycle fallback

Layer / File(s) Summary
Lifecycle callback detection and fallback
src/OpenFeature.Hosting/HostedFeatureLifecycleService.cs
Tracks lifecycle callback support, conditionally initializes and shuts down at configured boundaries, and logs fallback execution.
Lifecycle behavior documentation and tests
test/OpenFeature.Hosting.Tests/HostedFeatureLifecycleServiceTests.cs, src/OpenFeature.Hosting/README.md
Validates generic-host callback timing, web-host fallback behavior, exactly-once execution, and lifecycle configuration documentation.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Host
  participant HostedFeatureLifecycleService
  participant IFeatureLifecycleManager
  Host->>HostedFeatureLifecycleService: Invoke StartingAsync, StoppedAsync, StartAsync, or StopAsync
  HostedFeatureLifecycleService->>HostedFeatureLifecycleService: Check callback support and configured lifecycle state
  HostedFeatureLifecycleService->>IFeatureLifecycleManager: EnsureInitializedAsync or ShutdownAsync
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding lifecycle initialization fallback for hosts without IHostedLifecycleService support.
Description check ✅ Passed The description is clearly related to the changeset and explains the bug, fix, tests, and documentation updates.
Linked Issues check ✅ Passed The changes address #773 by making HostedFeatureLifecycleService initialize and shut down on WebHost-style IHostedService-only hosts.
Out of Scope Changes check ✅ Passed The added tests, logging, and README updates all support the lifecycle fallback fix and appear in scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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.

@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.55%. Comparing base (1fe490f) to head (36469d6).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #787      +/-   ##
==========================================
+ Coverage   93.18%   93.55%   +0.37%     
==========================================
  Files          66       66              
  Lines        2993     3010      +17     
  Branches      376      378       +2     
==========================================
+ Hits         2789     2816      +27     
+ Misses        140      130      -10     
  Partials       64       64              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

askpt added 2 commits July 17, 2026 18:01
Adds generic-host stop timing coverage per stop state, a shutdown test for
hosts stopping services before StartAsync ever ran, and clarifies in the
README that the fallback preserves lifecycle execution rather than exact
callback timing on IHostedService-only hosts.

Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
@askpt
askpt marked this pull request as ready for review July 17, 2026 17:03
@askpt
askpt requested a review from a team as a code owner July 17, 2026 17:03
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.

[BUG] HostedFeatureLifecycleService never initializes in ASP.NET core

2 participants