![]() | |||||||||||||
| |||||||||||||
Solving a Mosel model using a REST webservice, from NodeJS Description In this example, the Xpress Executor should first be configured with the blend3c.mos model. Then, you
run the blendxe.js program locally; this uses REST webservice requests to send the blend.csv file to the Xpress
Executor and remotely solve the model using this, then downloads and displays the results. This example
requires a local installation of Xpress for compiling the initial model, but not for starting the execution.
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
Data Files blendxe.js /******************************************************* Xpress Executor Example Model ============================= file blendxe.js ``````````````` Demonstrates executing the 'blend3c' model using Xpress Executor with the supplied input data & displaying the results. This example is written in JavaScript and intended to be run using node.js. Local prerequisites: node.js npm Instructions 1) Configure your Xpress Executor component with the blend3c example model 2) Fill in the DMP_* variables with the details of your Xpress Executor component 3) Open a command prompt and type: npm install 4) When that completes, type: node blendxe.js (c) 2017 Fair Isaac Corporation author: J. Farmer, Jul. 2017 *******************************************************/ // The REST endpoint of the Xpress Executor DMP component // ! Obtain this by clicking "View Links" for the Xpress Executor component on the DMP UI var DMP_XE_REST_ENDPOINT=""; // The client ID of solution containing the Xpress Executor DMP component // Obtain this through the DMP UI var DMP_SOLUTION_CLIENT_ID=""; // The secret of the solution containing the Xpress Executor DMP component // Obtain this through the DMP UI var DMP_SOLUTION_SECRET=""; // The endpoint from which to request the authorization token. // See DMP help page "Requesting a Bearerer Token" for details on how to obtain this var DMP_BEARER_TOKEN_URL="https://iam-svc.dms.usw2.ficoanalyticcloud.com/registration/rest/client/token" // The input file for the remote model var INPUTFILE="../data/blend.csv"; // Third-party dependency: prequest // for promise-based HTTP requests var prequest = require('prequest'); // Third-party dependency: delay // for promise-based delays var delay = require('delay'); // Third-party dependency: csv-parse // for parsing CSV data // The example model blend3c.mos reads & outputs CSV; this is a feature of this example rather than a requirement // of Xpress Executor. var parse = require('csv-parse/lib/sync'); // Standard node.js filesystem module var fs = require('fs'); // Standard node.js URL handling module var url = require('url'); // Request an authentication token from DMP console.log("Requesting authorization token from DMP"); var authorizationToken; prequest({ method: 'POST', url: DMP_BEARER_TOKEN_URL, body: { clientId: DMP_SOLUTION_CLIENT_ID, secret: DMP_SOLUTION_SECRET } }).then(function(body) { // This token can be re-used in subsequent requests, but should be refreshed every half hour authorizationToken = body; // Start the execution of the model in our Xpress Executor service console.log("Initiating model execution"); return prequest({ method: 'POST', url: DMP_XE_REST_ENDPOINT, headers: { "Authorization": 'Bearer '+authorizationToken }, body: { // parameters defined in 'parameters' section at the top of blend3c.mos parameters: { INPUTFILE: "input", RESULTFILE: "result" }, // Use inputText for passing input data as a string, inputBase64 for encoded binary input data inputText: fs.readFileSync(INPUTFILE,"utf8") } }); }).then(function(executionStatus) { // executionStatus is a standard structure that contains various meta-data about an execution in // the Xpress Executor service. It also contains relative paths to various REST resources // relating to this execution - e.g. input, result, status, run log... // Model will be executing asynchronously; repeatedly wait 1/4 second then re-fetch status until it // is complete console.log("Waiting for completion of execution"); function waitForCompletion() { if (executionStatus.status!=='NOT_COMPLETED' && executionStatus.status!=='NOT_LOADED') { // Execution has finishd! return Promise.resolve(executionStatus); } else { // Wait 250ms return delay(250).then(function() { // Refresh executionInfo return prequest({ method: 'GET', url: url.resolve(DMP_XE_REST_ENDPOINT, executionStatus.statusPath), headers: { "Authorization": 'Bearer '+authorizationToken } }).then(function(body) { // Request returns updated executionStatus executionStatus = body; return waitForCompletion(); }); }); } } return waitForCompletion(); }).then(function(executionStatus) { // Execution has completed; check that it was successful and display results as appropriate console.log("Processing model results"); // In event of failure, echo the remote model status, exit code & run log to aid with troubleshooting if (executionStatus.status!=='OK' || executionStatus.exitCode!==0) { // Execution failed for some reason console.log("Execution failed!"); console.log("Execution status: "+executionStatus.status); console.log("Execution exit code: "+executionStatus.exitCode); console.log(""); console.log("Execution log:"); // Fetch the remote execution log as it will likely contain error messages from the model return prequest({ method: 'GET', url: url.resolve(DMP_XE_REST_ENDPOINT, executionStatus.runLogPath), headers: { "Authorization": 'Bearer '+authorizationToken, "Accept": 'text/plain' } }).then(function(runLog) { console.log(runLog); return executionStatus; }); } else { // Download results file return prequest({ method: 'GET', url: url.resolve(DMP_XE_REST_ENDPOINT, executionStatus.resultPath), headers: { "Authorization": 'Bearer '+authorizationToken, "Accept": 'application/octet-stream' } }).then(function(csvResults) { // The blend3c.mos example downloads its results as a CSV file. Use the NodeJS 'csv' module to parse this. console.log(); console.log("Results of optimization:"); records = parse(csvResults); records.forEach(function(record) { console.log(" use("+record[0]+"): "+record[1]); }); console.log(); return executionStatus; }); } }).then(function(executionStatus) { // Finally, delete execution from component, to free the resources it holds console.log("Deleting execution from component"); return prequest({ method: 'DELETE', url: url.resolve(DMP_XE_REST_ENDPOINT, executionStatus.statusPath), headers: { "Authorization": 'Bearer '+authorizationToken } }); }).catch(function(err) { if (err.statusCode) { console.error("ERROR returned by Xpress Executor service: HTTP status code "+err.statusCode); } else { console.error("ERROR encountered: "+err.message); } });
| |||||||||||||
© Copyright 2024 Fair Isaac Corporation. |