You are viewing an old version of this page. View the current version.
Compare with Current
View Page History
« Previous
Version 16
Next »
Scope
- How to sort a number of orders that have been added to a job chain and to force serialized processing in a predefined order?
- The solution outline includes a job that is added to the top of the job chain and that would
- suspend all incoming orders until a predefined idle timeout is reached and no more orders are expected
- sort the orders in alphabetical sequence of the order id and reinsert them to the next job node in the job chain.
- Reference: https://sourceforge.net/p/jobscheduler/discussion/486122/thread/a66295bb/
Solution
- Download sort_orders.zip
- Extract the archive to any folder within the
./config/live
folder of your JobScheduler installation. - The archive will extract the files included to a folder
sort_orders.
- You can store the sample files to a different folder, the solution does not make use of specific folder names.
Pattern
Implementation
Components
- The solution implements a job
sorter
that can be added to the top of any job chain.- This job implements a
spooler_process()
function that suspends all incoming orders. - This job is configured for one task and with an idle timeout attribute, i.e. it executes incoming orders sequentually.
- After the last order this job waits for the duration specified with the
idle_timeout
attribute for new orders. - The idle timeout is configured by
<job idle_timeout="10">
with the sorter
job definition. - With the idle timeout being expired this job will execute its
spooler_exit()
function and will sort all orders that have previously been suspended.- Sorting is done in alphabetical order.
- The orders are reinserted to the next job node that follows the
sorter
job in the job chain.
- The sample included makes use of a job chain
job_chain1
that includes the job nodes for the sorter
job and a hello
job.
var jobChainPath = null;
var jobChainNodeState = null;
var jobChainNodeNextState = null;
function spooler_init() {
spooler_log.info( ".. performing spooler_init()" );
jobChainPath = spooler_task.order.job_chain.path;
jobChainNodeState = spooler_task.order.job_chain_node.state;
jobChainNodeNextState = spooler_task.order.job_chain_node.next_state;
return true;
}
function spooler_process() {
var rc = true;
// suspend all orders, sorting is done on spooler_exit()
spooler_log.info( ".. suspending current order" );
spooler_task.order.suspended = true;
spooler_task.order.state = jobChainNodeState;
return rc;
}
function spooler_exit() {
spooler_log.info( ".. peforming spooler_exit()" );
var rc = true;
var orderList = Array();
// select all orders of the current job node
var response = spooler.execute_xml( "<show_job_chain job_chain='" + jobChainPath + "' what='job_chain_orders'/>" );
var orderDOM = new Packages.sos.xml.SOSXMLXPath( new java.lang.StringBuffer( response ) );
var orderNodes = orderDOM.selectNodeList( "/spooler/answer/job_chain/job_chain_node[@state = '" + jobChainNodeState + "']/order_queue/order" );
// traverse orders and check if orders are completed
for( orderIndex=0; orderIndex<orderNodes.getLength(); orderIndex++ ) {
var orderNode = orderNodes.item(orderIndex);
var orderID = orderDOM.selectSingleNodeValue( orderNode, "@id" );
if (orderID == null) {
continue;
}
spooler_log.info( ".... order found: " + orderID );
orderList.push( orderID );
}
// alphabetical string sort
orderList.sort(function(a, b){return (a > b) - (a < b) });
// numeric sort
// orderList.sort(function(a, b){return b - a) });
for(i=0; i<orderList.length; i++) {
spooler_log.info( ".... moving order: " + orderList[i] );
var response = spooler.execute_xml( "<modify_order job_chain='" + jobChainPath + "' order='" + orderList[i] + "' state='" + jobChainNodeNextState + "' suspended='no'/>" );
var orderDOM = new Packages.sos.xml.SOSXMLXPath( new java.lang.StringBuffer( response ) );
var errorCode = orderDOM.selectSingleNodeValue( "//ERROR/@code" );
var errorText = orderDOM.selectSingleNodeValue( "//ERROR/@text" );
if ( errorCode || errorText ) {
spooler_log.error( "........ modify order state response: errorCode=" + errorCode + ", errorText=" + errorText );
rc = false;
}
}
return rc;
}
Usage
- Add two orders to the
job_chain1
job chain. - Use an order id in descending alphabetical order, e.g. "cba" for the order id of the first order and "abc" for the order id of the second order.
- Both orders will be suspended in the first node of the job chain.
- After 10s both orders are reinserted to the next job node in the job chain.
- This time the orders are processed in ascending alphabetical order.