gottscj/Hangfire.Mongo

GetUtcDateTime need authorized on admin,

hetaoos opened this issue · 9 comments

@hetaoos,

I see. Actually it should not be needed to use the admin db for getting the hostInfo.
Could you kindly try the following:

/// <inheritdoc />
public class TestMongoConnection : MongoConnection
{
    private readonly HangfireDbContext _database;

    /// <inheritdoc />
    public TestMongoConnection(HangfireDbContext database, MongoStorageOptions storageOptions) 
        : base(database, storageOptions)
    {
        _database = database;
    }

    /// <inheritdoc />
    public override DateTime GetUtcDateTime()
    {
        // hostInfo.system.currentTime
        var command = new JsonCommand<BsonDocument>("{'hostInfo': 1}");
        // var database = _dbContext.Client.GetDatabase("admin");
        var cmdResponse = _database.Database.RunCommand(command);
        var serverTime = cmdResponse["system"]["currentTime"].ToUniversalTime();
        return serverTime;
    }
}

you need to setup you configuration like this to use the test connection class:

/// <inheritdoc />
public class TestMongoFactory : MongoFactory
{
    /// <inheritdoc />
    public override MongoConnection CreateMongoConnection(HangfireDbContext dbContext, MongoStorageOptions storageOptions)
    {
        return new TestMongoConnection(dbContext, storageOptions);
    }
}

var mongoClient = new MongoClient("connectionString");
var storage = new MongoStorage(mongoClient, "hangfire.mongo", new MongoStorageOptions
{
    Factory = new TestMongoFactory()
});

The code is not working.

https://www.mongodb.com/docs/v6.0/reference/command/hostInfo/

You must run the hostInfo command, which takes no arguments, against the admin database.

@hetaoos,

OK. its a case of "It works on my machine" :)

Then for now, I suggest you return DateTime.UtcNow in the "GetUtcDateTime" method which would be the fallback logic anyway.

I'll look at alternatives or an easier way of configuring this feature.

OK, thanks.

@hetaoos,

Could you try the following in "GetUtcDateTime"?

var pipeline = new[]
{
    new BsonDocument("$project", new BsonDocument("date", "$$NOW"))
};
var time = _dbContext.Server.Aggregate<BsonDocument>(pipeline).FirstOrDefault();
return time["date"].ToUniversalTime();

Hi, This code works. But if the hangfire.server collection is empty, an exception will be thrown.

28683bdb2493423015f12951ed219ba

I recommend using the hangfire.schema collection.
By the way, the pipeline needs to add $limit to limit return one record.

 var pipeline = new[]
 {
      new BsonDocument("$project", new BsonDocument("date", "$$NOW")),
      new BsonDocument("$limit", 1)
 };
var time = dbContext.Schema.Aggregate<BsonDocument>(pipeline).FirstOrDefault();
return time != null ? time["date"].ToUniversalTime() : DateTime.UtcNow;

@hetaoos,

I added the fix with PR #353
the $limit stage should be redundant as im using FirstOrDefault which will iterate the IAsyncCursor only once

https://github.com/Hangfire-Mongo/Hangfire.Mongo/blob/6ba69bcd1608319bf47bc895f66d6d9b8af74fd4/src/Hangfire.Mongo/MongoConnection.cs#L680

thanks

You're welcome and thank you too.