262 lines
7.6 KiB
JavaScript
262 lines
7.6 KiB
JavaScript
/**
|
|
* Export client
|
|
*
|
|
* Copyright (C) 2017 R-T Specialty, LLC.
|
|
*
|
|
* This file is part of the Liza Data Collection Framework.
|
|
*
|
|
* liza is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
var Class = require( 'easejs' ).Class,
|
|
HttpDataApi = require( '../../dapi/http/HttpDataApi' ),
|
|
XhrHttpImpl = require( '../../dapi/http/XhrHttpImpl' ),
|
|
AutoRetry = require( '../../dapi/AutoRetry' ),
|
|
JsonResponse = require( '../../dapi/format/JsonResponse' );
|
|
|
|
|
|
/**
|
|
* Facade handling export request
|
|
*
|
|
* TODO: If this is to be a facade, then this needs to have most of its
|
|
* logic extracted into another class. Time constraints.
|
|
*/
|
|
module.exports = Class( 'ExportClient',
|
|
{
|
|
/**
|
|
* Export service path
|
|
* @var {string}
|
|
*/
|
|
'private _service': '',
|
|
|
|
|
|
/**
|
|
* Initialize with service path
|
|
*
|
|
* The service path SERVICE is relative to the base URI of the quote.
|
|
*
|
|
* @param {string} service path to service
|
|
*/
|
|
__construct: function( service )
|
|
{
|
|
this._service = ''+service;
|
|
},
|
|
|
|
|
|
/**
|
|
* Initiate and await result of export of quote data into external
|
|
* system
|
|
*
|
|
* The export will first attempt to initiate the remote process; if this
|
|
* fails due to an active process for the same quote, it will continue
|
|
* to retry. Once initiated, the server is polled for the result data
|
|
* and accepted once available, completing the request.
|
|
*
|
|
* If there is any error during initiation or polling, the process is
|
|
* aborted and an error passed to CALLBACK.
|
|
*
|
|
* @param {Quote} quote quote to export
|
|
* @param {Object.<string,string>} params additional parameters to pass
|
|
* to remote import script
|
|
*
|
|
* @param {function(?Error,Object)} callback result of export
|
|
*
|
|
* @return {ExportClient} self
|
|
*/
|
|
'public export': function( quote, params, callback )
|
|
{
|
|
var _self = this;
|
|
|
|
this._startExport( quote, params, function( e, response )
|
|
{
|
|
// bail out on export request failure
|
|
if ( e !== null )
|
|
{
|
|
callback( e, response );
|
|
}
|
|
|
|
var token_id = response.data.tokenId;
|
|
if ( !token_id )
|
|
{
|
|
callback(
|
|
Error( "No token id provided for export request" ),
|
|
response
|
|
);
|
|
}
|
|
|
|
// monitor the token and accept the data once available
|
|
_self._startAccept( quote, token_id, function( e, response )
|
|
{
|
|
if ( e !== null )
|
|
{
|
|
callback( e, response );
|
|
}
|
|
|
|
// parse the return data; we're done
|
|
try
|
|
{
|
|
callback( null, JSON.parse( response.data.tokenData ) );
|
|
}
|
|
catch ( parse_err )
|
|
{
|
|
callback( parse_err, response.data );
|
|
}
|
|
} );
|
|
} );
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
/**
|
|
* Create an API suitable for the export request
|
|
*
|
|
* TODO: This is the facade part; all other logic should be stripped
|
|
* from this class.
|
|
*
|
|
* @param {string} uri base URI for export request
|
|
* @param {function(?Error,Object)} pred retry predicate
|
|
*
|
|
* @return {undefined}
|
|
*/
|
|
'private _createExportApi': function( uri, pred )
|
|
{
|
|
// we will give it a good two minutes (test site can be slow)
|
|
var delay_s = 2,
|
|
tries = ( 120 / delay );
|
|
|
|
var delay = function( remain, callback )
|
|
{
|
|
setTimeout( callback, 2e3 );
|
|
};
|
|
|
|
return HttpDataApi
|
|
.use( JsonResponse )
|
|
.use( AutoRetry( pred, tries, delay ) )
|
|
(
|
|
uri,
|
|
'GET',
|
|
XhrHttpImpl( XMLHttpRequest )
|
|
);
|
|
},
|
|
|
|
|
|
/**
|
|
* Initiate export
|
|
*
|
|
* @param {Quote} quote quote to export
|
|
* @param {Object.<string,string>} params additional parameters to pass
|
|
* to remote import script
|
|
*
|
|
* @param {function(?Error,Object)} callback result of export
|
|
*
|
|
* @return {undefined}
|
|
*/
|
|
'private _startExport': function( quote, params, callback )
|
|
{
|
|
this._startRequest( quote, params, null, 'ACTIVE', callback );
|
|
},
|
|
|
|
|
|
/**
|
|
* Await export completion and accept response
|
|
*
|
|
* @param {Quote} quote quote to export
|
|
* @param {string} token token to monitor
|
|
*
|
|
* @param {function(?Error,Object)} callback result of export
|
|
*
|
|
* @return {undefined}
|
|
*/
|
|
'private _startAccept': function( quote, token, callback )
|
|
{
|
|
var action = 'accept/' + token;
|
|
|
|
this._startRequest( quote, null, action, 'DONE', callback );
|
|
},
|
|
|
|
|
|
/**
|
|
* Initiate auto-retrying request
|
|
*
|
|
* @param {Quote} quote quote to export
|
|
* @param {?Object.<string,string>} params additional parameters to pass
|
|
* to remote import script
|
|
* @param {?string} action service action
|
|
* @param {string} status token status to await
|
|
*
|
|
* @param {function(?Error,Object)} callback result of export
|
|
*
|
|
* @return {undefined}
|
|
*/
|
|
'private _startRequest': function( quote, params, action, status, callback )
|
|
{
|
|
var _self = this;
|
|
|
|
var c1_export = this._createExportApi(
|
|
this._genRequestUri( quote, action ),
|
|
|
|
function( e, output )
|
|
{
|
|
// if this is a legitimate failure, then we should _not_
|
|
// retry: something went wrong, and we do not want to
|
|
// continue to cause problems
|
|
if ( e !== null )
|
|
{
|
|
return _self._shouldTryAgain( e.status, output.error );
|
|
}
|
|
|
|
// continue requesting until we produce an active import
|
|
return ( output.data.status !== status );
|
|
}
|
|
);
|
|
|
|
c1_export.request( params, callback );
|
|
},
|
|
|
|
|
|
/**
|
|
* Generate URI for export request
|
|
*
|
|
* @param {Quote} quote quote to export
|
|
* @param {string=} action service action
|
|
*
|
|
* @return {string} export request URI
|
|
*/
|
|
'private _genRequestUri': function( quote, action )
|
|
{
|
|
// XXX: we should not make these assumptions; abstract!
|
|
return '/quote/' +
|
|
quote.getProgramId() +
|
|
'/' + quote.getId() +
|
|
'/' + this._service +
|
|
( ( action ) ? '/' + action : '' );
|
|
},
|
|
|
|
|
|
/**
|
|
* Determine whether the response indicates that the request should be
|
|
* re-tried
|
|
*
|
|
* @param {number} status HTTP status code
|
|
* @param {string} error error response from server
|
|
*/
|
|
'private _shouldTryAgain': function( status, error )
|
|
{
|
|
return ( status === 503 )
|
|
&& error === 'EAGAIN';
|
|
}
|
|
} );
|
|
|