1
0
Fork 0

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.
master
Mike Gerwitz 2017-08-15 15:03:52 -04:00
parent b09d7ecd60
commit 0e1cbe7c34
3 changed files with 55 additions and 10 deletions

View File

@ -1136,11 +1136,12 @@ module.exports = Class( 'Server' )
var parsed_data = JSON.parse( post_data.data ); var parsed_data = JSON.parse( post_data.data );
var bucket = quote.getBucket(); var bucket = quote.getBucket();
const { filtered, dapis } = server._dataProcessor.processDiff( const { filtered, dapis, meta_clear } =
parsed_data, request, program, bucket server._dataProcessor.processDiff(
); parsed_data, request, program, bucket
);
server._monitorMetadataPromise( quote, dapis ); server._monitorMetadataPromise( quote, dapis, meta_clear );
} }
catch ( err ) 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 dapis.map( promise => promise
.then( ( { field, index, data } ) => .then( ( { field, index, data } ) =>
this.dao.saveQuoteMeta( this.dao.saveQuoteMeta(

View File

@ -100,15 +100,16 @@ module.exports = Class( 'DataProcessor',
program.initQuote( staging, true ); program.initQuote( staging, true );
// array of promises for any dapi requests // array of promises for any dapi requests
const dapis = this._triggerDapis( const [ dapis, meta_clear ] = this._triggerDapis(
dapi_manager, program, staging.getDiff(), staging dapi_manager, program, staging.getDiff(), staging
); );
staging.commit(); staging.commit();
return { return {
filtered: filtered, filtered: filtered,
dapis: dapis, dapis: dapis,
meta_clear: meta_clear,
}; };
}, },
@ -183,8 +184,9 @@ module.exports = Class( 'DataProcessor',
} = program; } = program;
const dapi_fields = this._determineDapiFields( mapis, data ); 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 { dapi } = fields[ field ];
const indexes = dapi_fields[ field ]; const indexes = dapi_fields[ field ];
@ -199,9 +201,38 @@ module.exports = Class( 'DataProcessor',
) )
); );
} ).reduce( ( result, x ) => result.concat( x ), [] ); } ).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.<string,Array>} 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 * Determine which fields require a Data API to be triggered
* *

View File

@ -181,7 +181,9 @@ describe( 'DataProcessor', () =>
src1: [ 'bsrc10', 'bsrc11' ], src1: [ 'bsrc10', 'bsrc11' ],
} ); } );
const { dapis } = sut.processDiff( data, request, program, bucket ); const { dapis, meta_clear } = sut.processDiff(
data, request, program, bucket
);
const expected = { const expected = {
dapi_foo: [ dapi_foo: [
@ -211,6 +213,11 @@ describe( 'DataProcessor', () =>
], ],
}; };
const expected_clear = {
foo: [ "", "" ],
bar: [ "", "" ],
};
for ( let dapi_name in expected ) for ( let dapi_name in expected )
{ {
let expected_call = expected[ dapi_name ]; let expected_call = expected[ dapi_name ];
@ -239,6 +246,8 @@ describe( 'DataProcessor', () =>
expect( triggered.dapi_no_call ).to.equal( undefined ); expect( triggered.dapi_no_call ).to.equal( undefined );
expect( meta_clear ).to.deep.equal( expected_clear );
return Promise.all( dapis ); return Promise.all( dapis );
} ); } );
} ); } );