I have this repository class
public sealed class ProcessDataApiKeyRepository : IProcessDataApiKeyRepository
{
private readonly ElasticClient client;
private static readonly string index = nameof(ProcessDataApiKey).ToLower();
private readonly AppSettings _appSetting;
public ProcessDataApiKeyRepository(IOptions<AppSettings> appSetting)
{
_appSetting = appSetting.Value;
var node = new Uri(_appSetting.DbConnection.Elastic.Url);
var settings = new ConnectionSettings(node);
settings.DefaultIndex(index);
client = new ElasticClient(settings);
}
public async Task<bool> SaveApiKeyAsync(ProcessDataApiKey apiKey)
{
var response = await client.IndexAsync(apiKey);
return response.Created;
}
and inject this class in asp.net core default Di container
services.AddSingleton<IProcessDataApiKeyRepository, ProcessDataApiKeyRepository>();
Reading the Nest Documentation, the best way to manage the Nest client lifetimes
(https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/lifetimes.html)
is through the singleton instance.
But, I don't know if this way is the best, because I think that I should be just managing the Nest client class as singleton and then inject in any repository
I made some test using asp.net core scope lifetime
services.AddScoped<IProcessDataApiKeyRepository, ProcessDataApiKeyRepository>();
and the memory usage for each request was around 50 mg !!!!
with the singleton scope the memory usage peer request was around 2 mg
ConnectionSettings needs to be a singleton its what all the caches are leaning on.
ElasticClient may or may not be registered as a singleton, its thread safe so using a single instance is just fine.
I'd definitely make IElasticClient a constructor dependency that gets injected into ProcessDataApiKeyRepository
+1 to what @Mpdreamz said.
To elaborate a bit further, your current implementation of
services.AddSingleton<IProcessDataApiKeyRepository, ProcessDataApiKeyRepository>();
will cause each repository to have their own ConnectionSettings caches, which is definitely better than AddScoped which will create a new ConnectionSettings every time, basically defeating the purpose caching (hence the 50ms vs 2ms difference you observed).
But injecting a singleton instance of ConnectionSettings as Martijn suggested into each repository will cause all your repositories to share the same caches which will result in overall better performance.
@gmarz Thank you
Can anyone show me how to create a singleton object of Elasticclient in .net? for .net core it is straight forward.
Most helpful comment
+1 to what @Mpdreamz said.
To elaborate a bit further, your current implementation of
will cause each repository to have their own
ConnectionSettingscaches, which is definitely better thanAddScopedwhich will create a newConnectionSettings every time, basically defeating the purpose caching (hence the 50ms vs 2ms difference you observed).But injecting a singleton instance of
ConnectionSettingsas Martijn suggested into each repository will cause all your repositories to share the same caches which will result in overall better performance.