3826: Merge branch 'master' into 3826-crunchstat-netstats
[arvados.git] / services / nodemanager / arvnodeman / timedcallback.py
1 #!/usr/bin/env python
2
3 from __future__ import absolute_import, print_function
4
5 import heapq
6 import time
7
8 import pykka
9
10 from .config import actor_class
11
12 class TimedCallBackActor(actor_class):
13     """Send messages to other actors on a schedule.
14
15     Other actors can call the schedule() method to schedule delivery of a
16     message at a later time.  This actor runs the necessary event loop for
17     delivery.
18     """
19     def __init__(self, max_sleep=1):
20         super(TimedCallBackActor, self).__init__()
21         self._proxy = self.actor_ref.proxy()
22         self.messages = []
23         self.max_sleep = max_sleep
24
25     def schedule(self, delivery_time, receiver, *args, **kwargs):
26         if not self.messages:
27             self._proxy.deliver()
28         heapq.heappush(self.messages, (delivery_time, receiver, args, kwargs))
29
30     def deliver(self):
31         if not self.messages:
32             return None
33         til_next = self.messages[0][0] - time.time()
34         if til_next < 0:
35             t, receiver, args, kwargs = heapq.heappop(self.messages)
36             try:
37                 receiver(*args, **kwargs)
38             except pykka.ActorDeadError:
39                 pass
40         else:
41             time.sleep(min(til_next, self.max_sleep))
42         self._proxy.deliver()