From 0e1cbe7c34c448c9e06214c96783ca8fe5b55ced Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Tue, 15 Aug 2017 15:03:52 -0400 Subject: [PATCH] Clear metadata for pending dapi calls * src/server/Server.js (_monitorMetadataPromise): Save metadata immediately after pending dapi requests (to clear in db). (handlePost): Pass clear update to _monitorMetadataPromise. * src/server/request/DataProcessor.js (processDiff): Return meta clear update. (_triggerDapis): Call _genClearMetaValues and return results to caller. (_genClearMetaValues): Add method to calculate bucket update. * test/server/request/DataProcessorTest.js: Update accordingly. --- src/server/Server.js | 15 ++++++--- src/server/request/DataProcessor.js | 39 +++++++++++++++++++++--- test/server/request/DataProcessorTest.js | 11 ++++++- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/server/Server.js b/src/server/Server.js index 7a75507..5b70bde 100644 --- a/src/server/Server.js +++ b/src/server/Server.js @@ -1136,11 +1136,12 @@ module.exports = Class( 'Server' ) var parsed_data = JSON.parse( post_data.data ); var bucket = quote.getBucket(); - const { filtered, dapis } = server._dataProcessor.processDiff( - parsed_data, request, program, bucket - ); + const { filtered, dapis, meta_clear } = + server._dataProcessor.processDiff( + parsed_data, request, program, bucket + ); - server._monitorMetadataPromise( quote, dapis ); + server._monitorMetadataPromise( quote, dapis, meta_clear ); } catch ( err ) { @@ -1168,8 +1169,12 @@ module.exports = Class( 'Server' ) }, - 'private _monitorMetadataPromise'( quote, dapis ) + 'private _monitorMetadataPromise'( quote, dapis, meta_clear ) { + // save metadata clear to database to prevent stale data from being + // used while requests are pending + this.dao.saveQuoteMeta( quote, meta_clear, null, e => { throw e; } ); + dapis.map( promise => promise .then( ( { field, index, data } ) => this.dao.saveQuoteMeta( diff --git a/src/server/request/DataProcessor.js b/src/server/request/DataProcessor.js index 896251b..4c44857 100644 --- a/src/server/request/DataProcessor.js +++ b/src/server/request/DataProcessor.js @@ -100,15 +100,16 @@ module.exports = Class( 'DataProcessor', program.initQuote( staging, true ); // array of promises for any dapi requests - const dapis = this._triggerDapis( + const [ dapis, meta_clear ] = this._triggerDapis( dapi_manager, program, staging.getDiff(), staging ); staging.commit(); return { - filtered: filtered, - dapis: dapis, + filtered: filtered, + dapis: dapis, + meta_clear: meta_clear, }; }, @@ -183,8 +184,9 @@ module.exports = Class( 'DataProcessor', } = program; const dapi_fields = this._determineDapiFields( mapis, data ); + const clear = this._genClearMetaValues( dapi_fields ); - return Object.keys( dapi_fields ).map( field => + const dapis = Object.keys( dapi_fields ).map( field => { const { dapi } = fields[ field ]; const indexes = dapi_fields[ field ]; @@ -199,9 +201,38 @@ module.exports = Class( 'DataProcessor', ) ); } ).reduce( ( result, x ) => result.concat( x ), [] ); + + return [ dapis, clear ]; }, + /** + * Generate update to clear metadata fields with pending dapi calls + * + * This ensures that stale data won't be accessible to systems while a + * request hasn't yet completed. For example, if performing a rate + * lookup, it wouldn't be desirable to use an old rate even though data + * used to retrieve it has since changed. + * + * @param {Object.} fields field names and array of indexes + * + * @return {undefined} + */ + 'private _genClearMetaValues'( fields ) + { + return Object.keys( fields ).reduce( ( result, field ) => + { + result[ field ] = fields[ field ].reduce( ( values, i ) => + { + values[ i ] = ""; + return values; + }, [] ); + + return result; + }, {} ); +}, + + /** * Determine which fields require a Data API to be triggered * diff --git a/test/server/request/DataProcessorTest.js b/test/server/request/DataProcessorTest.js index 7f5a101..8e27e06 100644 --- a/test/server/request/DataProcessorTest.js +++ b/test/server/request/DataProcessorTest.js @@ -181,7 +181,9 @@ describe( 'DataProcessor', () => src1: [ 'bsrc10', 'bsrc11' ], } ); - const { dapis } = sut.processDiff( data, request, program, bucket ); + const { dapis, meta_clear } = sut.processDiff( + data, request, program, bucket + ); const expected = { dapi_foo: [ @@ -211,6 +213,11 @@ describe( 'DataProcessor', () => ], }; + const expected_clear = { + foo: [ "", "" ], + bar: [ "", "" ], + }; + for ( let dapi_name in expected ) { let expected_call = expected[ dapi_name ]; @@ -239,6 +246,8 @@ describe( 'DataProcessor', () => expect( triggered.dapi_no_call ).to.equal( undefined ); + expect( meta_clear ).to.deep.equal( expected_clear ); + return Promise.all( dapis ); } ); } );