Im having a hard time connecting to elasticsearch form my dotnet 9 application.
System.NullReferenceException: Object reference not set to an instance of an object.
at Elastic.Transport.DistributedTransport`1.RequestCoreAsync[TResponse](Boolean isAsync, EndpointPath path, PostData data, Action`1 configureActivity, IRequestConfiguration localConfiguration, CancellationToken cancellationToken)
at Elastic.Clients.Elasticsearch.ElasticsearchClient.<>c__DisplayClass865_0`3.<<DoRequestCoreAsync>g__SendRequestWithProductCheckCore|2>d.MoveNext() in /_/src/Elastic.Clients.Elasticsearch/_Shared/Client/ElasticsearchClient.cs:line 221
--- End of stack trace from previous location ---
at Elastic.Clients.Elasticsearch.ElasticsearchClient.<>c__DisplayClass865_0`3.<<DoRequestCoreAsync>g__SendRequestWithProductCheck|1>d.MoveNext() in /_/src/Elastic.Clients.Elasticsearch/_Shared/Client/ElasticsearchClient.cs:line 180
--- End of stack trace from previous location ---
at Rust.Domain.Infrastructure.Searching.SearchProvider.HealthyAsync(CancellationToken cancellationToken) in /src/src/Rust.Domain/Infrastructure/Searching/SearchProvider.cs:line 21
at Rust.GameserverIndexer.GameserverIndexer.EnsureIndexRebuiltAsync(CancellationToken cancellationToken) in /src/src/Rust.GameserverIndexer/GameserverIndexer.cs:line 64
at Rust.GameserverIndexer.GameserverIndexer.EnsureIndexRebuiltAsync(CancellationToken cancellationToken) in /src/src/Rust.GameserverIndexer/GameserverIndexer.cs:line 67
at Rust.GameserverIndexer.GameserverIndexer.ExecuteAsync(CancellationToken stoppingToken) in /src/src/Rust.GameserverIndexer/GameserverIndexer.cs:line 39
at Microsoft.Extensions.Hosting.Internal.Host.TryExecuteBackgroundServiceAsync(BackgroundService backgroundService)
Very, very similar issues on both 9.0.1 and 8.17.1, I downgraded to check which makes me think this is a skill issue.
Im currently using Microsoft.Extensions.DependencyInjection and registering the client as a singleton:
builder.Services.AddSingleton(sp =>
{
IConfiguration configuration = sp.GetRequiredService<IConfiguration>();
ILogger<ElasticsearchClient> logger = sp.GetRequiredService<ILogger<ElasticsearchClient>>();
Uri[] nodeUris = configuration.GetValue<string>("ELASTIC_NODES")?
.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(uri => new Uri(uri))
.ToArray() ?? throw new InvalidOperationException("ELASTIC_NODES configuration is missing or invalid.");
if (nodeUris.Length == 0)
throw new InvalidOperationException("No valid ELASTIC_NODES provided.");
string apiKey = configuration.GetValue<string>("ELASTIC_APIKEY")
?? throw new InvalidOperationException("ELASTIC_APIKEY configuration is missing.");
ElasticsearchClientSettings settings = new ElasticsearchClientSettings(new StaticNodePool(nodeUris))
.Authentication(new Base64ApiKey(apiKey))
.ServerCertificateValidationCallback((_, _, _, _) => true)
.ThrowExceptions(true)
#if DEBUG
.EnableDebugMode(x =>
{
logger.LogDebug(x.DebugInformation);
})
#endif
;
return new ElasticsearchClient(settings);
});
And using it in my service which is registered as transient:
public class SearchProvider : ISearchProvider
{
private readonly ILogger<SearchProvider> logger;
private readonly ElasticsearchClient _client;
public SearchProvider(ILogger<SearchProvider> logger, ElasticsearchClient client)
{
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
_client = client ?? throw new ArgumentNullException(nameof(client));
}
public async Task<bool> HealthyAsync(CancellationToken cancellationToken)
{
Elastic.Clients.Elasticsearch.Cluster.HealthResponse health = await _client.Cluster.HealthAsync(cancellationToken);
if (!health.IsValidResponse)
{
throw new Exception($"Elasticsearch health check failed: {health.DebugInformation}");
}
return health.Status == HealthStatus.Green;
}
}
My app starts a hosted service which the first thing it does is call the HealthyAsync method, which throws the above error.
I feel like im missing a step. anyone got ideas?