def test_example_aggregate_event_classes(self):
        self.assertIn("Event", ExampleAggregateRoot.__dict__)
        self.assertIn("Created", ExampleAggregateRoot.__dict__)
        self.assertIn("Discarded", ExampleAggregateRoot.__dict__)
        self.assertIn("AttributeChanged", ExampleAggregateRoot.__dict__)

        self.assertEqual(ExampleAggregateRoot.Event.__name__, "Event")
        self.assertEqual(ExampleAggregateRoot.Event.__qualname__, "ExampleAggregateRoot.Event")
        topic = "eventsourcing.tests.core_tests.test_aggregate_root#ExampleAggregateRoot.Event"
        self.assertEqual(get_topic(ExampleAggregateRoot.Event), topic)
        self.assertEqual(resolve_topic(topic), ExampleAggregateRoot.Event)

        self.assertEqual(ExampleAggregateRoot.Created.__name__, "Created")
        self.assertEqual(ExampleAggregateRoot.Created.__qualname__, "ExampleAggregateRoot.Created")
        topic = "eventsourcing.tests.core_tests.test_aggregate_root#ExampleAggregateRoot.Created"
        self.assertEqual(get_topic(ExampleAggregateRoot.Created), topic)
        self.assertEqual(resolve_topic(topic), ExampleAggregateRoot.Created)
        self.assertTrue(issubclass(ExampleAggregateRoot.Created, ExampleAggregateRoot.Event))

        self.assertEqual(ExampleAggregateRoot.Discarded.__name__, "Discarded")
        self.assertEqual(ExampleAggregateRoot.Discarded.__qualname__, "ExampleAggregateRoot.Discarded")
        topic = "eventsourcing.tests.core_tests.test_aggregate_root#ExampleAggregateRoot.Discarded"
        self.assertEqual(get_topic(ExampleAggregateRoot.Discarded), topic)
        self.assertEqual(resolve_topic(topic), ExampleAggregateRoot.Discarded)
        self.assertTrue(issubclass(ExampleAggregateRoot.Discarded, ExampleAggregateRoot.Event))

        self.assertEqual(ExampleAggregateRoot.ExampleCreated.__name__, "ExampleCreated")
        self.assertEqual(ExampleAggregateRoot.ExampleCreated.__qualname__, "ExampleAggregateRoot.ExampleCreated")
        topic = "eventsourcing.tests.core_tests.test_aggregate_root#ExampleAggregateRoot.ExampleCreated"
        self.assertEqual(get_topic(ExampleAggregateRoot.ExampleCreated), topic)
        self.assertEqual(resolve_topic(topic), ExampleAggregateRoot.ExampleCreated)
        self.assertTrue(issubclass(ExampleAggregateRoot.ExampleCreated, ExampleAggregateRoot.Event))
Beispiel #2
0
 def _decode_object(d):
     topic = d['__class__']['topic']
     state = d['__class__']['state']
     obj_class = resolve_topic(topic)
     obj = object.__new__(obj_class)
     obj.__dict__.update(state)
     return obj
Beispiel #3
0
def entity_from_snapshot(snapshot):
    """
    Reconstructs domain entity from given snapshot.
    """
    assert isinstance(snapshot, AbstractSnapshop), type(snapshot)
    if snapshot.state is not None:
        entity_class = resolve_topic(snapshot.topic)
        return reconstruct_object(entity_class, snapshot.state)
Beispiel #4
0
def decode_frozenset(d):
    set_data = d["__frozenset__"]
    if isinstance(set_data, dict):
        topic = set_data["topic"]
        state = set_data["state"]
        set_type = resolve_topic(topic)
        return set_type(state)
    else:
        return frozenset(set_data)
Beispiel #5
0
        def __mutate__(self, obj: Optional[TDomainEntity]) -> Optional[TDomainEntity]:
            """
            Constructs object from an entity class,
            which is obtained by resolving the originator topic,
            unless it is given as method argument ``entity_class``.

            :param entity_class: Class of domain entity to be constructed.
            """
            entity_class: Type[TDomainEntity] = resolve_topic(self.originator_topic)
            return entity_class(**self.__entity_kwargs__)
Beispiel #6
0
 def __mutate__(self, entity_class=None):
     if entity_class is None:
         entity_class = resolve_topic(self.originator_topic)
     with_data_integrity = getattr(entity_class,
                                   '__with_data_integrity__', True)
     if with_data_integrity:
         self.__check_hash__()
     obj = entity_class(**self.__entity_kwargs__)
     if with_data_integrity:
         obj.__head__ = self.__event_hash__
     return obj
Beispiel #7
0
 def _decode_object(d):
     topic = d['__class__']['topic']
     state = d['__class__']['state']
     obj_class = resolve_topic(topic)
     obj = object.__new__(obj_class)
     if hasattr(obj, '__dict__'):
         obj.__dict__.update(state)
     else:
         for k, v in state.items():
             object.__setattr__(obj, k, v)
     return obj
Beispiel #8
0
    def get_event_class_and_attrs(self, topic, state):
        # Resolve topic to event class.
        domain_event_class = resolve_topic(topic)

        # Decrypt state.
        if self.cipher:
            state = self.cipher.decrypt(state)

        # Deserialize data.
        event_attrs = json_loads(state, cls=self.json_decoder_class)
        return domain_event_class, event_attrs
Beispiel #9
0
def decode_object(d):
    topic = d["__class__"]["topic"]
    state = d["__class__"]["state"]
    obj_class = resolve_topic(topic)
    obj = object.__new__(obj_class)
    if hasattr(obj, "__dict__"):
        obj.__dict__.update(state)
    else:
        for k, v in state.items():
            object.__setattr__(obj, k, v)
    return obj
Beispiel #10
0
def decode_tuple(d):
    topic = d["__tuple__"]["topic"]
    state = d["__tuple__"]["state"]
    tuple_type = resolve_topic(topic)
    if topic == "builtins#tuple":
        # For standard tuple objects.
        obj = tuple_type(state)
    else:
        # For NamedTuple objects.
        obj = tuple_type(*state)
    return obj
Beispiel #11
0
        def __mutate__(self, entity_class=None):
            """
            Constructs object from an entity class,
            which is obtained by resolving the originator topic,
            unless it is given as method argument ``entity_class``.

            :param entity_class: Class of domain entity to be constructed.
            """
            if entity_class is None:
                entity_class = resolve_topic(self.originator_topic)
            return entity_class(**self.__entity_kwargs__)
    def test_aggregate1_event_classes(self):
        self.assertIn("Event", Aggregate1.__dict__)
        self.assertIn("Created", Aggregate1.__dict__)
        self.assertIn("Discarded", Aggregate1.__dict__)
        self.assertIn("AttributeChanged", Aggregate1.__dict__)

        self.assertEqual(Aggregate1.Event.__name__, "Event")
        self.assertEqual(Aggregate1.Event.__qualname__, "Aggregate1.Event")
        topic = "eventsourcing.tests.core_tests.test_aggregate_root#Aggregate1.Event"
        self.assertEqual(get_topic(Aggregate1.Event), topic)
        self.assertEqual(resolve_topic(topic), Aggregate1.Event)

        self.assertEqual(Aggregate1.Created.__name__, "Created")
        self.assertEqual(Aggregate1.Created.__qualname__, "Aggregate1.Created")
        topic = "eventsourcing.tests.core_tests.test_aggregate_root#Aggregate1.Created"
        self.assertEqual(get_topic(Aggregate1.Created), topic)
        self.assertEqual(resolve_topic(topic), Aggregate1.Created)
        self.assertTrue(issubclass(Aggregate1.Created, Aggregate1.Event))

        self.assertEqual(Aggregate1.Discarded.__name__, "Discarded")
        self.assertEqual(Aggregate1.Discarded.__qualname__,
                         "Aggregate1.Discarded")
        topic = (
            "eventsourcing.tests.core_tests.test_aggregate_root#Aggregate1"
            ".Discarded")
        self.assertEqual(get_topic(Aggregate1.Discarded), topic)
        self.assertEqual(resolve_topic(topic), Aggregate1.Discarded)
        self.assertTrue(issubclass(Aggregate1.Discarded, Aggregate1.Event))

        self.assertEqual(Aggregate1.ExampleCreated.__name__, "ExampleCreated")
        self.assertEqual(Aggregate1.ExampleCreated.__qualname__,
                         "Aggregate1.ExampleCreated")
        topic = (
            "eventsourcing.tests.core_tests.test_aggregate_root#Aggregate1"
            ".ExampleCreated")
        self.assertEqual(get_topic(Aggregate1.ExampleCreated), topic)
        self.assertEqual(resolve_topic(topic), Aggregate1.ExampleCreated)
        self.assertTrue(issubclass(Aggregate1.ExampleCreated,
                                   Aggregate1.Event))
        self.assertTrue(
            issubclass(Aggregate1.SomethingElseOccurred, Aggregate1.Event))
Beispiel #13
0
def decode_tuple(d):
    tuple_data = d["__tuple__"]
    if type(tuple_data) == dict:
        # For NamedTuple objects.
        topic = tuple_data["topic"]
        state = tuple_data["state"]
        tuple_type = resolve_topic(topic)
        obj = tuple_type(*state)
    else:
        # For standard tuple objects.
        obj = tuple(tuple_data)
    return obj
Beispiel #14
0
def decode_deque(d):
    deque_data = d["__deque__"]
    if type(deque_data) == dict:
        topic = deque_data["topic"]
        try:
            state = deque_data["state"]
        except KeyError:
            state = deque_data["values"]

        deque_type = resolve_topic(topic)
        return deque_type(state)
    else:
        return deque(deque_data)
Beispiel #15
0
def example_policy(process, repository, event):
    # Whenever an aggregate is created, then "move it on".
    if isinstance(event, ExampleAggregate.Created):
        # Get aggregate and move it on.
        aggregate = repository[event.originator_id]

        assert isinstance(aggregate, ExampleAggregate)
        aggregate.move_on()

    elif isinstance(event, Command.Created):
        command_class = resolve_topic(event.originator_topic)
        if command_class is CreateExample:
            return ExampleAggregate.__create__()
Beispiel #16
0
    def from_topic_and_data(self, topic, data):
        # Resolve topic to event class.
        domain_event_class = resolve_topic(topic)

        # Decrypt data.
        if self.cipher:
            data = self.cipher.decrypt(data)

        # Deserialize data.
        event_attrs = json_loads(data, cls=self.json_decoder_class)

        # Reconstruct domain event object.
        return reconstruct_object(domain_event_class, event_attrs)
 def test_topic_resolution_error(self):
     # Check topic resolution error is raised, if the module path is
     # broken, and if the class name is broken.
     resolve_topic("eventsourcing.domain.model.events#DomainEvent")
     with self.assertRaises(TopicResolutionError):
         resolve_topic("eventsourcing.domain.model.broken#DomainEvent")
     with self.assertRaises(TopicResolutionError):
         resolve_topic("eventsourcing.domain.model.events#Broken")
Beispiel #18
0
def example_policy(repository, event):
    # Whenever an aggregate is created, then "move it on".
    if isinstance(event, ExampleAggregate.Created):
        # Get aggregate and move it on.
        aggregate = repository[event.originator_id]

        assert isinstance(aggregate, ExampleAggregate)

        # Also create a second entity, allows test to check that
        # events from more than one entity are stored.
        second_id = uuid4()
        other_entity = AggregateRoot.__create__(originator_id=second_id)
        aggregate.move_on(second_id=second_id)
        return other_entity

    elif isinstance(event, Command.Created):
        command_class = resolve_topic(event.originator_topic)
        if command_class is CreateExample:
            return ExampleAggregate.__create__()
Beispiel #19
0
def example_policy(repository, event):
    if isinstance(event, ExampleAggregate.Created):
        # Create a second aggregate, allowing test to check that
        # events from more than one entity are stored.
        second_id = uuid4()
        second = AggregateRoot.__create__(originator_id=second_id)

        # Get first aggregate and move it on, allowing test to
        # check that the first aggregate was mutated by the policy.
        first = repository[event.originator_id]
        assert isinstance(first, ExampleAggregate)
        first.move_on(second_id=second_id)

        return second

    elif isinstance(event, Command.Created):
        command_class = resolve_topic(event.originator_topic)
        if command_class is CreateExample:
            return ExampleAggregate.__create__(event.example_id)
    def get_event_class_and_attrs(self, topic: str,
                                  state: bytes) -> Tuple[Type[TEvent], Dict]:
        # Resolve topic to event class.
        domain_event_class: Type[TEvent] = resolve_topic(topic)

        # Decrypt and decompress state.
        if self.cipher:
            state = self.cipher.decrypt(state)

        # Decompress plaintext bytes.
        if self.compressor:
            state = self.compressor.decompress(state)

        # Decode unicode bytes.
        statestr = state.decode("utf8")

        # Deserialize JSON.
        event_attrs: Dict = self.json_loads(statestr)

        # Return instance class and attribute values.
        return domain_event_class, event_attrs
Beispiel #21
0
    def __init__(
        self,
        application_topic,
        pipeline_id,
        infrastructure_topic,
        setup_table,
        address,
        upstreams,
        downstreams,
        push_prompt_interval,
    ):
        super(ProcessorServer, self).__init__()

        # Make getting notifications more efficient.
        notificationlog.USE_REGULAR_SECTIONS = False
        notificationlog.DEFAULT_SECTION_SIZE = 100

        self.has_been_stopped = Event()
        signal(SIGINT, self.stop)
        self.application_class: Type[ProcessApplication] = resolve_topic(
            application_topic)
        self.pipeline_id = pipeline_id
        self.application_name = self.application_class.create_name()
        infrastructure_class: Type[
            ApplicationWithConcreteInfrastructure] = resolve_topic(
                infrastructure_topic)
        self.application = self.application_class.mixin(
            infrastructure_class=infrastructure_class)(
                pipeline_id=self.pipeline_id, setup_table=setup_table)
        self.address = address
        self.json_encoder = ObjectJSONEncoder()
        self.json_decoder = ObjectJSONDecoder()
        self.upstreams = upstreams
        self.downstreams = downstreams
        self.prompt_events = {}
        self.push_prompt_interval = push_prompt_interval

        self.notification_log_view = NotificationLogView(
            self.application.notification_log,
            json_encoder=ObjectJSONEncoder(),
        )
        for upstream_name in self.upstreams:
            self.prompt_events[upstream_name] = Event()
            # self.prompt_events[upstream_name].set()

        self.downstream_prompt_event = Event()
        subscribe(self._set_downstream_prompt_event, is_prompt_to_pull)

        self.serve()

        self.clients: Dict[str, ProcessorClient] = {}
        self.clients_lock = Lock()
        start_client_threads = []
        remotes = {}
        remotes.update(self.upstreams)
        remotes.update(self.downstreams)
        for name, address in remotes.items():
            thread = StartClient(self.clients, name, address)
            thread.setDaemon(True)
            thread.start()
            start_client_threads.append(thread)
        for thread in start_client_threads:
            thread.join()
            # logging.info("%s connected to %s" % (self.application_name, thread.name))

        self.push_prompts_thread = Thread(target=self._push_prompts)
        self.push_prompts_thread.setDaemon(True)
        self.push_prompts_thread.start()

        # self.count_of_events = 0

        self.pull_notifications_threads = {}
        self.unprocessed_domain_event_queue = Queue()
        for upstream_name, upstream_address in self.upstreams.items():
            thread = PullNotifications(
                prompt_event=self.prompt_events[upstream_name],
                reader=NotificationLogReader(
                    RemoteNotificationLog(
                        client=self.clients[upstream_name],
                        json_decoder=ObjectJSONDecoder(),
                        section_size=self.application.notification_log.
                        section_size,
                    )),
                process_application=self.application,
                event_queue=self.unprocessed_domain_event_queue,
                upstream_name=upstream_name,
                has_been_stopped=self.has_been_stopped,
            )
            thread.setDaemon(True)
            self.pull_notifications_threads[upstream_name] = thread

        self.process_events_thread = Thread(target=self._process_events)
        self.process_events_thread.setDaemon(True)
        self.process_events_thread.start()

        # Start the threads.
        for thread in self.pull_notifications_threads.values():
            thread.start()

        # Wait for termination.
        self.wait_for_termination()
Beispiel #22
0
def decode_dict(d):
    topic = d["__dict__"]["topic"]
    state = d["__dict__"]["state"]
    dict_type = resolve_topic(topic)
    return dict_type(state)
Beispiel #23
0
def decode_deque(d):
    topic = d["__deque__"]["topic"]
    values = d["__deque__"]["values"]
    deque = resolve_topic(topic)
    return deque(values)
Beispiel #24
0
 def get_event_class_and_attrs(self, topic: str,
                               state: bytes) -> Tuple[Type[TEvent], Dict]:
     return resolve_topic(topic), state  # type: ignore
Beispiel #25
0
def decode_enum(d):
    topic = d["__enum__"]["topic"]
    name = d["__enum__"]["name"]
    enum = resolve_topic(topic)
    return getattr(enum, name)
Beispiel #26
0
def decode_type(d):
    return resolve_topic(d["__type__"])
Beispiel #27
0
 def __mutate__(self, entity_class=None):
     if entity_class is None:
         entity_class = resolve_topic(self.originator_topic)
     return entity_class(**self.__entity_kwargs__)
Beispiel #28
0
 def __mutate__(self, obj: Optional[TEntity]) -> Optional[TEntity]:
     if self.state is not None:
         entity_class = resolve_topic(self.topic)
         return reconstruct_object(entity_class, self.state)