def post_delete(cls, sender, **kwargs): """ :param dj_cqrs.mixins.MasterMixin sender: Class or instance inherited from CQRS MasterMixin. """ if not sender.CQRS_PRODUCE: return instance = kwargs['instance'] if not instance.is_sync_instance(): return instance_data = { 'id': instance.pk, 'cqrs_revision': instance.cqrs_revision + 1, 'cqrs_updated': str(now()), } data = instance.get_custom_cqrs_delete_data() if data: instance_data['custom'] = data signal_type = SignalType.DELETE payload = TransportPayload( signal_type, sender.CQRS_ID, instance_data, instance.pk, expires=get_expires_datetime(), ) # Delete is always in transaction! transaction.on_commit(lambda: producer.produce(payload))
def from_message(cls, dct): """Builds payload from message data. :param dct: Deserialized message body data. :type dct: dict :return: TransportPayload instance. :rtype: TransportPayload """ if 'expires' in dct: expires = dct['expires'] if dct['expires'] is not None: expires = dateutil_parse(dct['expires']) else: # Backward compatibility for old messages otherwise they are infinite by default. expires = get_expires_datetime() return cls( dct['signal_type'], dct['cqrs_id'], dct['instance_data'], dct.get('instance_pk'), previous_data=dct.get('previous_data'), correlation_id=dct.get('correlation_id'), expires=expires, retries=dct.get('retries') or 0, )
def test_get_expires_datetime_infinite(mocker, settings): settings.CQRS['master']['CQRS_MESSAGE_TTL'] = None fake_now = datetime(2020, 1, 1, second=0, tzinfo=timezone.utc) mocker.patch('django.utils.timezone.now', return_value=fake_now) result = get_expires_datetime() assert result is None
def test_get_expires_datetime(mocker, settings): settings.CQRS['master']['CQRS_MESSAGE_TTL'] = 3600 fake_now = datetime(2020, 1, 1, second=0, tzinfo=timezone.utc) mocker.patch('django.utils.timezone.now', return_value=fake_now) result = get_expires_datetime() expected_result = fake_now + timedelta(seconds=3600) assert result == expected_result
def post_save(cls, sender, **kwargs): """ :param dj_cqrs.mixins.MasterMixin sender: Class or instance inherited from CQRS MasterMixin. """ if not sender.CQRS_PRODUCE: return update_fields = kwargs.get('update_fields') if update_fields and ('cqrs_revision' not in update_fields): return instance = kwargs['instance'] if not instance.is_sync_instance(): return using = kwargs['using'] sync = kwargs.get('sync', False) queue = kwargs.get('queue', None) connection = transaction.get_connection(using) if not connection.in_atomic_block: instance.reset_cqrs_saves_count() instance_data = instance.to_cqrs_dict(using, sync=sync) previous_data = instance.get_tracked_fields_data() signal_type = SignalType.SYNC if sync else SignalType.SAVE payload = TransportPayload( signal_type, sender.CQRS_ID, instance_data, instance.pk, queue, previous_data, expires=get_expires_datetime(), ) producer.produce(payload) elif instance.is_initial_cqrs_save: transaction.on_commit( lambda: MasterSignals.post_save( sender, instance=instance, using=using, sync=sync, queue=queue, ), )
def handle_retry(self, channel, consumer_generator, dead_letters_count): self.stdout.write("Total dead letters: {}".format(dead_letters_count)) for i in range(1, dead_letters_count + 1): self.stdout.write("Retrying: {}/{}".format(i, dead_letters_count)) method_frame, properties, body = next(consumer_generator) dct = ujson.loads(body) dct['retries'] = 0 if dct.get('expires'): # Message could expire already expires = get_expires_datetime() dct['expires'] = expires.replace(microsecond=0).isoformat() payload = TransportPayload.from_message(dct) payload.is_requeue = True RabbitMQTransportService.produce(payload) message = ujson.dumps(dct) self.stdout.write(message) RabbitMQTransportService.nack(channel, method_frame.delivery_tag)