Using Lights-Out Mode with Optimization

This section provides an overview of lights-out mode, and discusses how to create and edit messages.

Some optimization applications can take several hours to run. These are typically run as overnight batch jobs every night when the work load is small to regenerate the optimization solution and have it ready for end users to use in the morning hence the term lights-out mode.

In the current release, application messages communicate between the Application Engine batch job and the online optimization engine. After the Application Engine job completes and the optimization solution has been written to the database, an application message initiates the download of the data from the database batch job to the online optimization engine.

Lights-out mode uses an Application Engine PeopleCode program within PeopleSoft Process Scheduler to send requests to an application server and receive responses from it. Within the application server, the OnRequest PeopleCode runs an optimization engine process.

Image: Lights-out process

This diagram illustrates the lights-out process:

Lights-out process

This request and response is in the form of a rowset as shown by the example supplied with optimization, the OPT_CALL message. Also supplied as an example is an Application Engine message publish PeopleCode program called PT_OPTCALL.

Important! Application Engine includes an action of type Log Message. which PeopleSoft Process Scheduler uses to record its activity in the PS_MESSAGE_LOG table. The PeopleCode MessageBox and WinMessage built-in functions also record their activity in the PS_MESSAGE_LOG table.

During lights-out optimization, these processes can conflict with each other or with the optimization engine when one process locks a row of the table, and another process tries to access the same row.

To prevent this conflict, pay close attention to where the MessageBox or WinMessage built-in functions are used in your Application Engine PeopleCode. In general, there can't be any outstanding database updates pending when communicating with the optimization engine using application messages.

The OPT_CALL Message

The OPT_CALL message is an example of what the lights-out process uses as the message for optimization. The OPT_CALL message has a structure using a record, PT_OPTPARMS, having the fields PARMKEY and VALUE which represent a name/value pair. These send requests and responses from the Application Engine PeopleCode in PeopleSoft Process Scheduler to and from the message OnRequest PeopleCode in the application server.

The OPT_CALL message also uses a record, PT_OPTDETMSGS, which contains the information needed for processing a detailed message.

This is an example of the Message Definition page (select PeopleTools > Integration Broker > Integration Setup > Messages) showing the OPT_CALL message definition:

Image: Message Definition page – OPT_CALL message definition

This example illustrates the fields and controls on the Message Definition page – OPT_CALL message definition. You can find definitions for the fields and controls later on this page.

Message Definition page - OPT_CALL message definition

The OPT_CALL message is associated with the OPT_CALL service operation. The OPT_CALL service operation defines the OPT_CALL application package as a handler. This application package implements the Integration Broker methods needed to handle any messaging PeopleCode.

This section provides an overview of the request message and describes how to create messages that:

  • Create an optimization engine.

  • Check optimization engine status.

  • Run an optimization engine transaction.

  • Set the trace level.

  • Get the trace level.

  • Shutdown an optimization engine.

Understanding the Request Message

For optimization, the Application Engine PeopleCode in PeopleSoft Process Scheduler sends a request OPT_CALL message. The message uses rowsets built from PT_OPTPARMS records as the request. You can use the following rowset structures as an example of how to perform certain optimization actions, by sending them as requests from the application engine program in the process scheduler to the message notification PeopleCode in the application server.

Creating an Optimization Engine

To create an optimization engine, structure the rowset as follows, using the PT_OPTPARMS record. You set key values using the PARMKEY field, and then set a value for that key field in the VALUE field.

PARMKEY Field

VALUE Field

OPTCMD

CREATE

Causes the PeopleCode program implementing the Integration Broker OnRequest method to load an optimization engine. The OPT_CALL example executes the CreateOptEngine function.

PROBINST

The name of the analytic instance.

PROCINSTANCE

The name of the process instance for this process scheduler job.

SYNCH

Y if this optimization engine load is to occur synchronously, N if asynchronously.

Checking Optimization Engine Status

To check optimization engine status (for example, to see when it finishes loading), structure the rowset as follows, using the PT_OPTPARMS record.

PARMKEY Field

VALUE Field

OPTCMD

CHECK_STATUS

Causes the PeopleCode program implementing the Integration Broker OnRequest method to check the status of an optimization engine. The OPT_CALL example executes the CheckOptEngineStatus function.

PROBINST

The name of the analytic instance.

PROCINSTANCE

The name of the process instance for this process scheduler job.

Running a Transaction

To run a transaction, structure the rowset as follows, using the PT_OPTPARMS record.

PARMKEY Field

VALUE Field

OPTCMD

RUN

Causes the PeopleCode program implementing the Integration Broker OnRequest method to run an optimization transaction. The OPT_CALL example executes the GetOptEngine method and either the RunSynch or RunAsynch method.

PROBINST

The name of the analytic instance.

PROCINSTANCE

The name of the process instance for this process scheduler job.

SYNCH

Y for a synchronous transaction, N for asynchronous.

TRANSACTION

The name of the transaction to run.

The names of one or more transaction parameters.

The value of each named transaction parameter.

Setting the Trace Level

To set a trace level, structure the rowset as follows, using the PT_OPTPARMS record.

PARMKEY Field

VALUE Field

OPTCMD

SET_TRACE_LEVEL

Causes the PeopleCode program implementing the OnRequest Integration Broker method to set the severity level at which events will be logged for an optimization engine. The OPT_CALL example executes the SetTraceLevel method.

PROBINST

The name of the analytic instance.

PROCINSTANCE

The name of the process instance for this process scheduler job.

COMPONENT

One of the following values:

  • %Opt_Engine server activity of the running optimization engine.

  • %Opt_Utility low level elements that support the running optimization engine.

  • %Opt_Datacache the in-memory database cache.

  • %Opt_Plugin the plugin being used for the running optimization engine.

SEVERITY_LEVEL

The severity level to log.

The following list starts with the most severe level; the level you specify includes all higher levels. For example, if you specify %Severity_Error, it logs %Severity_Fatal, %Severity_Status, and %Severity_Error messages and filters out the others.

  • %Severity_Fatal

  • %Severity_Status

  • %Severity_Error

  • %Severity_Warn

  • %Severity_Info

  • %Severity_Trace1

  • %Severity_Trace2

Getting the Trace Level

To get a trace level, structure the rowset as follows, using the PT_OPTPARMS record.

PARMKEY Field

VALUE Field

OPTCMD

GET_TRACE_LEVEL

Causes the PeopleCode program implementing the OnRequest Integration Broker method to get the severity level at which events will be logged for an optimization engine. The OPT_CALL example executes the GetTraceLevel method.

PROBINST

Set to the name of the analytic instance.

PROCINSTANCE

Set to the name of the process instance for this process scheduler job.

COMPONENT

One of the following values:

  • %Opt_Engine server activity of the running optimization engine.

  • %Opt_Utility low level elements that support the running optimization engine.

  • %Opt_Datacache the in-memory database cache.

  • %Opt_Plugin the plugin being used for the current opt engine.

Shutting Down an Optimization Engine

To shut down an optimization engine, structure the rowset as follows, using the PT_OPTPARMS record.

PARMKEY Field

VALUE Field

OPTCMD

SHUTDOWN

Causes the PeopleCode program implementing the OnRequest Integration Broker method to shut down an optimization engine. The OPT_CALL example executes the Shutdown method.

PROBINST

The name of the analytic instance.

PROCINSTANCE

The name of the process instance for this process scheduler job.

This section provides an overview of the response message and describes how to create messages that:

  • Send optimization status.

  • Send a detailed message.

Understanding the Response Message

For optimization, the message PeopleCode in application server receives the request messages, performs an optimization actions, and sends response OPT_CALL messages. One message uses rowsets built from PT_OPTPARMS records, the other uses rowsets from PT_DETMSGS records. You can use the rowset structures in the next section (Sending Optimization Status) as an example of how to send responses from the message notification PeopleCode in the application server to the application engine program in the process scheduler.

Sending Optimization Status

To send the status of the optimization functions and methods called within the PeopleCode program implementing the OnRequest Integration Broker method, structure the rowset as follows using the PT_OPTPARMS record. The optimization functions and messages are called in response to the request input message. You set key values using the PARMKEY field, and then set a value for that key field in the VALUE field.

PARMKEY Field

VALUE Field

STATUS

The return status of the optimization function or method that is called in the message PeopleCode.

DETAILED_STATUS

The optional detailed status returned by many of the optimization functions and methods.

Sending a Detailed Message

To send a detailed message, structure the rowset as follows, using the PT_DETMSGS record. You set key values using the PARMKEY field, and then set a value for that key field in the VALUE field.

PARMKEY Field

VALUE Field

MSGSET

The message set number. In the case of optimization, the message set number is 148.

MSGNUM

The name of the detailed message.

PARMCOUNT

The number of message parameters for the detailed message. There can be up to five parameters.

MSGPARM1

The first parameter value.

MSGPARM2

The second parameter value.

MSGPARM3

The third parameter value.

MSGPARM4

The fourth parameter value.

MSGPARM5

The fifth parameter value.

The PT_OPTCALL Application Engine program serves as a template. It is delivered with all the sections marked as inactive. You can edit the program to suit your needs, then mark the appropriate sections active before running it. You can also use the program as a guide to creating your own Application Engine program.

The program uses these steps to send request messages to perform the following tasks:

  1. Load the optimization engine.

  2. Wait for the optimization engine load to finish.

  3. Run an optimization transaction against the loaded optimization engine.

  4. Wait for the optimization transaction to finish running.

  5. Set the trace level.

  6. Get the trace level.

  7. Shut down the optimization engine.

You can edit steps 1 and 3 to run an optimization transaction. You can also use the entire program as a template to create your own Application Engine program.

Loading an Optimization Engine

In step 1, enter the name of your analytic instance. In this example, the name of the analytic instance is FEMALE1.

If you have multiple domains, enter the local node name and the machine name and port number for your application server. In this case, the local node name is %LocalNode and the machine name and port number are foo111111:9000.

Local Message &MSG;
Local Message &response;

Component string &probid;
Component string &isSync;
Component string &procinst;
Local integer &nInst;
Local string &url;

Local Rowset &rs;
Local Row &row;
Local Record &rec;

Local string &stName;
Local integer &stVal;

&MSG = CreateMessage(OPERATION.OPT_CALL);
&rs = &MSG.GetRowset();

&row = &rs.GetRow(1);
&rec = &row.GetRecord(Record.PT_OPTPARMS);
&rec.PARMKEY.Value = "OPTCMD";
&rec.VALUE.Value = "CREATE";

&rs.InsertRow(1);
&rec = &rs.GetRow(2).PT_OPTPARMS;
&rec.PARMKEY.Value = "PROBINST";
&rec.VALUE.Value = "FEMALE1";
&probid = "FEMALE1";

&rs.InsertRow(2);
&rec = &rs.GetRow(3).PT_OPTPARMS;
&rec.PARMKEY.Value = "PROCINSTANCE";
&nInst = Record.PT_OPT_AET.PROCESS_INSTANCE.Value;
&rec.VALUE.Value = String(&nInst);
&procinst = String(&nInst); 

&rs.InsertRow(3);
&rec = &rs.GetRow(4).PT_OPTPARMS;
&rec.PARMKEY.Value = "SYNCH";
&rec.VALUE.Value = "N";
&isSync = "N";


/* Specify the Application Server domain URL (foo111111:9000 in this example)
*/
&response = %IntBroker.SyncRequest(%LocalNode, "//foo111111:9000 e");

If &response.ResponseStatus = 0 Then
   &stName = &response.GetRowset().GetRow(1).GetRecord(Record.PT_OPTPARMS).Get
Field(Field.PARMKEY).Value;
   &stVal = Value(&response.GetRowset().GetRow(1).GetRecord(Record.PT_
OPTPARMS).GetField(Field.VALUE).Value);
   If &stName = "STATUS" And
         &stVal = %OptEng_Fail Then
      /* Check detailed message here */
      throw CreateException(148, 2, "Can not send to OptEngine");
   End-If;
End-If;

Running An Optimization Transaction

In step 3, enter the name of your optimization transaction and its parameter name/value pairs. In this example, the transaction name is TEST_LONG_TRANS, the first parameter name/value pair is Delay_in_Secs and 30, and the second parameter name/value pair is Sleep0_Work1 and 0.

The parameter values are stored as strings. You may need to convert them in the OnRequest PeopleCode.

Local Message &MSG;
Local Message &response;

Local Rowset &rs, &respRS;
Local Row &row;
Local Record &rec, &msgRec;

Component string &probid;
Component string &procinst;
Component string &isSync;
Local string &url = "";
Local integer &parmCount, &msgSet, &msgNum;

&MSG = CreateMessage(OPERATION.OPT_CALL);
&rs = &MSG.GetRowset();

&row = &rs.GetRow(1);
&rec = &row.GetRecord(Record.PT_OPTPARMS);
&rec.PARMKEY.Value = "OPTCMD";
&rec.VALUE.Value = "RUN";

&rs.InsertRow(1);
&rec = &rs.GetRow(2).PT_OPTPARMS;
&rec.PARMKEY.Value = "PROBINST";
&rec.VALUE.Value = &probid;

&rs.InsertRow(2);
&rec = &rs.GetRow(3).PT_OPTPARMS;
&rec.PARMKEY.Value = "PROCINSTANCE";
&rec.VALUE.Value = &procinst;

&rs.InsertRow(3);
&rec = &rs.GetRow(4).PT_OPTPARMS;
&rec.PARMKEY.Value = "SYNCH";
&rec.VALUE.Value = &isSync;

&rs.InsertRow(4);
&rec = &rs.GetRow(5).PT_OPTPARMS;
&rec.PARMKEY.Value = "TRANSACTION";
&rec.VALUE.Value = "TEST_LONG_TRANS";

&rs.InsertRow(5);
&rec = &rs.GetRow(6).PT_OPTPARMS;
&rec.PARMKEY.Value = "Delay_in_Secs";
&rec.VALUE.Value = "30";

&rs.InsertRow(6);
&rec = &rs.GetRow(7).PT_OPTPARMS;
&rec.PARMKEY.Value = "Sleep0_Work1";
&rec.VALUE.Value = "0";

/* SyncRequest will carry a url */
SQLExec("select URL from PSOPTSTATUS where PROBINST=:1 AND URL NOT LIKE '%:0';",
 &probid, &url);
If &url = "" Then
   throw CreateException(148, 2, "Can not send to OptEngine");
End-If;

/* Specify the Application Server domain URL. 
   (This was specified in Step 1 in this example.)
*/
&response = %IntBroker.SyncRequest(%LocalNode, &url);

If &response.ResponseStatus = 0 Then
   &stName = &response.GetRowset().GetRow(1).GetRecord(Record.PT_OPTPARMS).Get
Field(Field.PARMKEY).Value;
   &stVal = Value(&response.GetRowset().GetRow(1).GetRecord(Record.PT_
OPTPARMS).GetField(Field.VALUE).Value);
   
   If &stName = "STATUS" And
         &stVal = %OptEng_Fail Then
      throw CreateException(148, 2, "Can not send to OptEngine");
   End-If;
   
   /* Check Detailed msg here */
   If &isSync = "Y" And
         &stVal = %OptEng_Success Then
      
      &respRS = &response.GetRowset();
      &rowNum = &respRS.ActiveRowCount;
      For &iloop = 1 To &rowNum
         &msgRec = &respRS.GetRow(&iloop).GetRecord(Record.PT_OPTDETMSGS);
         If (&msgRec.GetField(Field.MSGSET).Value <> 0) Then
            &msgSet = Value(&msgRec.GetField(Field.MSGSET).Value);
            &msgNum = Value(&msgRec.GetField(Field.MSGNUM).Value);
            &parm1 = &msgRec.GetField(Field.MSGPARM1).Value;
            &parm2 = &msgRec.GetField(Field.MSGPARM2).Value;
            &parm3 = &msgRec.GetField(Field.MSGPARM3).Value;
            &parm4 = &msgRec.GetField(Field.MSGPARM4).Value;
            &parm5 = &msgRec.GetField(Field.MSGPARM5).Value;
            &string = MsgGetText(&msgSet, &msgNum, "Message Not Found", &parm1,
 &parm2, &parm3, &parm4, &parm5);
            
         End-If;
      End-For;
      
   End-If;
   
End-If;

The OPT_CALL message definition serves as a template. It is delivered to work with the PT_OPTCALL Application Engine program. You can edit the program to suit your needs, or use it as a guide when creating your own response message program.

OPT_CALL Message Program

The OPT_CALL application package implements the Integration Broker method OnRequest. The PeopleCode in this method shows application messages for lights-out mode.

Depending upon the request message, the OnRequest method PeopleCode calls appropriate optimization functions and methods to perform these tasks, and sends a response message containing the returned status and detailed messages from the optimization functions and methods.

You can use the OnRequest method PeopleCode as a template to create your own response message PeopleCode program. For example, you can edit it to run an optimization transaction, which is shown below as an example. This example is edited to match the examples for step 1 and step 3 in the PT_OPTCALL program.

Processing the Transaction Parameters

Edit the OPT_CALL application program OnRequest method to enter the name of your optimization transaction and the name/value pairs for its parameters. In this example, the transaction name is TEST_LONG_TRANS, the first parameter name/value pair is &delayParm and &delay (maps to Delay_in_Secs from the request message), and the second parameter name/value pair is &sleepParm and &isSleep (maps to Sleep0_Work1 from the request message).

The parameter values are stored as strings in step 3 of the Application Engine program. You may need to convert them here to your desired format. Here is a section of the application program showing the places to edit.

If &trans = "TEST_LONG_TRANS" Then
   &REC = &rs.GetRow(6).PT_OPTPARMS;&delayParm = &REC.PARMKEY.Value;&delay = Value(&REC.VALUE.Value);
   
   &REC = &rs.GetRow(7).PT_OPTPARMS;&sleepParm = &REC.PARMKEY.Value;&isSleep = Value(&REC.VALUE.Value);
   
   &myopt = GetOptEngine(&inst, &detStatus);
   If (&myopt = Null) Then
      &optstatus = %OptEng_Fail;
   End-If;
   
   If &myopt <> Null And &isSync = "Y" Then
      &optstatus = &myopt.RunSynch(&trans, &delayParm, &delay, &sleepParm, &isSleep
);
      &detStatus = &myopt.DetailedStatus;
      End-If;
      
   If &myopt <> Null And &isSync = "N" Then
      &myopt.ProcessInstance = &procInst;
      &optstatus = &myopt.RunASynch(&trans, &delayParm, &delay, &sleepParm, &is
Sleep);
      &detStatus = &myopt.DetailedStatus;
   End-If; /* iif myopt=null */
End-If;

Building a Status Response Message

This section shows the a response message to send a status message for the OPT_CALL message in the application server.

/* Insert detailed status and detailed msgs into Response msg rowset */
&respRS = &response.GetRowset();
&respRS.GetRow(1).GetRecord(Record.PT_OPTPARMS).GetField(Field.PARMKEY).Value =
 "STATUS";
&respRS.GetRow(1).GetRecord(Record.PT_OPTPARMS).GetField(Field.VALUE).Value =
 String(&optstatus);

&respRS.InsertRow(1);
&respRS.GetRow(2).GetRecord(Record.PT_OPTPARMS).GetField(Field.PARMKEY).Value =
 "DETAILED_STATUS";
&respRS.GetRow(2).GetRecord(Record.PT_OPTPARMS).GetField(Field.VALUE).Value =
 String(&detStatus);

Building a Detailed Response Message

This section shows a response message to send a detailed message for the OPT_CALL message on the application server.

/*Either optcmd or inst is not passed in correctly, or optengine is not loaded
/created correctly */
If &myopt = Null Then
   &msgRec = &respRS.GetRow(1).GetRecord(Record.PT_OPTDETMSGS);
   If &isParmBad = True Then
      &msgRec.GetField(Field.MSGSET).Value = 148;
      &msgRec.GetField(Field.MSGNUM).Value = 505;
   End-If;
End-If;

/* If it is sync transaction, insert DetailMsg to response msg */
If &myopt <> Null And
      &isSync = "Y" And
      &optcmd = "RUN" And
      &optstatus = %OptEng_Success Then
   &arrArray = &myopt.DetailMsgs;
   For &iloop = 1 To &arrArray.Len
      /* First two rows have been inserted because of PT_OPTPARMS for two status
 codes */
      If &iloop > 2 Then
         &respRS.InsertRow(&iloop - 1);
      End-If;
      
      &msgRec = &respRS.GetRow(&iloop).GetRecord(Record.PT_OPTDETMSGS);
      &msgRec.GetField(Field.MSGSET).Value = String(&arrArray [&iloop][1]);
      &msgRec.GetField(Field.MSGNUM).Value = String(&arrArray [&iloop][2]);
      &msgRec.GetField(Field.PARMCOUNT).Value = String(&arrArray [&iloop][3]);
      &msgRec.GetField(Field.MSGPARM1).Value = String(&arrArray [&iloop][4]);
      &msgRec.GetField(Field.MSGPARM2).Value = String(&arrArray [&iloop][5]);
      &msgRec.GetField(Field.MSGPARM3).Value = String(&arrArray [&iloop][6]);
      &msgRec.GetField(Field.MSGPARM4).Value = String(&arrArray [&iloop][7]);
      &msgRec.GetField(Field.MSGPARM5).Value = String(&arrArray [&iloop][8]);
   End-For;
   
End-If;