Module timer

Timer module that supports one-time timer, periodic timer and Cron-compatible syntax.

Type timer

timer.cancel(timer)

Cancels a running timer.

timer.cron(cron, hook, varargs)

Creates a new timer object, which will elapse at every date described by the cron parameter.

timer.latencyExec(func, latency)

Calls a function within a maximum delay, while trying to avoid multiple calls.

timer.new(expiry, hook, varargs)

Setups and returns a new timer object.

timer.once(delay, hook, varargs)

Creates a new timer object, which will elapse after delay seconds.

timer.periodic(period, hook, varargs)

Creates a new timer object, which will elapse every period seconds.

timer.rearm(timer)

Rearms a canceled or expired timer.

Type timer

Field(s)

timer.cancel(timer)

Cancels a running timer.

No signal will be triggered with this timer object. A canceled timer can be rearmed using the rearm function.

Parameter

Return values

  1. "ok" on success.

  2. nil followed by an error message otherwise.

timer.cron(cron, hook, varargs)

Creates a new timer object, which will elapse at every date described by the cron parameter.

If a hook function is provided, it is run whenever the timer elapses. This is an alternative to timer.new.

CRON specification strings

Cron entries are strings of 5 elements, separated by single spaces.

      .---------------- minute (0 - 59)
      |  .------------- hour (0 - 23)
      |  |  .---------- day of month (1 - 31)
      |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
      |  |  |  |  .---- day of week (0 - 7) (Sunday=0 or 7)  OR sun,mon,tue,wed,thu,fri,sat
      |  |  |  |  |  .- optional random jitter
      |  |  |  |  |  |
      *  *  *  *  *  *

The corresponding event is triggered every minute at most, if and only if every field matches the current date. Asterisks ("*") can be used as placeholderst in unused fields. For instance, "30 8 1 * * *" describes an event which takes place at 8:30AM every first day of the month.

Beside numbers, some operators are allowed in fields:

  • As mentionned, the asterisk ('*') placeholder represents all possible values for a field. For example, an asterisk in the hour time field would be equivalent to 'every hour' (subject to matching other specified fields).

  • The comma (',') is a binary operator which specifies a list of possible values, e.g. "1,3,4,7,8" (there must be no space around commas)

  • The dash ('-') is a binary operator which specifies a range of values. For instance, "1-6" is equivalent to "1,2,3,4,5,6"

  • The slash ('/') is a binary operator, called "step", which allows to skip a given number of values. For instance, "*/3" in the hour field is equivalent to "0,3,6,9,12,15,18,21".

For instance, "0 * * * *" denotes an event at every hour (whenever the number of minutes reaches 0), but "0 */6 * * *" denotes only the hours divisible by 6 (i.e. 0:00, 6:00, 12:00 and 18:00). Beware that the formal meaning of the '/' operator is "whenever the modulo is 0". As a consequence, "*/61" in the minutes slot will be triggered when the number of minutes reaches 0, because 0/61==0.

Cron also accepts some aliases for common periodicities. "@hourly", "@daily", "@weekly", "@monthly"and "@annually" represent the corresponding expected periodic events.

CRON jitter extension

timer.cron() supports an addition to the cron standard: if a sixth number element is appended to the string, this number is taken as a random jitter, in seconds. For instance, if a jitter of 120 is given, a random shifting between 0 and 120 is chosen when the timer is created; every triggerring of the event will be time-shifted by this amount of time.

The jitter doesn't change during the lifetime of a given timer: if a minutely test "* * * * * 59" is triggered at 12:03:28, it will be triggered next at 12:04:28, 12:05:28 etc.: jitters don't modify the time which elapses between the triggerings of a given timer.

Jitter allows to spread the triggering dates of resource-intensive operations. For instance, if a communication to the M2M operating portal is scheduled at midnight with "0 0 * * *" on a large fleet of devices, congestion might ensue on the communication networks and/or on the servers. By adding a 60604 = 14400 jitter, communications will be uniformly spread between 0:00AM and 04:00AM: "0 0 * * * 14400".

CRON specified with a table

Cron specifications can also be entered as tables, with keys `minute, hour, dayofmonth, dayofweek, jitter` respectively; missing keys are treated as "*" (except for jitter, which is treated as missing); lists of values are passed as tables; steps and ranges are not supported in any special ways, but they can be passed as strings, e.g. { hour='9-12,14-17', minute=0 }.

Parameters

  • cron : specification of the cron dates, as a cron string or a table (see timer.new)

  • hook : optional function, run everytime the timer elapses

  • varargs : optional parameters for hook

Return value

a timer object

timer.latencyExec(func, latency)

Calls a function within a maximum delay, while trying to avoid multiple calls.

In some cases, a task must be performed within the next n seconds; if the task is performed by calling function f, then a call to timer.latencyexec(f, n) will guarantee that. If f hasn't been run after the n seconds delay expired (neither by this thread nor any other one), then the execution of f is triggered. However, if f has already been triggered by another call to timer.latencyexec before the delay expired, then it isn't triggered a second time.

When a function can treat data by batches and is idempotent (think for instance flushing buffered data to a server), calling it with a delay through latencyexec leaves a chance to group multiple invocations into a single one, thus presumably saving resources.

Parameters

  • func : function to run.

  • latency : optional number. Time to wait before running the function (in seconds), if set to O then the function is run asynchronously but as soon as possible. if set to nil, then the function is run synchronously.

Return values

  1. "ok" on success.

  2. nil followed by an error message otherwise.

Usage:


timer.latencyExec examples

-- t1: `f` must have run within the next 10s
timer.latencyexec(f, 10)
-- t2: `f` must have run within the next 5s. This supersedes t1
timer.latencyexec(f, 5)
-- after 3s elapsed, `f` must run within the next 5s-3s=2s
sched.wait(3)
-- t3: `f` must have run within the next 1s. This supersedes the 2s left in t2
t3 = timer.latencyexec(f, 1)
-- `f` will run in the middle of this 2s delay, due to t3
sched.wait(2)
-- This has been scheduled after t3 elapsed, so `f` will be run again in 1s at most.
t4 = timer.latencyexec(f, 1)
timer.new(expiry, hook, varargs)

Setups and returns a new timer object.

This function can be called directly instead of timer.once, timer.periodic and timer.cron.

The event will cause a signal([returned timer], 'run') whenever its due date(s) is/are reached. The date(s) is/are determined by the expiry argument:

  • If expiry is a positive number, causes a 1-shot event after that delay, in seconds, has elapsed.

  • If expiry is a negative number, causes a periodic event whose period is the (positive) opposite of expiry, in seconds.

  • If expiry is a string or a table, causes events at the dates described under the POSIX CRON format. Cf. timer.cron for a detailed description of the CRON format. assert

Parameters

  • expiry : string or number specifying the timer's due date(s). See explanations above.

  • hook : an optional function which will be called whenever the timer is due. The hook is called in a new thread (thus blocking functions are allowed in it).

  • varargs : optional additional parameters, which will be passed to the hook function when called.

Return values

  1. created timer on success.

  2. nil followed by an error message otherwise.

timer.once(delay, hook, varargs)

Creates a new timer object, which will elapse after delay seconds.

If a hook function is provided, it is run when the timer elapses.

Parameters

  • delay : the duration before the timer elapses, in seconds

  • hook : optional function, run when the timer elapses

  • varargs : optional parameters for hook

timer.periodic(period, hook, varargs)

Creates a new timer object, which will elapse every period seconds.

If a hook function is provided, it is run whenever the timer elapses.

Parameters

  • period : the duration between two timer triggerrings, in seconds

  • hook : optional function, run everytime the timer elapses

  • varargs : optional parameters for hook

timer.rearm(timer)

Rearms a canceled or expired timer.

Same as new function. A signal will be emitted on timer expiration. Rearming a timer that have not expired, reset it to its inital value.

Parameter

Return values

  1. "ok" on success.

  2. nil followed by an error message otherwise.