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 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(

View File

@ -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.<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
*

View File

@ -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 );
} );
} );