コード例 #1
0
    def test_upsert_on_index_elements_mismatch(self):
        """
        Events with a duplicate index elements cannot be upsert if they don't match.

        """
        with transaction():
            created_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                task_id=self.task.id,
            )
            self.store.create(created_event)
            task_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                parent_id=created_event.id,
                task_id=self.task.id,
            )
            self.store.create(task_event)

        assert_that(
            calling(self.store.upsert_on_index_elements).with_args(
                TaskEvent(
                    event_type=TaskEventType.REVISED,
                    parent_id=created_event.id,
                    task_id=self.task.id,
                )),
            raises(ConcurrentStateConflictError),
        )
コード例 #2
0
    def test_column_alias(self):
        assert_that(TaskEvent.container_id, is_(equal_to(TaskEvent.task_id)))

        task_event = TaskEvent()
        task_event.container_id = self.task.id
        assert_that(task_event.container_id, is_(equal_to(self.task.id)))
        assert_that(task_event.task_id, is_(equal_to(self.task.id)))
コード例 #3
0
    def test_unique_parent_id(self):
        """
        Events are unique per parent.

        """
        with transaction():
            created_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                task_id=self.task.id,
            )
            self.store.create(created_event)
            task_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                parent_id=created_event.id,
                task_id=self.task.id,
            )
            self.store.create(task_event)

        assert_that(
            calling(self.store.create).with_args(
                TaskEvent(
                    event_type=TaskEventType.CREATED,
                    parent_id=created_event.id,
                    task_id=self.task.id,
                ), ),
            raises(DuplicateModelError),
        )
コード例 #4
0
    def test_upsert_on_index_elements(self):
        """
        Events with a duplicate index elements can be upserted.

        """
        with transaction():
            created_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                task_id=self.task.id,
            )
            self.store.create(created_event)
            task_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                parent_id=created_event.id,
                task_id=self.task.id,
            )
            self.store.create(task_event)

        upserted = self.store.upsert_on_index_elements(
            TaskEvent(
                event_type=TaskEventType.CREATED,
                parent_id=created_event.id,
                task_id=self.task.id,
            ))

        assert_that(task_event.id, is_(equal_to(upserted.id)))
コード例 #5
0
    def iter_events(self):
        """
        Walk through the event state machine.

        """
        created = TaskEvent(
            event_type=TaskEventType.CREATED,
            state=[TaskEventType.CREATED],
            task_id=self.task.id,
        ).create()
        yield created

        assigned = TaskEvent(
            assignee="Alice",
            event_type=TaskEventType.ASSIGNED,
            parent_id=created.id,
            state=[TaskEventType.CREATED, TaskEventType.ASSIGNED],
            task_id=self.task.id,
        ).create()
        yield assigned

        scheduled = TaskEvent(
            deadline=datetime.utcnow(),
            event_type=TaskEventType.SCHEDULED,
            parent_id=assigned.id,
            state=[
                TaskEventType.CREATED, TaskEventType.ASSIGNED,
                TaskEventType.SCHEDULED
            ],
            task_id=self.task.id,
        ).create()
        yield scheduled

        started = TaskEvent(
            event_type=TaskEventType.STARTED,
            parent_id=scheduled.id,
            state=[TaskEventType.STARTED],
            task_id=self.task.id,
        ).create()
        yield started

        reassigned = TaskEvent(
            assignee="Bob",
            event_type=TaskEventType.REASSIGNED,
            parent_id=started.id,
            state=[TaskEventType.STARTED],
            task_id=self.task.id,
        ).create()
        yield reassigned
コード例 #6
0
    def test_retrieve_with_update_lock_exception(self):
        with transaction():
            created_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                task_id=self.task.id,
            )
            self.store.create(created_event)

        with patch.object(Query, 'with_for_update') as mocked_with_for_update:
            mocked_with_for_update.side_effect = OperationalError(
                statement="",
                params="",
                orig=psycopg2.errors.LockNotAvailable())

            assert_that(
                calling(self.store.retrieve_most_recent_with_update_lock).
                with_args(task_id=self.task.id, ),
                raises(ContainerLockNotAvailableRetry),
            )

        with patch.object(Query, 'with_for_update') as mocked_with_for_update:
            mocked_with_for_update.side_effect = Exception()

            assert_that(
                calling(self.store.retrieve_most_recent_with_update_lock).
                with_args(task_id=self.task.id, ),
                raises(Exception),
            )
コード例 #7
0
    def setup(self):
        self.graph = create_object_graph(
            "microcosm_eventsource",
            root_path=join(dirname(__file__), pardir),
            testing=True,
        )
        self.graph.use(
            "task_store",
            "task_event_store",
            "activity_store",
            "activity_event_store",
        )
        self.store = self.graph.task_event_store
        self.activity_store = self.graph.activity_event_store

        self.context = SessionContext(self.graph)
        self.context.recreate_all()
        self.context.open()

        with transaction():
            self.task = Task().create()
            self.created_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                task_id=self.task.id,
            ).create()
            self.scheduled_event = TaskEvent(
                deadline=datetime.utcnow(),
                event_type=TaskEventType.SCHEDULED,
                parent_id=self.created_event.id,
                state=[TaskEventType.CREATED, TaskEventType.SCHEDULED],
                task_id=self.task.id,
            ).create()
            self.assigned_event = TaskEvent(
                deadline=datetime.utcnow(),
                event_type=TaskEventType.ASSIGNED,
                parent_id=self.scheduled_event.id,
                state=[TaskEventType.ASSIGNED, TaskEventType.CREATED, TaskEventType.SCHEDULED],
                assignee="assignee",
                task_id=self.task.id,
            ).create()
            self.started_event = TaskEvent(
                event_type=TaskEventType.STARTED,
                parent_id=self.assigned_event.id,
                task_id=self.task.id,
            ).create()
            # flush sqlalchemy cache before sql operation
            self.store.session.expire_all()
コード例 #8
0
    def setup(self):
        self.graph = create_object_graph(
            "microcosm_eventsource",
            root_path=dirname(__file__),
            testing=True,
        )
        self.graph.use(
            "task_store",
            "task_event_store",
            "activity_store",
            "activity_event_store",
        )

        self.context = SessionContext(self.graph)
        self.context.recreate_all()
        self.context.open()

        with transaction():
            self.task = Task().create()
            self.created_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                task_id=self.task.id,
            ).create()
            self.assigned_event = TaskEvent(
                assignee="Alice",
                event_type=TaskEventType.ASSIGNED,
                parent_id=self.created_event.id,
                task_id=self.task.id,
            ).create()
            self.started_event = TaskEvent(
                event_type=TaskEventType.STARTED,
                parent_id=self.assigned_event.id,
                task_id=self.task.id,
            ).create()
            self.reassigned_event = TaskEvent(
                assignee="Bob",
                event_type=TaskEventType.REASSIGNED,
                parent_id=self.started_event.id,
                task_id=self.task.id,
            ).create()
            self.reassigned_event = TaskEvent(
                event_type=TaskEventType.COMPLETED,
                parent_id=self.reassigned_event.id,
                task_id=self.task.id,
            ).create()
コード例 #9
0
 def test_retrieve_with_update_lock(self):
     with transaction():
         created_event = TaskEvent(
             event_type=TaskEventType.CREATED,
             task_id=self.task.id,
         )
         self.store.create(created_event)
     assert_that(
         self.store.retrieve_most_recent_with_update_lock(
             task_id=self.task.id),
         is_(equal_to(created_event)),
     )
コード例 #10
0
    def test_non_initial_event_requires_parent_id(self):
        """
        A non-initial event must have a previous event.

        """
        task_event = TaskEvent(
            event_type=TaskEventType.STARTED,
            task_id=self.task.id,
        )
        assert_that(
            calling(self.store.create).with_args(task_event),
            raises(ModelIntegrityError),
        )
コード例 #11
0
    def test_retrieve_most_recent(self):
        """
        The logical clock provides a total ordering on the main foreign key.

        """
        with transaction():
            created_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                task_id=self.task.id,
            )
            self.store.create(created_event)
            assigned_event = TaskEvent(
                assignee="Alice",
                event_type=TaskEventType.ASSIGNED,
                parent_id=created_event.id,
                task_id=self.task.id,
            )
            self.store.create(assigned_event)

        assert_that(
            self.store.retrieve_most_recent(task_id=self.task.id),
            is_(equal_to(assigned_event)),
        )
コード例 #12
0
    def test_multi_valued_state(self):
        """
        A state can contain multiple values.

        """
        with transaction():
            task_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                state=(TaskEventType.CREATED, TaskEventType.ASSIGNED),
                task_id=self.task.id,
            )
            self.store.create(task_event)

        assert_that(
            task_event.state,
            contains_inanyorder(TaskEventType.ASSIGNED, TaskEventType.CREATED),
        )
コード例 #13
0
    def test_create_retrieve(self):
        """
        An event can be retrieved after it is created.

        """
        with transaction():
            task_event = TaskEvent(
                event_type=TaskEventType.CREATED,
                task_id=self.task.id,
            )
            self.store.create(task_event)

        assert_that(task_event.clock, is_(equal_to(1)))
        assert_that(task_event.parent_id, is_(none()))
        assert_that(task_event.state, contains(TaskEventType.CREATED))
        assert_that(task_event.version, is_(equal_to(1)))

        assert_that(
            self.store.retrieve(task_event.id),
            is_(equal_to(task_event)),
        )