blob: ffc4a0b3150b57e34898a8ace8d149a2bace7eac [file] [log] [blame]
var smartService = require('../../../services/smart/service');
var log = require('../../../lib/log')(
'components:browse:item-details:method-end');
var formatDetail = require('./format-detail');
module.exports = methodEnd;
/*
* Use the data from a successful/failed RPC to record the results properly.
* Note that the recorded results are rendered according to formatDetail.
* Successful RPCs also update the smartService.
* data needs to have runID and either (error) or (result and args)
*/
function methodEnd(state, method, data) {
// Simply draw the error message if there was an error.
if (data.error !== undefined) {
formatResult(state, method, data.runID, data.error, false);
return;
}
var sig = state.item().serverInfo.signature;
// Otherwise, we'll have to learn from the results and draw them, if possible.
var numInArgs = sig[method].inArgs.length;
// Since the RPC was successful, we can assume the inputs were good.
if (numInArgs > 0) {
learnMethodInput(state, method, data.args);
learnMethodInvocation(state, method, data.args);
}
// Do not process results we expect to be empty.
// TODO(alexfandrianto): Streaming results are ignored with this logic.
var expectedOutArgs = sig[method].numOutArgs;
if (expectedOutArgs === 1) { // Error is the only possible out argument.
replaceResult(state, data.runID, '<ok>');
return;
}
// Draw the results.
formatResult(state, method, data.runID, data.result, numInArgs === 0);
}
/*
* The result will be rendered, overwriting the placeholder identified by runID.
*/
function formatResult(state, method, runID, result, addToDetails) {
// Use formatDetail to process the raw result into a renderable format.
var formattedResult = formatDetail(result);
// Then overwrite the old value.
replaceResult(state, runID, formattedResult);
}
/*
* Find the correct output replacement mercury struct and replace its result.
* If the replacement cannot be found, then no substitution occurs.
*/
function replaceResult(state, runID, newResult) {
var match = state.methodOutputs.get(state.item().objectName).filter(
function matchesRunID(output) {
return output.get('runID').equals(runID);
}
).get(0);
if (match !== undefined) {
match.put('result', newResult);
}
}
/*
* Learn from the method inputs to be able to suggest them in the future.
*/
function learnMethodInput(state, method, args) {
var sig = state.item().serverInfo.signature;
args.forEach(function(value, i) {
var argName = sig[method].inArgs[i];
var input = {
argName: argName,
methodName: method,
signature: sig,
value: args[i]
};
log.debug('Update Input:', input);
smartService.update('learner-method-input', input).catch(function(err) {
log.error('Error while updating method input learner', err);
});
});
}
/*
* Learn from this invocation to be able to suggest them in the future.
*/
function learnMethodInvocation(state, method, args) {
var sig = state.item().serverInfo.signature;
var input = {
methodName: method,
signature: sig,
value: JSON.stringify(args)
};
log.debug('Update Invocation:', input);
smartService.update('learner-method-invocation', input).catch(function(err) {
log.error('Error while updating method invocation learner', err);
});
}