-
Notifications
You must be signed in to change notification settings - Fork 0
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
.NET LaunchDarkly SDK incompatible with Orleans or other single-threaded TaskSchedulers #32
Comments
Thank you for bringing this to our attention @alexn-tinwell. We will discuss on team and get back to you later this week. |
@alexn-tinwell, we investigated and were able to identify this change as having changed the code from using Documentation here seems to indicate we should use You mention steps to reproduce being to create a Orleans project. Are you able to provide the source code for a sample project in which you were able to reproduce the issue? That could help us iterate more quickly as we work to solve this. I am also unsure if there may be other logic/components in the SDK that don't operate well in a single threaded environment and can't guarantee any timeline for this refactoring to be completed. We have long term goals of refactoring several of our SDKs to use native async support in each respect language, so this work may get lumped in to that. Does the workaround you have of instantiating the client in |
(apologies for the notification noise; I fat-fingered this response while drafting) @tanderson-ld Thanks for looking into this! In the context of Orleans, it's not that it's single-threaded per se, it's that it overrides the
An interim improvement on your end could be:
I haven't tested as we're heads-down on something rn, but this should avoid the issue entirely because this would start your long-running process on the default threadpool rather than the one being used by the caller of the SDK. We have been unblocked by the You may prefer to replicate this by simply implementing a custom |
👋 we're evaluating an SDK / API version upgrade at the moment and I was reminded about this issue. Has there been any further thought / progress on resolving it? |
Describe the bug
We've found that unless we call
Events(Components.NoEvents)
on the SDK, all Orleans mesh activity is halted at app startup around the same time that an LdClient singleton is first instantiated.For context, Microsoft Orleans is a virtual actor / service mesh framework. Grain (actor) instances are executed with a custom task scheduler that is intentionally single-threaded so that the core framework managing the instance mesh can reason about the resource impact of each grain activation and balance them across nodes as required.
Unfortunately, turning off LaunchDarkly analytics events also appears to disable auto-creation of new ContextKinds. We can reference User contexts just fine, but when trying to create a custom context kind for backend services, the context is never shown in the LD dashboard unless we turn events back on, but in that case the app hangs shortly after boot.
I theorise that it's related to the internal implementation of
EventProcessorInternal
, which starts the main message loop usingTask.Factory.StartNew
(which usesTaskScheduler.Current
internally). In scenarios whereLdClient
is instantiated in the context of an Orleans Grain, this could block the only thread on the scheduler and prevent other work from ever occurring.Furthermore, the implementation of
RunMainEventLoop
is inefficient because it pegs that thread with no slippage or sleeping between loop iterations whatsoever, so that thread is unlikely ever to relinquish context to other waiting tasks even when there is no work to perform.For reasons I can't quite understand,
EventProcessor
implements no interfaces and is sealed, so we can't resolve this ourselves short of forking the SDK.To reproduce
Create any sample Orleans application with a couple of grains, declare LdClient as a singleton for the Silo, and observe communication timeouts between grains.
While I couldn't prove my theory by modifying the SDK code or overriding the implementation, I did find a correlating fix.
Spot the difference:
Hangs any app using a single-threaded task scheduler:
Does not hang the app because the client is instantiated on a threadpool thread using
Task.Run
:Expected behavior
Merely instantiating the SDK should have no adverse affects on the hosting application nor peg a CPU thread.
Logs
If applicable, add any log output related to your problem.
SDK version
8.0.0.0 but this was also present in 7.x. We ignored it until now because we weren't using events, but now want to reference custom ContextKinds and couldn't get them working until we turned events back on.
Language version, developer tools
C# / .NET 7
OS/platform
Any
Additional context
If you must start your own long-running threads inside an SDK instead of exposing an
IHostedService
, always pass inTaskScheduler.Default
(and ideally useTask.Run
instead ofTask.Factory.StartNew
)The text was updated successfully, but these errors were encountered: