GetUtcDateTime need authorized on admin,
hetaoos opened this issue · 9 comments
Ordinary database users are not normally authorized to access the admin database.
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.
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.
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.
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;
I added the fix with PR #353
the $limit stage should be redundant as im using FirstOrDefault which will iterate the IAsyncCursor only once
thanks
You're welcome and thank you too.