Elasticsearch-net: asp.net core ElasticClient DI scope

Created on 13 Jul 2016  路  4Comments  路  Source: elastic/elasticsearch-net

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

Most helpful comment

+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.

All 4 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

meriturva picture meriturva  路  3Comments

gmarz picture gmarz  路  5Comments

mausch picture mausch  路  4Comments

alwag85 picture alwag85  路  5Comments

jhellemann picture jhellemann  路  4Comments