Timers

Repeated actions

Timers can be used to repeat an action after a period of time. To illustrate this, let us modify the Push-Pull example a bit and make use of the .each() method:

import time

from osbrain import run_agent
from osbrain import run_nameserver


def log_message(agent, message):
    agent.log_info('Received: %s' % message)


def annoy(agent, say, more=None):
    message = say if not more else say + ' ' + more + '!'
    agent.send('annoy', message)


if __name__ == '__main__':

    ns = run_nameserver()
    orange = run_agent('Orange')
    apple = run_agent('Apple')
    addr = orange.bind('PUSH', alias='annoy')
    apple.connect(addr, handler=log_message)

    # Multiple timers with parameters
    orange.each(1.0, annoy, 'Hey')
    orange.each(1.4142, annoy, 'Apple')
    orange.each(3.1415, annoy, 'Hey', more='Apple')

    time.sleep(10)

    ns.shutdown()

Note that if an action takes longer to run than the time available before the next execution, the timer will simply fall behind.

Note

To be able to start timers on agent initialization, the agent must be already running, which means you cannot do it from .on_init(). Instead, you can use .before_loop(), which will be called inside the .run() method and before starting the main loop.

Delayed actions

Timers can be used to execute an action after a defined time delay using the .after() method:

import time

from osbrain import run_agent
from osbrain import run_nameserver


def delayed(agent):
    agent.log_info('Logged later')


if __name__ == '__main__':

    ns = run_nameserver()
    agent = run_agent('a0')

    agent.after(2, delayed)
    agent.log_info('Logged now')

    time.sleep(2.5)

    ns.shutdown()

Note that if an action takes longer to run than the time available before the next execution, the timer will simply fall behind.

Stopping timers

When executing the .each() or .after() methods, a timer is created and an identifier is returned that can be used later to refer to that timer (i.e.: for stopping it).

In the following example we can see how the returned identifier and an alias parameter can be used to identify the timer and stop it calling the .stop_timer() method:

import time

from osbrain import run_agent
from osbrain import run_nameserver


def delayed(agent, message):
    agent.log_info(message)


if __name__ == '__main__':

    ns = run_nameserver()
    agent = run_agent('a0')

    agent.after(1, delayed, 'Hello!')
    # Timer ID returned
    timer0 = agent.after(1, delayed, 'Never logged')
    # Timer alias set
    agent.after(1, delayed, 'Never logged either', alias='timer_alias')

    # Stop timers by ID and alias
    agent.stop_timer(timer0)
    agent.stop_timer('timer_alias')

    time.sleep(2)

    ns.shutdown()

You can call the .stop_all_timers() method if you would rather simply stop all started timers.

If you want to list the timers that are currently running, you can call the .list_timers() method.