Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FeatureRefreshWorker throws intermittent errors with .NET Framework #36

Open
acappiello opened this issue Apr 11, 2024 · 0 comments
Open

Comments

@acappiello
Copy link

When integrating GrowthBook with a .NET Framework application (at least I've only been able to reproduce in .NET Framework), I observe intermittent errors logged from the FeatureRefreshWorker. A minimal reproduction can be observed as follows:

  1. Have GrowthBook Proxy running (in my case, on localhost).
  2. Have a project targeting .NET Framework, e.g. 4.8.
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net48</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="growthbook-c-sharp" Version="1.0.5" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
  </ItemGroup>

</Project>
  1. Initialize GrowthBook from the code.
static async Task Main(string[] args)
{
	using (var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()))
	{
		var context = new Context
		{
			ApiHost = "http://localhost:3300/",
			ClientKey = "sdk-your-key",
			LoggerFactory = loggerFactory,
		};

		var gb = new GrowthBook(context);
		await gb.LoadFeatures();
		await Task.Delay(Timeout.Infinite); // Sit back and wait a little bit.
	}
}

The logs written to the console look like this:

info: GrowthBook.GrowthBook[0]
      Loading features from the repository
info: GrowthBook.Api.FeatureRepository[0]
      Getting features from repository, verifying cache expiration and option to force refresh
info: GrowthBook.Api.FeatureRepository[0]
      Cache has expired or option to force refresh was set, refreshing the cache from the API
info: GrowthBook.Api.FeatureRefreshWorker[0]
      Making an HTTP request to the default Features API endpoint 'http://localhost:3300/api/features/sdk-your-key'
info: GrowthBook.Api.FeatureRepository[0]
      Either cache currently has no features or the option to wait for completion was set, waiting for cache to refresh
info: GrowthBook.Api.FeatureRefreshWorker[0]
      API response JSON contained no encrypted features, returning '2' unencrypted features
info: GrowthBook.GrowthBook[0]
      Loading features has completed, retrieved '2' features
info: GrowthBook.Api.FeatureRefreshWorker[0]
      The listener for server sent events is now running
info: GrowthBook.Api.FeatureRefreshWorker[0]
      Making an HTTP request to server sent events endpoint 'http://localhost:3300/sub/sdk-your-key'
info: GrowthBook.Api.FeatureRefreshWorker[0]
      Making an HTTP request to server sent events endpoint 'http://localhost:3300/sub/sdk-your-key'
info: GrowthBook.Api.FeatureRefreshWorker[0]
      Making an HTTP request to server sent events endpoint 'http://localhost:3300/sub/sdk-your-key'
fail: GrowthBook.Api.FeatureRefreshWorker[0]
      Encountered an unhandled exception during request to server sent events endpoint 'http://localhost:3300/sub/sdk-your-key'
      System.IO.IOException: The read operation failed, see inner exception. ---> System.Net.WebException: The request was aborted: The request was canceled.
         at System.Net.ConnectStream.Read(Byte[] buffer, Int32 offset, Int32 size)
         at System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.Read(Byte[] buffer, Int32 offset, Int32 count)
         --- End of inner exception stack trace ---
         at System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.Read(Byte[] buffer, Int32 offset, Int32 count)
         at System.IO.StreamReader.ReadBuffer()
         at System.IO.StreamReader.get_EndOfStream()
         at GrowthBook.Api.Extensions.HttpClientExtensions.<UpdateWithFeaturesStreamFrom>d__2.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
         at GrowthBook.Api.FeatureRefreshWorker.<<ListenForServerSentEvents>b__15_0>d.MoveNext()
info: GrowthBook.Api.FeatureRefreshWorker[0]
      Making an HTTP request to server sent events endpoint 'http://localhost:3300/sub/sdk-your-key'
info: GrowthBook.Api.FeatureRefreshWorker[0]
      Making an HTTP request to server sent events endpoint 'http://localhost:3300/sub/sdk-your-key'

The exception points to the use of EndOfStream in UpdateWithFeaturesStreamFrom, which can throw when the underlying stream is already closed (race condition?). Functionally, this doesn't cause any issues, but it's leaving a mess of errors in the logs. Hopefully, this can be improved to eliminate the exceptions.

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

No branches or pull requests

1 participant