Search code examples
volttron

Dynamically change a @Core.periodic method's repeat time


Assuming I have a method X with a Core.periodic decorator initially set to 60 seconds, is there a way to change the repeat time of the method X to say 45 seconds from another method (call it Y) while the agent is running?

class SomeAgent(Agent)
...
    @Core.periodic(settings.HEARTBEAT_PERIOD)
    method X():
       #Do stuff

    method Y():
       #Change method X's repeat time

Solution

  • If you want to change a periodic you must set it up using a call to self.core.periodic.

    self.core.periodic returns a reference to the greenlet which is running the periodic method. Call the kill method on that to stop the greenlet before you start a new one. You'll want to setup the periodic in an onsetup method. Unless your periodic function uses the message bus, in which case you will want to put in it an onstart method.

    class SomeAgent(Agent):
        def __init__(self, **kwargs):
            super(SomeAgent, self).__init__(**kwargs)
            self.periodic_greenlet = None
    
        @Core.receiver('onstart')
        def onstart(self, sender, **kwargs):
            self.periodic_greenlet = self.core.periodic(settings.HEARTBEAT_PERIOD, self.X)
    
    
        def X(self):
           #Do stuff
    
        def Y(self, new_period):
           #Checking for None may seem superfluous, but there are some possible race
           #conditions at startup that cannot be completely eliminated.
           if self.periodic_greenlet is not None:
               self.periodic_greenlet.kill()
    
           self.periodic_greenlet = self.core.periodic(new_period, self.X)