scheduler.lua
Schedule jobs to run at a specified time of day, very useful for batch processing
local scheduler={} local LastRunTime = 0 local ScheduledRunTime = 0 local function NextRunTime(Hour, LastRunTime) local T = os.ts.date('*t') T.hour = Hour T.min = (Hour - math.floor(Hour)) * 60 T.sec = 0 local NextTime = os.ts.time(T) local LastT = os.ts.date('*t', LastRunTime) os.ts.date("%c", LastRunTime) if os.ts.difftime(LastRunTime, NextTime) > 0 then NextTime = NextTime + 24*60*60 end return NextTime, os.ts.date("%c", NextTime) end local function RunFileName() return iguana.channelName():gsub('%s','_')..'_LastScheduledTime.txt' end local function LastRun() if not os.fs.access(RunFileName()) then return 0, 'No recorded run' end local F = io.open(RunFileName(), 'r') local T = F:read('*a') F:close() return tonumber(T), 'Last run at '..os.ts.date('%c', tonumber(T)) end local function Status(LastRun, ScheduledTime) local R if LastRun ~= 0 then R = 'Last run at '..os.ts.date('%c', LastRun) else R = 'Has not run yet.' end R = R..'\nScheduled to run at '..os.ts.date('%c',ScheduledTime) iguana.setChannelStatus{color='green', text=R} return R end local function RecordRun(ScheduledHour) if iguana.isTest() then return end local R = os.ts.time() local F = io.open(RunFileName(), 'w') F:write(R) F:close() LastRunTime = R ScheduledRunTime = NextRunTime(ScheduledHour, LastRunTime) local R = Status(LastRunTime, ScheduledRunTime) iguana.logInfo(R) end local function Init(Time) LastRunTime = LastRun() ScheduledRunTime = NextRunTime(Time, LastRunTime) local R = Status(LastRunTime, ScheduledRunTime) iguana.logInfo(R) return R end function scheduler.runAt(ScheduledHour, Func, Arg) local R trace(LastRunTime) if LastRunTime == 0 or iguana.isTest() then -- We need to do one time initialization R = Init(ScheduledHour) end trace(ScheduledRunTime) local WouldRun = (os.ts.time() > ScheduledRunTime and LastRunTime <= ScheduledRunTime) trace("Would run = "..tostring(WouldRun)) if WouldRun then iguana.logInfo('Kicking off batch process') Func(Arg) RecordRun(ScheduledHour) return R end if iguana.isTest() then Func(Arg) return R end return R end local scheduler_runAt = { Title="scheduler.runAt"; Usage="scheduler.runAt(time, function [, argument])", SummaryLine="Schedule a function to run at a specified time", Desc=[[Schedule a function to run at a specified time, optionally you can pass a single argument for the scheduled function. ]]; ParameterTable= true, Parameters= { {time= {Desc='Scheduling time <u>number</u>.'}}, {['function']= {Desc='The function to be run <u>function</u>.'}}, {argument= {Desc='Argument to pass to the function <u>any type</u>.', Opt = true}}, }; Returns = { {Desc="Information on previous and next scheduled runtime <u>string</u>."}, }; Examples={ [[ -- Within the editor we the function runs all the time. local function DoBatchProcess(Data) iguana.logInfo('Processed a lot of X12') end function main() -- schedule the job function to run at 11.30pm scheduler.runAt(23.5, DoBatchProcess, "Some Argument") end ]], }; SeeAlso={ { Title="scheduler.lua - in our code repository", Link="http://help.interfaceware.com/code/details/scheduler-lua" }, { Title="Scheduler example", Link="http://help.interfaceware.com/v6/scheduler-example" } } } help.set{input_function=scheduler.runAt, help_data=scheduler_runAt} return scheduler
A common interface requirement involves running a batch job at a specific time of day (for example, every night at 10pm). Although Iguana does not have this capability built directly into the product, it is simple to create a simple channel that will perform this task. The scheduler.runAt()
function simply checks the time and runs the function. It also stores information (in a text file) about when each process was last run, and checks to ensure that each task is only run once at the scheduled time.
The module also does a few other useful things like : Logging useful error messages (in the Iguana log), changing the tooltips for scheduled jobs to show when they were last run, and if is running in the editor (test mode), it always run the job as scheduled (as opposed to live which checks when the job was last run to prevent running it more than once).
How to use scheduler.lua:
- Create a “Scheduler” channel and set the polling time to sensible period like 5 minutes (300,000 milliseconds)
- Load the module into a From Translator component
- Use
scheduler.runAt()
to run your function at the desired time
Here is some example code for main():
scheduler = require 'scheduler' -- This scheduler script can be used to run a script at a given time -- https://help.interfaceware.com/code/details/scheduler-lua -- Within the editor we the function runs all the time. local function DoBatchProcess(Data) iguana.logInfo('Processed a lot of X12') end function main() -- schedule the job function to run at 11.30pm scheduler.runAt(23.5, DoBatchProcess, "Some Argument") end