Performing Optimization in PeopleCode

This section discusses how to perform optimization in PeopleCode using analytic instances.

Important! The optimization PeopleCode classes are not supported on IBM z/OS and Linux for IBM System z platforms.

To create a new analytic instance for an analytic type:

  1. Call the function InsertOptProbInst with the analytic type and analytic instance as parameters to create an analytic instance ID.

  2. Use Application Engine or a similar mechanism to load the optimization application tables with data.

    Use the analytic instance ID as the key value in scenario-managed optimization application tables.

    The analytic instance is now ready to be loaded into an analytic server.

Note: You can load multiple copies of the same analytic instance into multiple instances of an analytic server, provided that each instance of the analytic server resides in a different application server domain. Each analytic instance loaded into a given domain must be unique. Within a given domain, you cannot have the same analytic instance in more than one analytic server. The analytic server maintains data integrity by checking to see if the data has been altered by another user (refer to the steps in the optimization system architecture description). Try to maintain data consistency when the same analytic instance uses the same database in different domains.

Use the CreateOptEngine function to load an analytic server with an analytic instance. It takes analytic instance ID and a mode parameter with %Synch and %Asynch as possible values and returns a PeopleCode object of type OptEngine.

You can run the PeopleCode on the application server or from Application Engine.

Loading Analytic Instances by Running PeopleCode on the Application Server

To block PeopleCode from running on the application server until the load is done (synchronous mode), use the %Synch value for the mode parameter. An error is generated if the load isn't successful. The application server imposes a timeout beyond which the PeopleCode and optimization engine load are terminated. Here is a code example:

Local OptEngine &myopt;
&myopt = CreateOptEngine("PATSMITH", %Synch);

To load the analytic server without blocking the PeopleCode from running (asynchronous mode) on the application server, use the %Asynch value for the mode parameter. The analytic server performs a preliminary check of the load request and returns the OptEngine object if it is successful or an error if it is unsuccessful. A successful return does not mean that the load was successful. You must then use repeated CheckOptEngineStatus methods on the returned OptEngine object to determine whether the analytic engine is done with the load and whether it was successful. Here is a code example:

Local OptEngine &myopt;
&myopt = CreateOptEngine("PATSMITH", %Asynch);

Loading Analytic Instances by Running PeopleCode in Application Engine

Both synchronous (%Synch) and asynchronous (%Asynch) modes block the PeopleCode from running on Application Engine until the load is done. Use only %Asynch while loading an optimization engine.

The absolute number of optimization engine instances that may be loaded in a given domain is governed by a configuration file loaded by Tuxedo during its domain startup.

You send an optimization transaction to the optimization engine using the RunSynch and RunAsynch methods. Both are methods on an OptEngine object. The OptEngine object can be created either by calling CreateOptEngine (if the optimization engine is not loaded already) or by calling GetOptEngine (if the optimization engine is already loaded). Both RunSynch and RunAsynch have the same signature, except that RunSynch runs the optimization transaction in synchronous mode and RunAsynch runs it in asynchronous mode. Both return an integer status code. You can run transactions either on the application server or with Application Engine.

To invoke an optimization transaction:

  1. Use the GetOptEngine function to get the OptEngine object as a handle for the optimization engine that has loaded an analytic instance ID.

    Use the CreateOptEngine function to create the OptEngine object for a new optimization engine if the analytic instance has not been loaded.

  2. Call RunSynch or RunAsynch to send an optimization transaction to the optimization engine to be run in synchronous or asynchronous mode.

  3. If the transaction is run in synchronous mode (RunSynch), use the OptEngine methods GetString, GetNumber, and so on, to retrieve the output result from the optimization transaction.

    The transaction names, parameter names, and data types are viewable in the analytic type in Application Designer.

  4. If the transaction is run in asynchronous mode, use the OptEngine method CheckOptEngineStatus to check the status of the optimization transaction in the optimization engine.

    After the transaction is done, result data is available in the database for retrieval using standard PeopleCode mechanisms.

Running Optimization Transactions from the Application Server

To block the PeopleCode from running on the application server until the optimization transaction is done (synchronous mode) and receives the results, use RunSynch to send an optimization transaction. An error status code is returned if the transaction isn't successful. If successful, you can use other methods to retrieve the results from the transaction call. The application server imposes a timeout beyond which the PeopleCode and optimization engine transaction are terminated.

To run a transaction without blocking PeopleCode from running (asynchronous mode) on the application server, use RunAsynch to send an optimization transaction. In this mode, the optimization engine performs a preliminary check of the transaction request and returns a success or failure status code. A successful return does not mean that the transaction is successful; it means only that the syntax is correct. You must then use repeated calls to the CheckOptEngineStatus method on the OptEngine object to determine whether the optimization engine is done with the transaction and whether it is successful.

RunAsynch does not allow transaction output results to be returned. Use this method for long-running transactions that return results entirely through the database.

Running Optimization Transactions from Application Engine

Both synchronous (RunSynch) and asynchronous (RunAsynch) methods block the PeopleCode from running on Application Engine until the optimization transaction is done. RunSynch allows output results to be returned, but it should be used for transactions that are fast (less than 10 seconds). RunAsynch does not have a time limit, but it does not return output results.

If you're developing an optimization application that uses the Optimization PeopleCode plug-in, you must do the following to invoke the plug-in:

  • Develop a PeopleCode application class that extends the PT_OPT_BASE:OptBase class.

  • Define methods in your application class that use the PeopleCode OptInterface class to perform your optimization functions.

  • Define an analytic type that specifies the Optimization PeopleCode plug-in, by selecting the PeopleCode Plugin check box in the analytic type properties.

  • In the analytic type properties, specify the application package and application class that you developed.

  • Define transactions in your analytic type definition that correspond to the methods you developed in your application class, with corresponding parameters.

Use the GetOptEngine function to get the OptEngine object as a handle for the optimization engine that loaded an analytic instance ID.

Use the OptEngine method named ShutDown to shut down the optimization engine. This ends the optimization engine process with the current analytic instance ID. Based on application server settings, the system restarts a new, unloaded optimization engine process that can be loaded with any other analytic instance.

To delete an existing analytic instance for an analytic type:

  1. Shut down any optimization engines that have this analytic instance currently loaded.

  2. Using Application Engine or a similar mechanism, delete the data in the optimization application tables pertaining to that analytic instance.

    Use the analytic instance ID as the key value to find and delete analytic instance rows from scenario-managed optimization application tables.

  3. Use the function DeleteOptProbInst with the analytic type and analytic instance as arguments to delete the analytic instance ID from PeopleTools metadata.

    Note: If you try to delete an existing analytic instance that is loaded in a running optimization engine, DeleteOptProbInst returns %OptEng_Fail, and the optional status reference parameter is set to %OptEng_Exists.

You must plan for uncommitted database changes in your optimization PeopleCode. The PeopleSoft Optimization Framework detects pending database updates, and generates a failure status if data is not committed to the database before certain optimization methods are called.

This checking for database updates happens in runtime for the CreateOptEngine function and the following methods: RunSync, RunAsync, Shutdown, GetTraceLevel, and SetTraceLevel. Ensure that your PeopleCode performs proper database updates and commits before you execute these methods. If you use the optional parameter for detailed status that is available for these functions, or the DetailedStatus property that is available for the methods, you can check for the status of %OptEng_DB_Updates_Pending to see if there is a pending database update.

Note: The pending database update may have happened considerably earlier in the code. Forcing a commit within your PeopleCode to avoid this problem prevents roll-back on database error. Forcing a commit should be used with care.

The InsertOptProbInst and DeleteOptProbInst functions can be called only inside FieldChange, PreSaveChange and PostSaveChange PeopleCode events, and in Workflow.

This database update checking happens in compile time for the following functions: InsertOptProbInst and DeleteOptProbInst. Make sure that there are no pending database updates before you execute these methods.