Skip to main content
Version: Previous

Evaluator - examples

Cron rules (static events)

This example creates a cron rule that triggers a batch job to run once every minute.

The batch job generates a position report as a csv for each counterparty. This will be stored in runtime/position-minute-report. The file name of each report written will have the form COUNTERPARTY_ID-DATE.csv.

Our cron rule takes the following form:

CRON_EXPRESSIONDESCRIPTIONTIME_ZONERULE_STATUSNAMEUSER_NAMEPROCESS_NAMEMESSAGE_TYPERESULT_EXPRESSION
0 45 7 ? * MON,TUE,WED,THU,FRI *It’s a ruleEurope/LondonENABLEDA ruleJaneDeeALPHA_EVENTHANDLEREVENT_POSITION_REPORT

Let's look at the most important fields:

  • RULE_STATUS can be ENABLED or DISABLED.
  • CRON_EXPRESSION determines when the rule is evaluated.
  • PROCESS_NAME is the target process for the rule. When the rule is triggered, it will send a message to the process specified here.
  • MESSAGE_TYPE is the message that needs to be sent to the specified PROCESS_NAME.
  • RESULT_EXPRESSION is the value or values that will be sent as part of the transaction to the target PROCESS_NAME; we can leave RESULT_EXPRESSION empty, as we are going to generate a report for all positions anyway.

For the purposes of this exercise, we assume that the application is called MYAPP.

1. Configure the Evaluator

To start, create a process called MYAPP_EVALUATOR and add it to the file myapp-processes.xml inside your project folder myapp-config/src/main/resources/cfg as the code below.

<processes>
...
<process name="MYAPP_EVALUATOR">
<start>true</start>
<groupId>MYAPP</groupId>
<options>-Xmx512m -DXSD_VALIDATE=false</options>
<module>genesis-evaluator</module>
<primaryOnly>true</primaryOnly>
<package>global.genesis.eventhandler,global.genesis.evaluator</package>
<description>Dynamic/time rules engine</description>
<loggingLevel>DEBUG,DATADUMP_ON</loggingLevel>
</process>
</processes>

Add MYAPP_EVALUATOR to the file myapp-service-definitions.xml inside your project folder server/alpha-app/src/main/genesis/cfg/ with the code below.

<configuration>
...
<service host="localhost" name="MYAPP_EVALUATOR" port="11003"/>
</configuration>

From the Genesis plugin for Intellij, build the application.

Double-check your Resource daemon using the Genesis Intellij plugin. You should be able to see the MYAPP_EVALUATOR process on Standby.

This is because the Evaluator process is set to run only on the primary node. Our application only has one node, but we still have to identify it as the Primary node.

Run SetPrimary script as explained here and you should be able to see all processes running.

2. Create a new class

When the Evaluator is running, create a PositionReport kotlin class to trigger the new event. This class should be created inside your project folder server/myapp/src/main/kotlin/genesis/global/message/event/. Use the code below:

PositionReport
package genesis.global.message.event

class PositionReport {}

3. Create an eventHandler codeblock

Create an eventHandler codeblock that will write the csv files to the runtime/position-minute-report folder. Call it EVENT_POSITION_REPORT.

Open the file myapp-eventhandler.kts and the following eventHandler codeblock:

import genesis.global.message.event.TradeAllocated
import genesis.global.message.event.TradeCancelled
import global.genesis.TradeStateMachine
import global.genesis.gen.dao.Trade
import genesis.global.message.event.PositionReport
import global.genesis.jackson.core.GenesisJacksonMapper
import java.io.File
import java.time.LocalDate
import global.genesis.commons.standards.GenesisPaths

eventHandler {
//... other event handlers removed for clarity

eventHandler<PositionReport> (name="POSITION_REPORT"){
onCommit {
val mapper = GenesisJacksonMapper.csvWriter<TradeView>()
val today = LocalDate.now().toString()
val positionReportFolder = File(GenesisPaths.runtime()).resolve("position-minute-report")
if (!positionReportFolder.exists()) positionReportFolder.mkdirs()

entityDb.getBulk(TRADE_VIEW)
.toList()
.groupBy { it.counterpartyName }
.forEach { (counterParty, trades) ->
val file = positionReportFolder.resolve("${counterParty}_$today.csv")
if (file.exists()) file.delete()
mapper.writeValues(file).use { it.writeAll(trades) }
}

ack()
}
}
}

4. Load the cron rule into the database

Load the cron rule csv below into the database, CRON_RULE Table.

Create a new file in the same folder as USER.csv and call it CRON_RULE.csv. Add the content below to this file.

CRON_EXPRESSION,DESCRIPTION,TIME_ZONE,RULE_STATUS,NAME,USER_NAME,PROCESS_NAME,MESSAGE_TYPE
"*/30 * * ? * *","It’s a rule","Europe/London","ENABLED","A rule","admin","ALPHA_EVENT_HANDLER","EVENT_POSITION_REPORT"

5. Build and run

To build, use the Genesis Intellij plugin to select: Prepare Local Genesis Application

This runs a full Gradle build and a genesisInstall.

Now you can start the server and the UI to see the cron rule in action every sixty seconds.