Schedule Regular Jobs
Some applications involve solving a mathematical program regularly, for instance every night or every ten minutes.
There are two mechanisms available to achieve this.
Tasks v2 on AIMMS Cloud explains clearly how to achieve regular execution easily.
AIMMS PRO jobs that reschedule themselves. This may be a bit tricky and warrants a detailed example.
In the remainder of this article, we’ll discuss how an AIMMS job can reschedule itself, as depicted in the next picture.
Effectively, this realizes that the job at hand is solved regularly. As you can see from this image:
The WebUI session you start via AIMMS PRO has an associated AIMMS data session. This data session has a
pro::CurrentDelegationLevel()
of 0; there is no delegation of work yet.The AIMMS solver session started from this AIMMS Data Session has a
pro::CurrentDelegationLevel()
of 1; it is the consequence of one delegation.The AIMMS solver session started from the above AIMMS solver session has a
pro::CurrentDelegationLevel()
of 1 higher than its predecessor.
To start this sequence, the following code is used.
1Procedure pr_OnButtonStartServerSessions {
2 Body: {
3 ep_PayloadProcedure := StringToElement( AllProcedures, "pr_Friesian", create: 0 );
4 pr_IterativeJobScheduling(
5 maxDelegateLevel : 4,
6 timeIncrement : 2[second],
7 epPayloadProcedure : ep_PayloadProcedure);
8 }
9}
Each line is explained as follows:
Determine the payload procedure that should be executed by each solver session. Here it is the
pr_Friesian
, as Friesian horses are excellent workhorses.A call to the procedure that actually starts each solver session.
The number of server sessions started is controlled by
maxDelegateLevel
The argument
timeIncrement
, is the time between sessions measured in seconds.The procedure to be executed regularly passed via the arguments.
The center piece of the project is the procedure pr_IterativeJobScheduling
:
1Procedure pr_IterativeJobScheduling {
2 Arguments: (maxDelegateLevel,timeIncrement,epPayloadProcedure);
3 Body: {
4 if pro::CurrentDelegationLevel() < maxDelegateLevel then
5 if pro::DelegateToServer(
6 requestDescription :
7 formatString("The %i'th iteration of %e",
8 pro::CurrentDelegationLevel()+1,
9 epPayloadProcedure),
10 waitForCompletion : 0,
11 completionCallback : 'pro::session::EmptyCallback',
12 delegationOverride : pro::CurrentDelegationLevel() + 1,
13 scheduledAt :
14 if pro::CurrentDelegationLevel() then
15 MomentToString( sp_LocalTimeFormat, [second],
16 CurrentToString(sp_ReferenceTimeformat),
17 timeIncrement )
18 else "" endif
19 ) then
20 return 1 ;
21 endif ;
22 endif ;
23
24 Apply( epPayloadProcedure );
25 }
26 Parameter maxDelegateLevel {
27 Property: Input;
28 }
29 Parameter timeIncrement {
30 Unit: second;
31 Property: Input;
32 }
33 ElementParameter epPayloadProcedure {
34 Range: AllProcedures;
35 Default: 'MainExecution';
36 Property: Input;
37 }
38}
Each portion of the procedure code is explained below:
Line 4: Limit the number of recurring jobs. When your application does not have a fixed number of jobs, you can remove this line and the argument
maxDelegateLevel
.Line 6:
requestDescription
: to properly identify each job in job overviews and in the session logs.Line 9:
delegationOverride
: necessary to submit jobs from within server sessions.Line 10:
scheduleAt
: Construct the next time the job is to be executed. By using the Local timezone, ambiguities regarding daylight saving time are avoided. Heresp_LocalTimFmt = "%c%y-%m-%d %H:%M:%S%TZ('Local')"
.Line 16: This will execute the payload for each of the server sessions started. The APPLY operator is used here.
To operate, the example that can be downloaded here
.
Create an .aimmspack, publish on your favorite AIMMS PRO system.
Launch it and press the only button
Close the app. Yes, once the sequence of server sessions is started, the WebUI of the enclosed example is no longer of use - it can be closed.
Go to job tab in the AIMMS PRO portal and watch new jobs being created, queued, running, and finished.
Note
When you check the session.log files, you may encounter a line like:
12:10:46,186 0x7f6389d90700 [INFO] {PRO.Client.Library} pr_Friesian(): At 2018-09-04 12:10:46 (UTC) delegation level is 3
That is because the procedure
pr_Friesian
uses the procedure callpro::management::LocalLogInfo(...);
to log some information about current solver session.When you want to interrupt a sequence of server jobs, please terminate the scheduled session before terminating the running session.
Note
The reference time format is initialized as follows:
1Procedure PostMainInitialization {
2 Body: {
3 if pro::GetPROEndPoint() then
4 pro::Initialize();
5 endif ;
6
7 block ! Determine the reference time format to be used in MomentToString.
8 p_getOPG := OptionGetValue(
9 OptionName : "use_UTC_forCaseAndStartEndDate",
10 Lower : p_lower,
11 Current : p_current,
12 Default : p_default,
13 Upper : p_upper);
14 if p_getOPG > 0 then
15 if p_current > 0 then
16 sp_ReferenceTimeformat := sp_UTCTimeFormat ;
17 else
18 sp_ReferenceTimeformat := sp_LocalTimeFormat ;
19 endif ;
20 else
21 ! option not defined. Assume local time format.
22 sp_ReferenceTimeformat := sp_LocalTimeFormat ;
23 endif ;
24 endblock ;
25 }
26 Comment: {
27 "Add initialization statements here that require that the libraries are already initialized properly,
28 or add statements that require the Data Management module to be initialized."
29 Parameter p_getOPG;
30 Parameter p_lower;
31 Parameter p_current;
32 Parameter p_default;
33 Parameter p_upper;
34}