class Reactor(object): def __init__(self, redis, events, periodics=[], select=[]): self.logger = logging.getLogger('reactor') self.selector = Selector(select) self.db = ReactorDB(redis) self.mapper = dict(self.mapper_gen(events)) self.periodics = periodics self.timeline = SortedDict() self.load() def time(self): return itime() def mapper_gen(self, events): for event in events: yield event.type(), event def __getitem__(self, name): return self.selector.get(name) def add_to_queue(self, event, time): self.selector.process(event) self.get(time).append(event) def load(self): for time, event_queue in self.db.event_models: for event_db in event_queue: event = self.mapper.get(event_db.type.get()) if event: self.add_to_queue(event(**event_db.params.get()), time=time) def flush(self): self.timeline.clear() self.selector.clear() def get(self, time): queue = self.timeline.get(time) if queue is None: queue = self.timeline[time] = [] return queue def append(self, event, tdelta=None, time=None): time = time or self.time() + tdelta self.add_to_queue(event, time) self.db.dump(time, event) return time def wait_for_calc(self, time): done = False while self.timeline and not done: smallest_time, events = self.timeline.smallest_item() if smallest_time <= time: yield smallest_time, events else: done = True def remove_events(self, time): if time in self.timeline: del self.timeline[time] self.db.remove_item(time) def execute(self, event, time): try: event.do(self, time) except Exception: self.logger.error('%s executing at %s' % (event, time), exc_info=1) def calc(self, time=None): time = time or self.time() for event in self.periodics: self.execute(event, time) for expected_time, events in self.wait_for_calc(time): for event in events: self.execute(event, time) self.selector.remove(event) self.remove_events(expected_time)
def test_clear(self): a = SortedDict({'a': 1, 'b': 2}) a.clear() self.assertEqual(len(a), 0) self.assertTrue('a' not in a)