You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 17 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 move 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. The job chain accepts Ad Hoc orders that are added by use of JOC and the job chain can be modified to watch incoming files and to create orders.

 

Job sorter
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.

 

  • No labels