def inner(self, *args, **kwargs): # abort if these message has already been processed and another event message # has already been emitted to drive the state machine forward primary = get_message_dispatched(self.correlation_id, self.steps, primary=True) secondary = get_message_dispatched(self.correlation_id, self.steps, primary=False) dispatched = primary or secondary if dispatched: self._queue_error( ERRORS.DUPLICATE, 'Message has been processed already (%s).' % dispatched) return f(self, *args, **kwargs) # once the message is emitted, we want to make sure the current event is never sent again. # the approach here is to simply use a cache to set a key like "correlation_id-steps" primary = set_message_dispatched(self.correlation_id, self.steps, self.retries, primary=True) secondary = set_message_dispatched(self.correlation_id, self.steps, self.retries, primary=False) dispatched = primary and secondary # 'and' is correct here. it just triggers an alarm. if not dispatched: self._queue_error( ERRORS.CACHE, 'Unable set message dispatched for idempotency.')
def smoke(self): correlation_id = uuid.uuid4().hex # can dispatch dispatched = aws.set_message_dispatched(correlation_id, 1, 1) self.assertTrue(dispatched is True) # is dispatched dispatched = aws.get_message_dispatched(correlation_id, 1) self.assertTrue(dispatched == correlation_id + '-1-1') # can dispatch with timeout dispatched = aws.set_message_dispatched(correlation_id, 1, 1, timeout=1) self.assertTrue(dispatched is True) time.sleep(2) # is not dispatched after timeout dispatched = aws.get_message_dispatched(correlation_id, 1) self.assertTrue(dispatched is None)