-
Notifications
You must be signed in to change notification settings - Fork 10
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
Startup init for singletons #15
Comments
Adding some context from slack A suggestion was made to use a background worker to prewarm anything that needs prewarming. Essentially having a central "warmup class" I'm not against people doing this, but one of the principles that we built agoda ioc on was decentralization of responsibilities, The 4k line UnityConfiguration class in the Agoda website from many years ago comes to mind. When we look at the example in one of the larger supply extranets where we want to apply this, there's about more than 20 services/repos that need prewarm (a lot less than unity configuration nightmare for sure), then i think about the unit test we would need to write. var underTest = new PrewarmService(MockGeoRepository,MockLanguageRepository, ...);// passing in >20 mocks
// we also have static content checks that this would fail because the ctor has too many parameters
MockGeoRepository.Prewarm().Received(1);
MockLanguageRepository.Prewarm().Received(1);
// copy past this type of line 20 times Maybe I am missing something, but i feel this is less elegant than the autofac solution. |
I find the It even feels less "safe" compared just using the service collection extensions directly, because |
So @szaboopeeter you are suggesting we do something like [RegisterSingleton]
public class MyRepoThatNeedsWarmup : IMyRepoThatNeedsWarmup, IStartupable
{
// ..
} As the approach, so it's just a singleton in terms of attribute, and we infer the Startup feature by the fact it is inheriting from IStartupable? |
``This is my idea Let's say on consumer of Agoda.Ioc have these class [RegisterSingleton]
public class MyRepoThatNeedsWarmup1 : IMyRepoThatNeedsWarmup1, IStartableAsync
{
// IStartableAsync implementation
public async Task StartAsync(){
// Do warmup
}
}
[RegisterSingleton]
public class MyRepoThatNeedsWarmup2 : IMyRepoThatNeedsWarmup2, IStartableAsync
{
// IStartableAsync implementation
public async Task StartAsync(){
// Do warmup
}
} All of these class were register as In Agoda.Ioc we provide new IHostedService called /// <summary>
/// This service was registered by Agoda.Ioc if comsumer has IStartableAsync implementation class
/// services.AddHostedService<NeedsWarmupBackgroundWorker>();
/// </summary>
public class NeedsWarmupBackgroundWorker : IHostedService
{
private readonly IEnumerable<IStartableAsync> _startableAsyncs;
// inject all singleto services
public cBackgroundWorker(IEnumerable<IStartableAsync> startableAsyncs)
{
_startableAsyncs = startableAsyncs;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
foreach (var startableAsync in _startableAsyncs)
{
await startableAsync.StartAsync();
}
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
} This way before we start we can make sure every NeedsWarmup class will be done before app start |
@kchinburarat when is StartAsync Called? It's after app.Run()? Or no? |
I think it will start on app.run and should finish before kestrel do port binding |
Autofac has this
anything that inherits from it will init on startup.
It's a cool idea some something we use in Supply extranets at Agoda. There this IHostedService now as well for background workers too
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-6.0&tabs=visual-studio
Idea would be to do something like this if we follow the autofac approach
And then call a GetService after app init, this would also require use to add a new extension method though something like "UseAgodaIoC", or more specific "StartupAgodaIoCSingletons".
Alternatively we could simply leverage the IHostedService and register them with a new attribute
The problem here though is that AddHostedService has no support for registering an interface.
In most of our use cases the startup method is prewarming cache in singletons that are later used for data fetchnig (i.e. Repositories, etc). So i think this wont work for us as we need interfaced use in teh regestration to properly mock for unit testing, so we need something simple like the autofac example imo.
Thoughts?
The text was updated successfully, but these errors were encountered: