Closed rgubby closed 8 years ago
Same etag as a MongoDate:
$updatedAt = new UTCDateTime(floor(microtime(true) * 1000));
echo $updatedAt;
MongoDB\BSON\UTCDateTime Object
(
[milliseconds] => 1479817009038
)
$mongodate = new \MongoDate();
echo $mongodate;
0.03800000 1479817009
$seconds = $updatedAt->__toString() / 1000;
$eTag = number_format(($seconds - floor($seconds)), 6) . "00 " . floor($seconds);
echo print_r($eTag,true)
0.03800000 1479817009
I have created a test script (https://github.com/talis/tripod-php/blob/a382b6ee9bd02cb54c24692d8a9b723668f6a5d3/scripts/mongo/testEtag.php) that gets all documents from a collection for a tenancy and outputs the etag.
I've run this for the surrey tenancy on CBD_config (71 records) and CBD_draft (244382 records).
I have then run a modified version of this script on the old mongo driver:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once('./common.inc.php');
require_once('../../src/tripod.inc.php');
$config = json_decode(file_get_contents('../../test/rest-interface/config/tripod-config.json'), true);
\Tripod\Mongo\Config::setConfig($config);
\Tripod\Mongo\Config::getInstance()->setConfig($config);
$tripod = new \Tripod\Mongo\Driver('CBD_draft','surrey',array('defaultContext'=>'http://talisaspire.com/'));
require_once '../../src/tripod.inc.php';
$client = new \MongoClient();
$db = $client->selectDb('surrey');
$collection = $db->selectCollection('CBD_draft');
$cursor = $collection->find(array());
foreach($cursor as $doc) {
$etag = isset($doc['_uts']) ? $doc['_uts']->__toString() : '' ;
echo '_id.r: '.$doc['_id']['r'] . ' - ' . $etag . "\n";
}
Now I have both results saved out to a local file, I can then do a diff on the 2 files to see if there are any discrepancies.
I can confirm that there are none - the 2 files (one for CBD_config, one for CBD_draft) are identical. This confirms that the etag returned with the new method is equivalent of the MongoDate::__toString()
function.
Manual 👍 from @kiyanwang
The last release started using the new PHP mongo driver. Usage of
MongoDate
has been replaced withUTCDateTime
. The problem with this is that the__toString()
function for each of those return dates in a different format. MongoDate returns it in a microtime format, UTCDateTime return it in milliseconds since epoch.If you only use one or the other, then there isn't a problem. But if you want to dual run the 2 versions (rolling upgrade of code) and you retrieve an etag from one server with the previous version on, but update to a newer server with new version on, you can get a mismatched etag.
We are converting the millisecond date format returned in the
__toString()
function ofUTCDateTime
into a float, then using the float part to return the microtime formatted date. This should now be compatible withMongoDate::__toString()
.In addition to this - we have introduced a bug with means we are not storing the microsecond part of the date. We are doing a multiplication of 1000 AFTER rounding, rather than before rounding. So you end up with a value with
000
at the end - which always gives you a microsecond value of000
. If we don't store the microsecond part of the date, our new etag format will always return0.00000000
as the microsecond part.Todo
Resolves #115 Resolves #116