From 9ea66c0440d1e4f4117c4dd6c9dc90f4bb86a817 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Mon, 9 Sep 2019 16:23:15 -0400 Subject: [PATCH] TokenDao: Lift out nondeterminism (date) * src/server/daemon/controller.js (getUnixTimestamp): New method. Not ideal, but better than where it was. (_initExportService): Pass to TokenDao constructor. * src/server/token/TokenDao.ts (_getTimestamp): New field. (constructor)[get_timestamp]: New param. (updateToken): Use it. * test/server/token/TokenDaoTest.ts: Provide stub timestamp function. --- src/server/daemon/controller.js | 11 ++++++++++- src/server/token/TokenDao.ts | 25 ++++++++++++++++++------- test/server/token/TokenDaoTest.ts | 25 +++++++++++++------------ 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/server/daemon/controller.js b/src/server/daemon/controller.js index 4b7f38e..36dca21 100644 --- a/src/server/daemon/controller.js +++ b/src/server/daemon/controller.js @@ -246,7 +246,7 @@ function _initExportService( db, callback ) ExportService .use( TokenedService( 'c1import', - new TokenDao( collection, "exports" ), + new TokenDao( collection, "exports", getUnixTimestamp ), function tokgen() { var shasum = crypto.createHash( 'sha1' ); @@ -268,6 +268,15 @@ function _initExportService( db, callback ) } +/** + * Retrieve current date as a Unix timestamp + */ +function getUnixTimestamp() +{ + return Math.floor( ( new Date() ).getTime() / 1000 ); +} + + /** * Create server cache * diff --git a/src/server/token/TokenDao.ts b/src/server/token/TokenDao.ts index 9930531..c357e63 100644 --- a/src/server/token/TokenDao.ts +++ b/src/server/token/TokenDao.ts @@ -56,16 +56,30 @@ export default class TokenDao */ private readonly _rootField: string; + /** + * Retrieve a Unix timestamp + * + * This is used for timestampping token updates. + */ + private readonly _getTimestamp: () => number; + /** * Initialize connection * * @param collection Mongo collection + * @param root_field topmost field in mongo document + * @param date_ctor Date constructor */ - constructor( collection: MongoCollection, root_field: string ) + constructor( + collection: MongoCollection, + root_field: string, + getTimestamp: () => number, + ) { - this._collection = collection; - this._rootField = root_field; + this._collection = collection; + this._rootField = root_field; + this._getTimestamp = getTimestamp; } @@ -91,12 +105,9 @@ export default class TokenDao { const root = this._genRoot( ns ) + '.'; - // XXX: nondeterminism - const current_ts = Math.floor( ( new Date() ).getTime() / 1000 ); - const token_entry: TokenStatus = { type: type, - timestamp: current_ts, + timestamp: this._getTimestamp(), data: data, }; diff --git a/test/server/token/TokenDaoTest.ts b/test/server/token/TokenDaoTest.ts index 707493f..b0b9f31 100644 --- a/test/server/token/TokenDaoTest.ts +++ b/test/server/token/TokenDaoTest.ts @@ -39,12 +39,13 @@ describe( 'server.token.TokenDao', () => { it( 'updates token with given data', () => { - const field = 'foo_field'; - const qid = 12345; - const ns = 'namespace'; - const tok_id = 'tok123'; - const tok_type = 'DONE'; - const data = "some data"; + const field = 'foo_field'; + const qid = 12345; + const ns = 'namespace'; + const tok_id = 'tok123'; + const tok_type = 'DONE'; + const data = "some data"; + const timestamp = 12345; const root = field + '.' + ns; @@ -54,10 +55,9 @@ describe( 'server.token.TokenDao', () => expect( given_data.$set[ `${root}.lastStatus` ].timestamp ) .to.be.greaterThan( 0 ); - // TODO: ts is nondeterministic; pass in const expected_entry: TokenStatus = { type: tok_type, - timestamp: given_data.$set[ `${root}.lastStatus` ].timestamp, + timestamp: timestamp, data: data, }; @@ -83,7 +83,7 @@ describe( 'server.token.TokenDao', () => findOne() {}, }; - return new Sut( coll, field ) + return new Sut( coll, field, () => timestamp ) .updateToken( qid, ns, tok_id, tok_type, data ); } ); @@ -102,7 +102,8 @@ describe( 'server.token.TokenDao', () => }; return expect( - new Sut( coll, 'foo' ).updateToken( 0, 'ns', 'id', 'DONE', null ) + new Sut( coll, 'foo', () => 0 ) + .updateToken( 0, 'ns', 'id', 'DONE', null ) ).to.eventually.be.rejectedWith( expected_error ); } ); } ); @@ -206,7 +207,7 @@ describe( 'server.token.TokenDao', () => }; return expect( - new Sut( coll, field ).getToken( qid, ns, tok_id ) + new Sut( coll, field, () => 0 ).getToken( qid, ns, tok_id ) ).to.eventually.deep.equal( expected ); } ) ); @@ -226,7 +227,7 @@ describe( 'server.token.TokenDao', () => }; return expect( - new Sut( coll, 'foo' ).getToken( 0, 'ns', 'id' ) + new Sut( coll, 'foo', () => 0 ).getToken( 0, 'ns', 'id' ) ).to.eventually.be.rejectedWith( expected_error ); } ); } );