Skip to content
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

MongoDb health check fails to be healthy when connecting to a database that has no collections yet #617

Closed
cscorley opened this issue Sep 2, 2020 · 2 comments · Fixed by #1626
Labels

Comments

@cscorley
Copy link

cscorley commented Sep 2, 2020

Please, fill the following sections to help us fix the issue

What happened:

MongoDb health check fails to be healthy when connecting to a database that has no collections. This is caused by an "Sequence contains no elements" exception.

What you expected to happen:

Reports healthy

How to reproduce it (as minimally and precisely as possible):

Create a Mongo database that has no collections. Specify this database as part of your connection string, e.g.,

mongodb://localhost/test

Source code sample:

        services.AddHealthChecks()
            .AddMongoDb(mongodbConnectionString: configuration.GetConnectionString("MongoDB"),
            name: "mongodb",
            failureStatus: HealthStatus.Unhealthy,
            tags: new[] { "ready" });

Anything else we need to know?:

We ran into an issue caused by our connection strings with this. Our setup is to have the client authorize against a particular database which has no collections, then switch to another db. I understand this is odd and there's a workaround (specify different db in the health check), but the assumption that there will be collections on the db causes a "Sequence contains no elements" exception.

I think the check should use a "FirstOrDefaultAsync" call for both if branches, which I think avoids this situation. I can also imagine scenarios where new databases are created that do not have collections yet that this scenario would apply.

d3a21e2#diff-e9b423a67796e60f4cafc9d188b866ee

Environment:

  • .NET Core version: 3.1
  • Healthchecks version: 3.1.2
  • Operative system: Windows Server 2016
  • Others:
@cscorley
Copy link
Author

cscorley commented Sep 2, 2020

Another alternative to listing databases/collections would be use Ping https://docs.mongodb.com/manual/reference/command/ping/

@KasperPurunen
Copy link

KasperPurunen commented Feb 17, 2021

I have ran into the same issue and have implemented my own version of the health check as follows:

public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context,
                CancellationToken cancellationToken = default)
            {
                try
                {
                    var mongoClient = MongoClient.GetOrAdd(_mongoClientSettings.ToString(),
                        _ => new MongoClient(_mongoClientSettings));

                    if (string.IsNullOrEmpty(_specifiedDatabase)) return HealthCheckResult.Healthy();

                    using var collectionCursor = await mongoClient
                        .GetDatabase(_specifiedDatabase)
                        .ListCollectionNamesAsync(cancellationToken: cancellationToken);
                    var collections = await collectionCursor.ToListAsync(cancellationToken);

                    if (collections.Any()) return HealthCheckResult.Healthy();

                    using var dbCursor = await mongoClient.ListDatabaseNamesAsync(cancellationToken);
                    await dbCursor.FirstOrDefaultAsync(cancellationToken);

                    return HealthCheckResult.Healthy();
                }
                catch (Exception ex)
                {
                    return new HealthCheckResult(context.Registration.FailureStatus, exception: ex);
                }
            }

Basically the difference from the original implementation is that if no collections are to be found we just list db names and assume that is good enough for validating the health of the connection to mongodb. I'm happy to create a PR if this solutions seems feasible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
3 participants