akostadinov akostadinov - 2 years ago 67
Ruby Question

How to get server time with mongoid 3.x?

Using MongoDB to schedule resource reservations. To be sure a broken client will not break the system I'd like to get server time and base queries on it.

I think that's possible with server side javascript but this is not directly supported by

gem and doesn't work because of db user permissions it seems.
I'm doing:

time_now = MongoModels::User.collection.database.session.cluster.with_primary do
MongoModels::User.collection.database.command(eval: """
function() {.
var now=new Date()
return now.toISOString()

I'm getting:

failed with error 13: "not authorized on cucushift to execute command { eval:

Another approach I thought would work without using javascript is getting server status. It should contain local time. But I can't find a way to get server status with

If anybody knows how to get server status or knows another way to get server local time. Or knows how to craft my query so that it compares with server time instead of client machine time, then that would be awesome. Thank you!

update: it seems I'm also disallowed to do serverStatus:

MongoModels::User.collection.database.command(serverStatus: 1)

failed with error 13: "not authorized on cucushift to execute command { serverStatus: 1 }"

This is strange IMO because it is not listed as admin only. Doing
I see:

{"help"=>"returns lots of administrative server statistics",

Answer Source

I found out the best way - allowing user to request server status. That's because the serverStatus command looks to be secure and is claimed to not affect mongodb server performance. To enable the account to get server status first I follow this serverfault question.

Then in ruby I do the above mentioned:

server_status = MongoModels::User.collection.database.command(serverStatus: 1)

Then I'm getting server time with:

[2] pry(#<CucuShift::MongoUserPoolQuery>)> server_status["localTime"]
=> 2014-10-29 09:44:55 UTC
[3] pry(#<CucuShift::MongoUserPoolQuery>)> server_status["localTime"] + 3600
=> 2014-10-29 10:44:55 UTC
[4] pry(#<CucuShift::MongoUserPoolQuery>)> server_status["localTime"].class
=> Time

I hope this helps somebody in the future.

btw I think it is also possible to get server time by saving a document and setting one of the fields to server current time. There are a couple of ways - see Is there any Equivalent of NOW() in MongoDB. Then read the doc and get server time at point of record insertion. But I think that is more heavyweight.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download