appdaemon
appdaemon copied to clipboard
handle racing condition on run_every when start is immediate
Handle the racing condition on functions like run_every or run_minutely, etc when the start time would be immediate.
run_every(self,callback,self.IMMEDIATE,interval,**kwargs)
as an example.
I ran into this when upgrading to AppDaemon 4. In AppDaemon 3 the following code worked...
self.run_every(CALLBACK, datetime.datetime.now(), 300)
In AppDaemon 4 it will error.
ValueError: start cannot be in the past
File "base.py", line 42, in wrapper
result = f(*args, **kwargs)
File "plant_monitor.py", line 63, in initialize
self.run_every(self.check_for_stale, datetime.datetime.now(), 300)
File "base.py", line 176, in run_every
return super().run_every(wrapped, start, interval, *args, **kwargs)
File "appdaemon/utils.py", line 191, in inner_sync_wrapper
f = run_coroutine_threadsafe(self, coro(self, *args, **kwargs))
File "appdaemon/utils.py", line 285, in run_coroutine_threadsafe
result = future.result(self.AD.internal_function_timeout)
File "concurrent/futures/_base.py", line 439, in result
return self.__get_result()
File "concurrent/futures/_base.py", line 388, in __get_result
raise self._exception
File "appdaemon/adapi.py", line 2476, in run_every
raise ValueError("start cannot be in the past")
I found this a little strange, since the only way to make it work is to guess how much might pass and add that to the start time. For example...
datetime.datetime.now() + datetime.timedelta(seconds=1)
I hope it would always be within a second, but maybe not on a very slow/overloaded system. I am not sure what AppDaemon 3 did in the case of a historical datetime. Did it just run it ASAP? That seems like a more natural behaviour to me.
in AD 3 it did work the same way, but it seems that the code did handle it just a little faster.
we will add the ASAP option in a future release