Configuring the SmartScheduler runtime

The SmartFramework scheduler allows for the execution of long running jobs in one or multiple scheduler runtimes potentially distributed on different machines. A scheduler runtime is configured to run all scheduled jobs for a particular queue, which may be the default (empty) queue.

Jobs are scheduled through the Scheduler screens in the SmartFramework maintenance and stored in the SmartSchedulerQueue, SmartSchedulerJob, SmartSchedulerJobPlan and SmartSchedulerJobStatus tables. Jobs can be executed once (e.g. long asynchronous job) or following scheduler patterns.

The scheduler does not depend on the use of the OpenEdge AppServer by design. The AppServer is not designed to execute jobs based on a scheduler (unlike the J2EE AppServer for instance). AppServer processes should be reserved to serve requests from GUI sessions or application integration requests. It is however possible to execute jobs using the scheduler which connect to an AppServer for (parts of) the execution of the job logic.

The scheduler runtime

The SmartFramework scheduler runtime is implemented in the procedures Consultingwerk/SmartFramework/Scheduler/Runtime/start.p and Consultingwerk/SmartFramework/Scheduler/Runtime/start-json.p. These procedures are designed to be executed in ABL batch sessions (prowin, prowin32, _progres). The batch sessions can be executed on the same machine that holds a database (shared memory connection), the machine executing an AppServer or a separate machine. Through the design of the scheduler, it’s also possible to distribute the load of the batch scheduler to multiple machines. Queues should be used to refine which jobs are executed by each distributed runtime process.

During the implementation of the scheduler runtime special care has been taken to ensure that multiple parallel running scheduler runtimes will not conflict when accessing the SmartSchedulerJobStatus records in a shared database.

The scheduler is designed to be executed and kept running from any suitable OS scheduler including CRON and the Windows Scheduler. One or many instances are expected to be executed. When executed each instance of the scheduler runtime will seek for jobs due for execution and will execute as many jobs as can be found. After each execution the scheduler runtime may sleep for a given number of seconds and then rescan the database for jobs that are due now. After a given amount of time the scheduler runtime will exit and should be replaced by a fresh instance of a scheduler session.

The scheduler startup procedures are intended to be executed via Ant and PCT .

Using JSON configuration file (start-json.p)

The SmartScheduler runtime supports using a JSON configuration file to specify parameters for the scheduler, using the https://consultingwerk.atlassian.net/wiki/spaces/SCL/pages/8094594 . Values specific to the Scheduler Runtime may be provided as static properties (eg Consultingwerk.SmartFramework.Scheduler.Runtime.SchedulerRuntime:Verbose ) in this configuration file, or they may be specified as a parameter to the PCTRun task. Values supplied to the Ant task will override those in the configuration file.

The name of the queue is provided either in the configuration file or as an Ant property. If the provided queue code is not empty/blank, or cannot be found in the SmartDB, an error is raised and the task stops execution.

The name of this file is provided to the task using a ConfigFile property. This value can be relative- or absolutely-pathed file name. If the file cannot be found, an error is raised and the task stops execution.

Configuration JSON format

An example of the configuration provided to the scheduler runtime is below. All properties are optional, so at a minimum an empty JSON object - {} - must be passed in.

For example, the JSON below can be used to set the scheduler’s QueueCode property. A queue named Linux must exist.

{ "staticProperties": { "Consultingwerk.SmartFramework.Scheduler.Runtime.SchedulerRuntime:QueueCode": "Linux } }

For example, the JSON below can be used to set the scheduler’s Verbose and KeepRunning properties.

{ "staticProperties": { "Consultingwerk.SmartFramework.Scheduler.Runtime.SchedulerRuntime:Verbose": true, "Consultingwerk.SmartFramework.Scheduler.Runtime.SchedulerRuntime:KeepRunning": 9000 } }

It is recommended that the QueueCode always specified.

Sample Ant script for scheduler execution

Below you’ll find a sample Ant script for executing the SmartFramework scheduler runtime. The key element is the PCTRun task executing the scheduler runtime procedure and passing the configuration file name as a parameter.

<?xml version="1.0" encoding="utf-8"?> <project name="Scheduler Runtime" default="scheduler" basedir="."> <description>SmartComponent Library Scheduler Runtime</description> <property environment="env" /> <property file="build/build.props" /> <property name="ConfigFile" value="" /> <taskdef resource="PCT.properties" classpath="PCT.jar" /> <typedef resource="types.properties" classpath="PCT.jar" /> <import file="build/smartcomponents.xml"/> <import file="build/smartcomponents-support.xml"/> <target name="scheduler"> <PCTVersion /> <PCTRun taskname="Scheduler" procedure="Consultingwerk/SmartFramework/Scheduler/Runtime/start-json.p" graphicalMode="false" dlcHome="${progress.DLC}" cpinternal="iso8859-1" cpstream="iso8859-1" inputchars="32000" iniFile="ini/progress.ini" token="4000" tempDir="/temp" dirSize="10000"> <propath refid="smartcomponents.propath.default" /> <Parameter name="configFile" value="${ConfigFile}" /> </PCTRun> </target> </project>

The Ant script is expected to be executed permanently through a system scheduler process (the host).

Using individual parameters (start.p)

In this approach, all database, PROPATH and other parameter values are provided in the Ant script, using nested <DBConnection>, <propath> and other elements.

The following parameters are supported passed from the PCTRun Ant task:

Parameter Name

Description

Parameter Name

Description

verbose

Logical value (true/false) controlling verbose output to the log

keepRunning

Number of seconds to keep the scheduler runtime running, e.g. 300 for 5 minutes, 86400 for a full day

pauseBetweenPolling

Number of seconds the scheduler runtime pauses before polling after no due jobs have been found

QueueCode

The code for the queue to execute. Defaults to blank if not specified.

Sample Ant script for scheduler execution

Below you’ll find a sample Ant script for executing the SmartFramework scheduler runtime. The key element is the PCTRun task executing the scheduler runtime procedure and passing values for the keepRunning and pauseBetweenPolling parameters.

The Ant script is expected to be executed permanently through a system scheduler process (the host).

Using Jenkins as a host for the scheduler

Our preferred host for the scheduler runtime is Jenkins (https://jenkins.io/). Benefits of using Jenkins are

  • Free and open source

  • Platform and OS scheduler independent configuration, available on Windows and Linux and other operating systems

  • Comfortable logging in the Jenkins console

  • Error reporting through email to selected recipients

  • Simple configuration of multiple parallel execution environments

  • Distribution on multiple machines through Jenkins slaves

To execute the scheduler runtime Ant script, at least one Jenkins job needs to be setup. When the scheduler should be executed in multiple parallel runtime sessions, multiple Jenkins jobs need to be configured (as a copy of each other). Each Jenkins job can only ever be executed once in parallel.

There are multiple options to configure a Jenkins job for permanent execution that can also be used in combination:

1.) Using a periodically setup Build Trigger

A job that is scheduled to be executed on a Schedule “* * * * *” will always be executed. When the job is completed (after the keepRunning setting, see above) a new instance of the job will be executed instantly.

2.) Setting a job to be executed after another job has been executed

When the previous instance of a job has been executed, the job can be re-executed using the option “execute job after another job has been built”. This option may also be used to execute a new instance of a job after the previous instance of the same job has been executed.

The first option will keep executing the job in any case. Whereas the second option will stop re-executing the job after an error has occurred (e.g. when a database is no longer available).

Jenkins supports disabling and enabling a job through the Jenkins console.