From 51817cf373ea364e45ebee111d2e8785e0c750ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 20 Apr 2022 10:17:03 +0200 Subject: [PATCH 01/75] ISSUE #64 * Remove the dependency to the `event_offset` value of transactions on the snapshot's synchronization step. --- .../snapshots/repositories/database/impl.py | 33 ++++++++++++------- .../transactions/repositories/factories.py | 7 ++-- .../transactions/repositories/abc.py | 7 ++-- .../repositories/database/factories/abc.py | 7 ++-- .../aiopg/factories/aggregate/transactions.py | 2 +- 5 files changed, 38 insertions(+), 18 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py index 2f80ae02b..b1b7554ee 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py @@ -5,6 +5,9 @@ from collections.abc import ( AsyncIterator, ) +from contextlib import ( + suppress, +) from typing import ( TYPE_CHECKING, Optional, @@ -134,16 +137,16 @@ async def is_synced(self, name: str, **kwargs) -> bool: async def _synchronize(self, **kwargs) -> None: initial_offset = await self._load_offset() + transaction_uuids = set() offset = initial_offset async for event_entry in self._event_repository.select(id_gt=offset, **kwargs): - try: + with suppress(SnapshotRepositoryConflictException): await self._dispatch_one(event_entry, **kwargs) - except SnapshotRepositoryConflictException: - pass + offset = max(event_entry.id, offset) + transaction_uuids.add(event_entry.transaction_uuid) - if initial_offset < offset: - await self._clean_transactions(initial_offset) + await self._clean_transactions(transaction_uuids) await self._store_offset(offset) @@ -217,11 +220,19 @@ async def _submit_entry(self, snapshot_entry: SnapshotEntry) -> SnapshotEntry: return snapshot_entry - async def _clean_transactions(self, offset: int, **kwargs) -> None: + async def _clean_transactions(self, uuids: set[UUID], **kwargs) -> None: + if not len(uuids): + return + iterable = self._transaction_repository.select( - event_offset_gt=offset, status_in=(TransactionStatus.COMMITTED, TransactionStatus.REJECTED), **kwargs + uuid_in=uuids, + status_in=(TransactionStatus.COMMITTED, TransactionStatus.REJECTED), + **kwargs, ) - transaction_uuids = {transaction.uuid async for transaction in iterable} - if len(transaction_uuids): - operation = self.database_operation_factory.build_delete(transaction_uuids) - await self.execute_on_database(operation) + uuids = {transaction.uuid async for transaction in iterable} + + if not len(uuids): + return + + operation = self.database_operation_factory.build_delete(uuids) + await self.execute_on_database(operation) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/factories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/factories.py index 5be8648d4..4bdfeeea3 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/factories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/factories.py @@ -1,3 +1,6 @@ +from collections.abc import ( + Iterable, +) from datetime import ( datetime, ) @@ -39,10 +42,10 @@ def build_query( self, uuid: Optional[UUID] = None, uuid_ne: Optional[UUID] = None, - uuid_in: Optional[tuple[UUID]] = None, + uuid_in: Optional[Iterable[UUID]] = None, destination_uuid: Optional[UUID] = None, status: Optional[str] = None, - status_in: Optional[tuple[str]] = None, + status_in: Optional[Iterable[str]] = None, event_offset: Optional[int] = None, event_offset_lt: Optional[int] = None, event_offset_gt: Optional[int] = None, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py index 6149b96fa..36a686afe 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py @@ -6,6 +6,9 @@ ABC, abstractmethod, ) +from collections.abc import ( + Iterable, +) from datetime import ( datetime, ) @@ -83,10 +86,10 @@ async def select( self, uuid: Optional[UUID] = None, uuid_ne: Optional[UUID] = None, - uuid_in: Optional[tuple[UUID, ...]] = None, + uuid_in: Optional[Iterable[UUID]] = None, destination_uuid: Optional[UUID] = None, status: Optional[TransactionStatus] = None, - status_in: Optional[tuple[str, ...]] = None, + status_in: Optional[Iterable[str]] = None, event_offset: Optional[int] = None, event_offset_lt: Optional[int] = None, event_offset_gt: Optional[int] = None, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/factories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/factories/abc.py index 5171be2b6..e7cb1bbe7 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/factories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/factories/abc.py @@ -6,6 +6,9 @@ ABC, abstractmethod, ) +from collections.abc import ( + Iterable, +) from datetime import ( datetime, ) @@ -57,10 +60,10 @@ def build_query( self, uuid: Optional[UUID] = None, uuid_ne: Optional[UUID] = None, - uuid_in: Optional[tuple[UUID]] = None, + uuid_in: Optional[Iterable[UUID]] = None, destination_uuid: Optional[UUID] = None, status: Optional[str] = None, - status_in: Optional[tuple[str]] = None, + status_in: Optional[Iterable[str]] = None, event_offset: Optional[int] = None, event_offset_lt: Optional[int] = None, event_offset_gt: Optional[int] = None, diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/transactions.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/transactions.py index d98ecfe08..b0d2830f1 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/transactions.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/transactions.py @@ -32,7 +32,7 @@ ) -# noinspection SqlNoDataSourceInspection,SqlResolve,PyMethodMayBeStatic +# noinspection SqlNoDataSourceInspection,SqlResolve,PyMethodMayBeStatic,SqlDialectInspection class AiopgTransactionDatabaseOperationFactory(TransactionDatabaseOperationFactory): """Aiopg Transaction Database Operation Factory class.""" From c85fc9709fd7943a19e59890b45c1f4152752240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 20 Apr 2022 11:18:57 +0200 Subject: [PATCH 02/75] ISSUE #64 * Remove `event_offset` attribute from `TransactionEntry`. --- .../snapshots/repositories/testcases.py | 16 +-- .../transactions/repositories/factories.py | 7 +- .../transactions/repositories/testcases.py | 122 +++++++----------- .../minos/aggregate/transactions/entries.py | 25 ++-- .../transactions/repositories/abc.py | 15 --- .../repositories/database/factories.py | 13 +- .../transactions/repositories/memory.py | 16 --- .../test_transactions/test_entries.py | 44 +++---- .../test_repositories/test_abc.py | 7 +- .../test_repositories/test_database.py | 51 +------- .../aiopg/factories/aggregate/transactions.py | 41 +----- .../test_transactions/test_factory.py | 6 - 12 files changed, 86 insertions(+), 277 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py index edf0dc10b..2fd005412 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py @@ -104,19 +104,11 @@ async def populate(self) -> None: await self.event_repository.delete( EventEntry(self.uuid_2, name, 3, bytes(), transaction_uuid=self.transaction_3) ) + await self.transaction_repository.submit(TransactionEntry(self.transaction_1, TransactionStatus.PENDING)) + await self.transaction_repository.submit(TransactionEntry(self.transaction_2, TransactionStatus.PENDING)) + await self.transaction_repository.submit(TransactionEntry(self.transaction_3, TransactionStatus.REJECTED)) await self.transaction_repository.submit( - TransactionEntry(self.transaction_1, TransactionStatus.PENDING, await self.event_repository.offset) - ) - await self.transaction_repository.submit( - TransactionEntry(self.transaction_2, TransactionStatus.PENDING, await self.event_repository.offset) - ) - await self.transaction_repository.submit( - TransactionEntry(self.transaction_3, TransactionStatus.REJECTED, await self.event_repository.offset) - ) - await self.transaction_repository.submit( - TransactionEntry( - self.transaction_4, TransactionStatus.REJECTED, await self.event_repository.offset, self.transaction_3 - ) + TransactionEntry(self.transaction_4, TransactionStatus.REJECTED, self.transaction_3) ) async def populate_and_synchronize(self): diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/factories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/factories.py index 4bdfeeea3..eef9e3564 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/factories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/factories.py @@ -33,7 +33,7 @@ def build_create(self) -> DatabaseOperation: return MockedDatabaseOperation("create") def build_submit( - self, uuid: UUID, destination_uuid: UUID, status: TransactionStatus, event_offset: int, **kwargs + self, uuid: UUID, destination_uuid: UUID, status: TransactionStatus, **kwargs ) -> DatabaseOperation: """For testing purposes.""" return MockedDatabaseOperation("submit") @@ -46,11 +46,6 @@ def build_query( destination_uuid: Optional[UUID] = None, status: Optional[str] = None, status_in: Optional[Iterable[str]] = None, - event_offset: Optional[int] = None, - event_offset_lt: Optional[int] = None, - event_offset_gt: Optional[int] = None, - event_offset_le: Optional[int] = None, - event_offset_ge: Optional[int] = None, updated_at: Optional[datetime] = None, updated_at_lt: Optional[datetime] = None, updated_at_gt: Optional[datetime] = None, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/testcases.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/testcases.py index 8276bbf85..c5257bb1d 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/testcases.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/testcases.py @@ -33,21 +33,19 @@ def setUp(self) -> None: self.uuid_5 = uuid4() self.entries = [ - TransactionEntry(self.uuid_1, TransactionStatus.PENDING, 12), - TransactionEntry(self.uuid_2, TransactionStatus.PENDING, 15), - TransactionEntry(self.uuid_3, TransactionStatus.REJECTED, 16), - TransactionEntry(self.uuid_4, TransactionStatus.COMMITTED, 20), - TransactionEntry(self.uuid_5, TransactionStatus.PENDING, 20, self.uuid_1), + TransactionEntry(self.uuid_1, TransactionStatus.PENDING), + TransactionEntry(self.uuid_2, TransactionStatus.PENDING), + TransactionEntry(self.uuid_3, TransactionStatus.REJECTED), + TransactionEntry(self.uuid_4, TransactionStatus.COMMITTED), + TransactionEntry(self.uuid_5, TransactionStatus.PENDING, self.uuid_1), ] async def populate(self) -> None: - await self.transaction_repository.submit(TransactionEntry(self.uuid_1, TransactionStatus.PENDING, 12)) - await self.transaction_repository.submit(TransactionEntry(self.uuid_2, TransactionStatus.PENDING, 15)) - await self.transaction_repository.submit(TransactionEntry(self.uuid_3, TransactionStatus.REJECTED, 16)) - await self.transaction_repository.submit(TransactionEntry(self.uuid_4, TransactionStatus.COMMITTED, 20)) - await self.transaction_repository.submit( - TransactionEntry(self.uuid_5, TransactionStatus.PENDING, 20, self.uuid_1) - ) + await self.transaction_repository.submit(TransactionEntry(self.uuid_1, TransactionStatus.PENDING)) + await self.transaction_repository.submit(TransactionEntry(self.uuid_2, TransactionStatus.PENDING)) + await self.transaction_repository.submit(TransactionEntry(self.uuid_3, TransactionStatus.REJECTED)) + await self.transaction_repository.submit(TransactionEntry(self.uuid_4, TransactionStatus.COMMITTED)) + await self.transaction_repository.submit(TransactionEntry(self.uuid_5, TransactionStatus.PENDING, self.uuid_1)) async def asyncSetUp(self): await super().asyncSetUp() @@ -68,82 +66,82 @@ async def test_subclass(self) -> None: self.assertTrue(isinstance(self.transaction_repository, TransactionRepository)) async def test_submit(self): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING, 34)) - expected = [TransactionEntry(self.uuid, TransactionStatus.PENDING, 34)] + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING)) + expected = [TransactionEntry(self.uuid, TransactionStatus.PENDING)] observed = [v async for v in self.transaction_repository.select()] self.assertEqual(expected, observed) async def test_submit_pending_raises(self): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED)) async def test_submit_reserving_raises(self): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED)) async def test_submit_reserved_raises(self): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED)) async def test_submit_committing_raises(self): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.REJECTED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.REJECTED)) async def test_submit_committed_raises(self): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.REJECTED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.REJECTED)) async def test_submit_rejected_raises(self): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.REJECTED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.REJECTED)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.PENDING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.RESERVED)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTING, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTING)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.COMMITTED)) with self.assertRaises(TransactionRepositoryConflictException): - await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.REJECTED, 34)) + await self.transaction_repository.submit(TransactionEntry(self.uuid, TransactionStatus.REJECTED)) async def test_select_empty(self): expected = [] @@ -197,36 +195,6 @@ async def test_select_status_in(self): ] self.assertEqual(expected, observed) - async def test_select_event_offset(self): - await self.populate() - expected = [self.entries[1]] - observed = [v async for v in self.transaction_repository.select(event_offset=15)] - self.assertEqual(expected, observed) - - async def test_select_event_offset_lt(self): - await self.populate() - expected = [self.entries[0]] - observed = [v async for v in self.transaction_repository.select(event_offset_lt=15)] - self.assertEqual(expected, observed) - - async def test_select_event_offset_gt(self): - await self.populate() - expected = [self.entries[2], self.entries[3], self.entries[4]] - observed = [v async for v in self.transaction_repository.select(event_offset_gt=15)] - self.assertEqual(expected, observed) - - async def test_select_event_offset_le(self): - await self.populate() - expected = [self.entries[0], self.entries[1]] - observed = [v async for v in self.transaction_repository.select(event_offset_le=15)] - self.assertEqual(expected, observed) - - async def test_select_event_offset_ge(self): - await self.populate() - expected = [self.entries[1], self.entries[2], self.entries[3], self.entries[4]] - observed = [v async for v in self.transaction_repository.select(event_offset_ge=15)] - self.assertEqual(expected, observed) - async def test_select_updated_at(self): await self.populate() updated_at = (await self.transaction_repository.get(self.uuid_3)).updated_at diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py index d883c2410..94b5f9213 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py @@ -57,7 +57,6 @@ class TransactionEntry: __slots__ = ( "uuid", "status", - "event_offset", "destination_uuid", "updated_at", "_autocommit", @@ -70,7 +69,6 @@ def __init__( self, uuid: Optional[UUID] = None, status: Union[str, TransactionStatus] = None, - event_offset: Optional[int] = None, destination_uuid: Optional[UUID] = None, updated_at: Optional[datetime] = None, autocommit: bool = True, @@ -108,7 +106,6 @@ def __init__( self.uuid = uuid self.status = status - self.event_offset = event_offset self.destination_uuid = destination_uuid self.updated_at = updated_at @@ -152,8 +149,7 @@ async def commit(self) -> None: async with self._transaction_repository.write_lock(): await self.save(status=TransactionStatus.COMMITTING) await self._commit() - event_offset = 1 + await self._event_repository.offset - await self.save(event_offset=event_offset, status=TransactionStatus.COMMITTED) + await self.save(status=TransactionStatus.COMMITTED) async def _commit(self) -> None: from ..events import ( @@ -179,10 +175,11 @@ async def reserve(self) -> None: committable = await self.validate() status = TransactionStatus.RESERVED if committable else TransactionStatus.REJECTED - event_offset = 1 + await self._event_repository.offset - await self.save(event_offset=event_offset, status=status) + await self.save(status=status) if not committable: - raise EventRepositoryConflictException(f"{self!r} could not be reserved!", event_offset) + raise EventRepositoryConflictException( + f"{self!r} could not be reserved!", await self._event_repository.offset + ) async def validate(self) -> bool: """Check if the transaction is committable. @@ -248,19 +245,15 @@ async def reject(self) -> None: ) async with self._transaction_repository.write_lock(): - event_offset = 1 + await self._event_repository.offset - await self.save(event_offset=event_offset, status=TransactionStatus.REJECTED) + await self.save(status=TransactionStatus.REJECTED) - async def save(self, *, event_offset: Optional[int] = None, status: Optional[TransactionStatus] = None) -> None: + async def save(self, *, status: Optional[TransactionStatus] = None) -> None: """Saves the transaction into the repository. - :param event_offset: The event offset. :param status: The status. :return: This method does not return anything. """ - if event_offset is not None: - self.event_offset = event_offset if status is not None: self.status = status @@ -307,13 +300,12 @@ def __iter__(self) -> Iterable: yield from ( self.uuid, self.status, - self.event_offset, self.destination_uuid, ) def __repr__(self): return ( - f"{type(self).__name__}(uuid={self.uuid!r}, status={self.status!r}, event_offset={self.event_offset!r}, " + f"{type(self).__name__}(uuid={self.uuid!r}, status={self.status!r}, " f"destination_uuid={self.destination_uuid!r}, updated_at={self.updated_at!r})" ) @@ -325,7 +317,6 @@ def as_raw(self) -> dict[str, Any]: return { "uuid": self.uuid, "status": self.status, - "event_offset": self.event_offset, "destination_uuid": self.destination_uuid, "updated_at": self.updated_at, } diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py index 36a686afe..5521cb2a5 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py @@ -90,11 +90,6 @@ async def select( destination_uuid: Optional[UUID] = None, status: Optional[TransactionStatus] = None, status_in: Optional[Iterable[str]] = None, - event_offset: Optional[int] = None, - event_offset_lt: Optional[int] = None, - event_offset_gt: Optional[int] = None, - event_offset_le: Optional[int] = None, - event_offset_ge: Optional[int] = None, updated_at: Optional[datetime] = None, updated_at_lt: Optional[datetime] = None, updated_at_gt: Optional[datetime] = None, @@ -110,11 +105,6 @@ async def select( :param destination_uuid: Destination Transaction identifier equal to the given value. :param status: Transaction status equal to the given value. :param status_in: Transaction status within the given values - :param event_offset: Event offset equal to the given value. - :param event_offset_lt: Event Offset lower than the given value - :param event_offset_gt: Event Offset greater than the given value - :param event_offset_le: Event Offset lower or equal to the given value - :param event_offset_ge: Event Offset greater or equal to the given value :param updated_at: Updated at equal to the given value. :param updated_at_lt: Updated at lower than the given value. :param updated_at_gt: Updated at greater than the given value. @@ -130,11 +120,6 @@ async def select( destination_uuid=destination_uuid, status=status, status_in=status_in, - event_offset=event_offset, - event_offset_lt=event_offset_lt, - event_offset_gt=event_offset_gt, - event_offset_le=event_offset_le, - event_offset_ge=event_offset_ge, updated_at=updated_at, updated_at_lt=updated_at_lt, updated_at_gt=updated_at_gt, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/factories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/factories.py index 76be162b7..cf35c8933 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/factories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/factories.py @@ -43,14 +43,13 @@ def build_create(self) -> DatabaseOperation: @abstractmethod def build_submit( - self, uuid: UUID, destination_uuid: UUID, status: TransactionStatus, event_offset: int, **kwargs + self, uuid: UUID, destination_uuid: UUID, status: TransactionStatus, **kwargs ) -> DatabaseOperation: """Build the database operation to submit a row. :param uuid: The identifier of the transaction. :param destination_uuid: The identifier of the destination transaction. :param status: The status of the transaction. - :param event_offset: The event offset of the transaction. :param kwargs: Additional named arguments. :return: A ``DatabaseOperation`` instance. """ @@ -64,11 +63,6 @@ def build_query( destination_uuid: Optional[UUID] = None, status: Optional[str] = None, status_in: Optional[Iterable[str]] = None, - event_offset: Optional[int] = None, - event_offset_lt: Optional[int] = None, - event_offset_gt: Optional[int] = None, - event_offset_le: Optional[int] = None, - event_offset_ge: Optional[int] = None, updated_at: Optional[datetime] = None, updated_at_lt: Optional[datetime] = None, updated_at_gt: Optional[datetime] = None, @@ -84,11 +78,6 @@ def build_query( :param destination_uuid: Destination Transaction identifier equal to the given value. :param status: Transaction status equal to the given value. :param status_in: Transaction status within the given values - :param event_offset: Event offset equal to the given value. - :param event_offset_lt: Event Offset lower than the given value - :param event_offset_gt: Event Offset greater than the given value - :param event_offset_le: Event Offset lower or equal to the given value - :param event_offset_ge: Event Offset greater or equal to the given value :param updated_at: Updated at equal to the given value. :param updated_at_lt: Updated at lower than the given value. :param updated_at_gt: Updated at greater than the given value. diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py index a74560420..3795aca29 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py @@ -53,7 +53,6 @@ async def _submit(self, transaction: TransactionEntry) -> TransactionEntry: uuid=transaction.uuid, destination_uuid=transaction.destination_uuid, status=transaction.status, - event_offset=transaction.event_offset, updated_at=transaction.updated_at, event_repository=transaction._event_repository, transaction_repository=transaction._transaction_repository, @@ -69,11 +68,6 @@ async def _select( destination_uuid: Optional[UUID] = None, status: Optional[s] = None, status_in: Optional[tuple[str, ...]] = None, - event_offset: Optional[int] = None, - event_offset_lt: Optional[int] = None, - event_offset_gt: Optional[int] = None, - event_offset_le: Optional[int] = None, - event_offset_ge: Optional[int] = None, updated_at: Optional[datetime] = None, updated_at_lt: Optional[datetime] = None, updated_at_gt: Optional[datetime] = None, @@ -96,16 +90,6 @@ def _fn_filter(transaction: TransactionEntry) -> bool: return False if status_in is not None and transaction.status not in status_in: return False - if event_offset is not None and event_offset != transaction.event_offset: - return False - if event_offset_lt is not None and event_offset_lt <= transaction.event_offset: - return False - if event_offset_gt is not None and event_offset_gt >= transaction.event_offset: - return False - if event_offset_le is not None and event_offset_le < transaction.event_offset: - return False - if event_offset_ge is not None and event_offset_ge > transaction.event_offset: - return False if updated_at is not None and updated_at != transaction.updated_at: return False if updated_at_lt is not None and updated_at_lt <= transaction.updated_at: diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py index ef8f2d75b..75fddc90f 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py @@ -37,7 +37,6 @@ def test_constructor(self): self.assertIsInstance(transaction.uuid, UUID) self.assertEqual(TransactionStatus.PENDING, transaction.status) - self.assertEqual(None, transaction.event_offset) self.assertEqual(True, transaction._autocommit) self.assertEqual(self.event_repository, transaction._event_repository) @@ -46,11 +45,9 @@ def test_constructor(self): def test_constructor_extended(self): uuid = uuid4() status = TransactionStatus.PENDING - event_offset = 56 - transaction = TransactionEntry(uuid, status, event_offset, autocommit=False) + transaction = TransactionEntry(uuid, status, autocommit=False) self.assertEqual(uuid, transaction.uuid) self.assertEqual(status, transaction.status) - self.assertEqual(event_offset, transaction.event_offset) self.assertEqual(False, transaction._autocommit) self.assertEqual(self.event_repository, transaction._event_repository) @@ -125,7 +122,7 @@ async def test_reserve_success(self) -> None: self.assertEqual(call(), validate_mock.call_args) self.assertEqual( - [call(status=TransactionStatus.RESERVING), call(event_offset=56, status=TransactionStatus.RESERVED)], + [call(status=TransactionStatus.RESERVING), call(status=TransactionStatus.RESERVED)], save_mock.call_args_list, ) @@ -145,7 +142,7 @@ async def test_reserve_failure(self) -> None: self.assertEqual(call(), validate_mock.call_args) self.assertEqual( - [call(status=TransactionStatus.RESERVING), call(event_offset=56, status=TransactionStatus.REJECTED)], + [call(status=TransactionStatus.RESERVING), call(status=TransactionStatus.REJECTED)], save_mock.call_args_list, ) @@ -389,7 +386,7 @@ async def test_reject(self) -> None: await transaction.reject() self.assertEqual(1, save_mock.call_count) - self.assertEqual(call(event_offset=56, status=TransactionStatus.REJECTED), save_mock.call_args) + self.assertEqual(call(status=TransactionStatus.REJECTED), save_mock.call_args) async def test_reject_raises(self) -> None: with self.assertRaises(ValueError): @@ -430,7 +427,7 @@ async def _fn(*args, **kwargs): ) self.assertEqual( - [call(status=TransactionStatus.COMMITTING), call(event_offset=56, status=TransactionStatus.COMMITTED)], + [call(status=TransactionStatus.COMMITTING), call(status=TransactionStatus.COMMITTED)], save_mock.call_args_list, ) @@ -457,7 +454,7 @@ async def _fn(): self.assertEqual(call(), commit_mock.call_args) self.assertEqual( - [call(status=TransactionStatus.COMMITTING), call(event_offset=56, status=TransactionStatus.COMMITTED)], + [call(status=TransactionStatus.COMMITTING), call(status=TransactionStatus.COMMITTED)], save_mock.call_args_list, ) @@ -481,10 +478,10 @@ async def test_save(self) -> None: self.assertEqual(1, submit_mock.call_count) self.assertEqual(call(TransactionEntry(uuid, TransactionStatus.COMMITTED)), submit_mock.call_args) - submit_mock.reset_mock() - await TransactionEntry(uuid, TransactionStatus.PENDING).save(event_offset=56) - self.assertEqual(1, submit_mock.call_count) - self.assertEqual(call(TransactionEntry(uuid, TransactionStatus.PENDING, 56)), submit_mock.call_args) + # submit_mock.reset_mock() + # await TransactionEntry(uuid, TransactionStatus.PENDING).save(event_offset=56) + # self.assertEqual(1, submit_mock.call_count) + # self.assertEqual(call(TransactionEntry(uuid, TransactionStatus.PENDING, 56)), submit_mock.call_args) async def test_uuids(self): first = TransactionEntry() @@ -504,24 +501,23 @@ async def test_destination(self): def test_equals(self): uuid = uuid4() - base = TransactionEntry(uuid, TransactionStatus.PENDING, 56) - self.assertEqual(TransactionEntry(uuid, TransactionStatus.PENDING, 56), base) - self.assertNotEqual(TransactionEntry(uuid4(), TransactionStatus.PENDING, 56), base) - self.assertNotEqual(TransactionEntry(uuid, TransactionStatus.COMMITTED, 56), base) - self.assertNotEqual(TransactionEntry(uuid, TransactionStatus.PENDING, 12), base) + base = TransactionEntry(uuid, TransactionStatus.PENDING) + self.assertEqual(TransactionEntry(uuid, TransactionStatus.PENDING), base) + self.assertNotEqual(TransactionEntry(uuid4(), TransactionStatus.PENDING), base) + self.assertNotEqual(TransactionEntry(uuid, TransactionStatus.COMMITTED), base) def test_iter(self): uuid = uuid4() destination_uuid = uuid4() - transaction = TransactionEntry(uuid, TransactionStatus.PENDING, 56, destination_uuid) - self.assertEqual([uuid, TransactionStatus.PENDING, 56, destination_uuid], list(transaction)) + transaction = TransactionEntry(uuid, TransactionStatus.PENDING, destination_uuid) + self.assertEqual([uuid, TransactionStatus.PENDING, destination_uuid], list(transaction)) def test_repr(self): uuid = uuid4() destination_uuid = uuid4() - transaction = TransactionEntry(uuid, TransactionStatus.PENDING, 56, destination_uuid) + transaction = TransactionEntry(uuid, TransactionStatus.PENDING, destination_uuid) expected = ( - f"TransactionEntry(uuid={uuid!r}, status={TransactionStatus.PENDING!r}, event_offset={56!r}, " + f"TransactionEntry(uuid={uuid!r}, status={TransactionStatus.PENDING!r}, " f"destination_uuid={destination_uuid!r}, updated_at={None!r})" ) self.assertEqual(expected, repr(transaction)) @@ -529,15 +525,13 @@ def test_repr(self): def test_as_raw(self): uuid = uuid4() status = TransactionStatus.PENDING - event_offset = 56 updated_at = datetime(2020, 10, 13, 8, 45, 32) destination_uuid = uuid4() - entry = TransactionEntry(uuid, status, event_offset, destination_uuid, updated_at) + entry = TransactionEntry(uuid, status, destination_uuid, updated_at) expected = { "uuid": uuid, "status": status, - "event_offset": event_offset, "destination_uuid": destination_uuid, "updated_at": updated_at, } diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py index 56f4013c5..5c8977ade 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py @@ -98,7 +98,7 @@ async def test_select(self): self.transaction_repository._select = mock iterable = self.transaction_repository.select( - uuid=uuid, status_in=(TransactionStatus.REJECTED, TransactionStatus.COMMITTED), event_offset_gt=56 + uuid=uuid, status_in=(TransactionStatus.REJECTED, TransactionStatus.COMMITTED) ) observed = [v async for v in iterable] @@ -111,11 +111,6 @@ async def test_select(self): destination_uuid=None, status=None, status_in=(TransactionStatus.REJECTED, TransactionStatus.COMMITTED), - event_offset=None, - event_offset_lt=None, - event_offset_gt=56, - event_offset_le=None, - event_offset_ge=None, updated_at=None, updated_at_lt=None, updated_at_gt=None, diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_database.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_database.py index f7900acff..b99fac437 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_database.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_database.py @@ -38,7 +38,7 @@ async def test_submit(self): with patch.object( DatabaseClient, "fetch_all", - return_value=FakeAsyncIterator([(self.uuid, TransactionStatus.PENDING, 34)]), + return_value=FakeAsyncIterator([(self.uuid, TransactionStatus.PENDING)]), ): await super().test_submit() @@ -213,55 +213,6 @@ async def test_select_status_in(self): ): await super().test_select_status_in() - async def test_select_event_offset(self): - with patch.object( - DatabaseClient, - "fetch_all", - return_value=FakeAsyncIterator([tuple(entry.as_raw().values()) for entry in [self.entries[1]]]), - ): - await super().test_select_event_offset() - - async def test_select_event_offset_lt(self): - with patch.object( - DatabaseClient, - "fetch_all", - return_value=FakeAsyncIterator([tuple(entry.as_raw().values()) for entry in [self.entries[0]]]), - ): - await super().test_select_event_offset_lt() - - async def test_select_event_offset_gt(self): - with patch.object( - DatabaseClient, - "fetch_all", - return_value=FakeAsyncIterator( - [tuple(entry.as_raw().values()) for entry in [self.entries[2], self.entries[3], self.entries[4]]] - ), - ): - await super().test_select_event_offset_gt() - - async def test_select_event_offset_le(self): - with patch.object( - DatabaseClient, - "fetch_all", - return_value=FakeAsyncIterator( - [tuple(entry.as_raw().values()) for entry in [self.entries[0], self.entries[1]]] - ), - ): - await super().test_select_event_offset_le() - - async def test_select_event_offset_ge(self): - with patch.object( - DatabaseClient, - "fetch_all", - return_value=FakeAsyncIterator( - [ - tuple(entry.as_raw().values()) - for entry in [self.entries[1], self.entries[2], self.entries[3], self.entries[4]] - ] - ), - ): - await super().test_select_event_offset_ge() - async def test_select_updated_at(self): with patch.object( DatabaseClient, diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/transactions.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/transactions.py index b0d2830f1..660855dc8 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/transactions.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/transactions.py @@ -82,7 +82,6 @@ def build_create(self) -> DatabaseOperation: uuid UUID PRIMARY KEY, destination_uuid UUID NOT NULL, status TRANSACTION_STATUS NOT NULL, - event_offset INTEGER, updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); """, @@ -96,7 +95,6 @@ def build_submit( uuid: UUID, destination_uuid: UUID, status: TransactionStatus, - event_offset: int, **kwargs, ) -> DatabaseOperation: """Build the database operation to submit a row. @@ -104,7 +102,6 @@ def build_submit( :param uuid: The identifier of the transaction. :param destination_uuid: The identifier of the destination transaction. :param status: The status of the transaction. - :param event_offset: The event offset of the transaction. :param kwargs: Additional named arguments. :return: A ``DatabaseOperation`` instance. """ @@ -113,16 +110,15 @@ def build_submit( "uuid": uuid, "destination_uuid": destination_uuid, "status": status, - "event_offset": event_offset, } return AiopgDatabaseOperation( f""" - INSERT INTO {self.build_table_name()} AS t (uuid, destination_uuid, status, event_offset) - VALUES (%(uuid)s, %(destination_uuid)s, %(status)s, %(event_offset)s) + INSERT INTO {self.build_table_name()} AS t (uuid, destination_uuid, status) + VALUES (%(uuid)s, %(destination_uuid)s, %(status)s) ON CONFLICT (uuid) DO - UPDATE SET status = %(status)s, event_offset = %(event_offset)s, updated_at = NOW() + UPDATE SET status = %(status)s, updated_at = NOW() WHERE (t.destination_uuid = %(destination_uuid)s) AND (NOT (t.status = 'pending' AND %(status)s NOT IN ('pending', 'reserving', 'rejected'))) AND (NOT (t.status = 'reserving' AND %(status)s NOT IN ('reserved', 'rejected'))) @@ -144,11 +140,6 @@ def build_query( destination_uuid: Optional[UUID] = None, status: Optional[str] = None, status_in: Optional[Iterable[str]] = None, - event_offset: Optional[int] = None, - event_offset_lt: Optional[int] = None, - event_offset_gt: Optional[int] = None, - event_offset_le: Optional[int] = None, - event_offset_ge: Optional[int] = None, updated_at: Optional[datetime] = None, updated_at_lt: Optional[datetime] = None, updated_at_gt: Optional[datetime] = None, @@ -164,11 +155,6 @@ def build_query( :param destination_uuid: Destination Transaction identifier equal to the given value. :param status: Transaction status equal to the given value. :param status_in: Transaction status within the given values - :param event_offset: Event offset equal to the given value. - :param event_offset_lt: Event Offset lower than the given value - :param event_offset_gt: Event Offset greater than the given value - :param event_offset_le: Event Offset lower or equal to the given value - :param event_offset_ge: Event Offset greater or equal to the given value :param updated_at: Updated at equal to the given value. :param updated_at_lt: Updated at lower than the given value. :param updated_at_gt: Updated at greater than the given value. @@ -197,16 +183,6 @@ def build_query( conditions.append("status = %(status)s") if status_in is not None: conditions.append("status IN %(status_in)s") - if event_offset is not None: - conditions.append("event_offset = %(event_offset)s") - if event_offset_lt is not None: - conditions.append("event_offset < %(event_offset_lt)s") - if event_offset_gt is not None: - conditions.append("event_offset > %(event_offset_gt)s") - if event_offset_le is not None: - conditions.append("event_offset <= %(event_offset_le)s") - if event_offset_ge is not None: - conditions.append("event_offset >= %(event_offset_ge)s") if updated_at is not None: conditions.append("updated_at = %(updated_at)s") if updated_at_lt is not None: @@ -219,15 +195,15 @@ def build_query( conditions.append("updated_at >= %(updated_at_ge)s") select_all = f""" - SELECT uuid, status, event_offset, destination_uuid, updated_at + SELECT uuid, status, destination_uuid, updated_at FROM {self.build_table_name()} """.strip() if not conditions: - return AiopgDatabaseOperation(f"{select_all} ORDER BY event_offset;") + return AiopgDatabaseOperation(f"{select_all} ORDER BY updated_at;") return AiopgDatabaseOperation( - f"{select_all} WHERE {' AND '.join(conditions)} ORDER BY event_offset;", + f"{select_all} WHERE {' AND '.join(conditions)} ORDER BY updated_at;", { "uuid": uuid, "uuid_ne": uuid_ne, @@ -235,11 +211,6 @@ def build_query( "destination_uuid": destination_uuid, "status": status, "status_in": status_in, - "event_offset": event_offset, - "event_offset_lt": event_offset_lt, - "event_offset_gt": event_offset_gt, - "event_offset_le": event_offset_le, - "event_offset_ge": event_offset_ge, "updated_at": updated_at, "updated_at_lt": updated_at_lt, "updated_at_gt": updated_at_gt, diff --git a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/test_factory.py b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/test_factory.py index d6559ae1d..15d7e0c17 100644 --- a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/test_factory.py +++ b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/test_factory.py @@ -39,7 +39,6 @@ def test_build_submit(self): uuid=uuid4(), destination_uuid=uuid4(), status=TransactionStatus.COMMITTED, - event_offset=234234, ) self.assertIsInstance(operation, AiopgDatabaseOperation) @@ -51,11 +50,6 @@ def test_build_query(self): destination_uuid=uuid4(), status=TransactionStatus.COMMITTED, status_in={TransactionStatus.REJECTED, TransactionStatus.RESERVED}, - event_offset=234, - event_offset_lt=24342, - event_offset_gt=3424, - event_offset_le=2342, - event_offset_ge=234342, updated_at=current_datetime(), updated_at_lt=current_datetime(), updated_at_gt=current_datetime(), From 377dae25d4cae5eab12e260859681c37466614c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 20 Apr 2022 11:34:38 +0200 Subject: [PATCH 03/75] ISSUE #64 * Raise a `TransactionRepositoryConflictException` instead of an `EventRepositoryConflictException`. --- .../minos/aggregate/transactions/entries.py | 6 +-- .../minos/aggregate/transactions/services.py | 3 +- .../test_transactions/test_entries.py | 4 +- .../test_transactions/test_services.py | 41 ++++++++++--------- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py index 94b5f9213..5be5419f8 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py @@ -34,7 +34,7 @@ ) from ..exceptions import ( - EventRepositoryConflictException, + TransactionRepositoryConflictException, ) from .contextvars import ( TRANSACTION_CONTEXT_VAR, @@ -177,9 +177,7 @@ async def reserve(self) -> None: status = TransactionStatus.RESERVED if committable else TransactionStatus.REJECTED await self.save(status=status) if not committable: - raise EventRepositoryConflictException( - f"{self!r} could not be reserved!", await self._event_repository.offset - ) + raise TransactionRepositoryConflictException(f"{self!r} could not be reserved!") async def validate(self) -> bool: """Check if the transaction is committable. diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/services.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/services.py index c02d35e91..c40c75e92 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/services.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/services.py @@ -16,7 +16,6 @@ ) from ..exceptions import ( - EventRepositoryConflictException, TransactionNotFoundException, TransactionRepositoryConflictException, ) @@ -58,7 +57,7 @@ async def __reserve__(self, request: Request) -> None: try: await transaction.reserve() - except EventRepositoryConflictException: + except TransactionRepositoryConflictException: raise ResponseException("The transaction could not be reserved.") async def __reject__(self, request: Request) -> None: diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py index 75fddc90f..7383c7279 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py @@ -18,8 +18,8 @@ TRANSACTION_CONTEXT_VAR, Action, EventEntry, - EventRepositoryConflictException, TransactionEntry, + TransactionRepositoryConflictException, TransactionStatus, ) from minos.common import ( @@ -135,7 +135,7 @@ async def test_reserve_failure(self) -> None: ), patch("minos.aggregate.TransactionEntry.save") as save_mock, patch( "minos.aggregate.TransactionEntry.validate", return_value=False ) as validate_mock: - with self.assertRaises(EventRepositoryConflictException): + with self.assertRaises(TransactionRepositoryConflictException): await transaction.reserve() self.assertEqual(1, validate_mock.call_count) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_services.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_services.py index 1fb1c1a6a..fdb1a12f5 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_services.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_services.py @@ -11,9 +11,9 @@ ) from minos.aggregate import ( - EventRepositoryConflictException, TransactionEntry, TransactionNotFoundException, + TransactionRepository, TransactionRepositoryConflictException, TransactionService, TransactionStatus, @@ -54,27 +54,27 @@ def test_get_enroute(self): async def test_reserve(self): uuid = uuid4() - with patch("minos.aggregate.TransactionEntry.reserve") as reserve_mock: - with patch("minos.aggregate.TransactionRepository.get", return_value=TransactionEntry(uuid)) as get_mock: + with patch.object(TransactionEntry, "reserve") as reserve_mock: + with patch.object(TransactionRepository, "get", return_value=TransactionEntry(uuid)) as get_mock: response = await self.service.__reserve__(InMemoryRequest(uuid)) self.assertEqual([call(uuid)], get_mock.call_args_list) self.assertEqual([call()], reserve_mock.call_args_list) self.assertEqual(None, response) async def test_reserve_raises(self): - with patch("minos.aggregate.TransactionRepository.get", side_effect=TransactionNotFoundException("")): + with patch.object(TransactionRepository, "get", side_effect=TransactionNotFoundException("")): with self.assertRaises(ResponseException): await self.service.__reserve__(InMemoryRequest(None)) - with patch("minos.aggregate.TransactionRepository.get", return_value=TransactionEntry()): - with patch("minos.aggregate.TransactionEntry.reserve", side_effect=EventRepositoryConflictException("", 0)): + with patch.object(TransactionRepository, "get", return_value=TransactionEntry()): + with patch.object(TransactionEntry, "reserve", side_effect=TransactionRepositoryConflictException("")): with self.assertRaises(ResponseException): await self.service.__reserve__(InMemoryRequest(None)) async def test_reject(self): uuid = uuid4() - with patch("minos.aggregate.TransactionEntry.reject") as reject_mock: - with patch("minos.aggregate.TransactionRepository.get", return_value=TransactionEntry(uuid)) as get_mock: + with patch.object(TransactionEntry, "reject") as reject_mock: + with patch.object(TransactionRepository, "get", return_value=TransactionEntry(uuid)) as get_mock: response = await self.service.__reject__(InMemoryRequest(uuid)) self.assertEqual([call(uuid)], get_mock.call_args_list) self.assertEqual([call()], reject_mock.call_args_list) @@ -82,7 +82,7 @@ async def test_reject(self): async def test_reject_already(self): uuid = uuid4() - with patch("minos.aggregate.TransactionEntry.reject") as reject_mock: + with patch.object(TransactionEntry, "reject") as reject_mock: with patch( "minos.aggregate.TransactionRepository.get", return_value=TransactionEntry(uuid, status=TransactionStatus.REJECTED), @@ -93,11 +93,11 @@ async def test_reject_already(self): self.assertEqual(None, response) async def test_reject_raises(self): - with patch("minos.aggregate.TransactionRepository.get", side_effect=TransactionNotFoundException("")): + with patch.object(TransactionRepository, "get", side_effect=TransactionNotFoundException("")): with self.assertRaises(ResponseException): await self.service.__reject__(InMemoryRequest(None)) - with patch("minos.aggregate.TransactionRepository.get", return_value=TransactionEntry()): + with patch.object(TransactionRepository, "get", return_value=TransactionEntry()): with patch( "minos.aggregate.TransactionEntry.reject", side_effect=TransactionRepositoryConflictException("") ): @@ -106,19 +106,19 @@ async def test_reject_raises(self): async def test_commit(self): uuid = uuid4() - with patch("minos.aggregate.TransactionEntry.commit") as commit_mock: - with patch("minos.aggregate.TransactionRepository.get", return_value=TransactionEntry(uuid)) as get_mock: + with patch.object(TransactionEntry, "commit") as commit_mock: + with patch.object(TransactionRepository, "get", return_value=TransactionEntry(uuid)) as get_mock: response = await self.service.__commit__(InMemoryRequest(uuid)) self.assertEqual([call(uuid)], get_mock.call_args_list) self.assertEqual([call()], commit_mock.call_args_list) self.assertEqual(None, response) async def test_commit_raises(self): - with patch("minos.aggregate.TransactionRepository.get", side_effect=TransactionNotFoundException("")): + with patch.object(TransactionRepository, "get", side_effect=TransactionNotFoundException("")): with self.assertRaises(ResponseException): await self.service.__commit__(InMemoryRequest(None)) - with patch("minos.aggregate.TransactionRepository.get", return_value=TransactionEntry()): + with patch.object(TransactionRepository, "get", return_value=TransactionEntry()): with patch( "minos.aggregate.TransactionEntry.commit", side_effect=TransactionRepositoryConflictException("") ): @@ -127,7 +127,7 @@ async def test_commit_raises(self): async def test_reject_blocked(self): uuid = uuid4() - with patch("minos.aggregate.TransactionEntry.reject") as reject_mock: + with patch.object(TransactionEntry, "reject") as reject_mock: with patch( "minos.aggregate.TransactionRepository.select", return_value=FakeAsyncIterator([TransactionEntry(uuid)]) ) as select_mock: @@ -146,11 +146,12 @@ async def test_reject_blocked(self): async def test_reject_blocked_raises(self): uuid = uuid4() - with patch( - "minos.aggregate.TransactionEntry.reject", side_effect=[None, TransactionRepositoryConflictException("")] + with patch.object( + TransactionEntry, "reject", side_effect=[None, TransactionRepositoryConflictException("")] ) as reject_mock: - with patch( - "minos.aggregate.TransactionRepository.select", + with patch.object( + TransactionRepository, + "select", return_value=FakeAsyncIterator([TransactionEntry(uuid), TransactionEntry(uuid)]), ): response = await self.service.__reject_blocked__(InMemoryRequest(uuid)) From dde70cd1b8c684acd87b1c774771fad95509a6e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 20 Apr 2022 13:30:13 +0200 Subject: [PATCH 04/75] ISSUE #63 * Add `TransactionalMixin` and implement an "Observer Pattern" between `EventRepository` and `TransactionEntry`. --- .../minos/aggregate/__init__.py | 1 + .../aggregate/events/repositories/abc.py | 35 ++++++++--- .../events/repositories/database/impl.py | 7 +-- .../snapshots/repositories/database/impl.py | 4 +- .../minos/aggregate/transactions/__init__.py | 3 + .../minos/aggregate/transactions/entries.py | 62 ++++++++----------- .../minos/aggregate/transactions/mixins.py | 59 ++++++++++++++++++ .../transactions/repositories/abc.py | 21 +++++++ .../repositories/database/impl.py | 3 +- .../transactions/repositories/memory.py | 1 - .../test_events/test_repositories/test_abc.py | 1 - .../test_transactions/test_entries.py | 2 - 12 files changed, 141 insertions(+), 58 deletions(-) create mode 100644 packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py index 3c99d6c3a..80032ab10 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py @@ -69,6 +69,7 @@ TRANSACTION_CONTEXT_VAR, DatabaseTransactionRepository, InMemoryTransactionRepository, + TransactionalMixin, TransactionDatabaseOperationFactory, TransactionEntry, TransactionRepository, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py index de03ccfd5..cd44fd6c4 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py @@ -31,7 +31,6 @@ LockPool, NotProvidedException, PoolFactory, - SetupMixin, classname, ) from minos.networks import ( @@ -53,8 +52,8 @@ ) from ...transactions import ( TRANSACTION_CONTEXT_VAR, + TransactionalMixin, TransactionEntry, - TransactionRepository, TransactionStatus, ) from ..entries import ( @@ -74,14 +73,13 @@ @Injectable("event_repository") -class EventRepository(ABC, SetupMixin): +class EventRepository(ABC, TransactionalMixin): """Base event repository class in ``minos``.""" @Inject() def __init__( self, broker_publisher: BrokerPublisher, - transaction_repository: TransactionRepository, lock_pool: Optional[LockPool] = None, pool_factory: Optional[PoolFactory] = None, *args, @@ -95,14 +93,10 @@ def __init__( if broker_publisher is None: raise NotProvidedException("A broker instance is required.") - if transaction_repository is None: - raise NotProvidedException("A transaction repository instance is required.") - if lock_pool is None: raise NotProvidedException("A lock pool instance is required.") self._broker_publisher = broker_publisher - self._transaction_repository = transaction_repository self._lock_pool = lock_pool def transaction(self, **kwargs) -> TransactionEntry: @@ -111,7 +105,7 @@ def transaction(self, **kwargs) -> TransactionEntry: :param kwargs: Additional named arguments. :return: A new ``TransactionEntry`` instance. """ - return TransactionEntry(event_repository=self, transaction_repository=self._transaction_repository, **kwargs) + return TransactionEntry(transaction_repository=self._transaction_repository, **kwargs) async def create(self, entry: Union[Event, EventEntry]) -> EventEntry: """Store new creation entry into the repository. @@ -317,8 +311,29 @@ async def _offset(self) -> int: raise NotImplementedError def write_lock(self) -> Lock: - """Get a write lock. + """Get a lock. :return: An asynchronous context manager. """ return self._lock_pool.acquire("aggregate_event_write_lock") + + async def get_related_transactions(self, transaction_uuid: UUID) -> set[UUID]: + """TODO""" + entries = dict() + async for entry in self.select(transaction_uuid=transaction_uuid): + if entry.uuid in entries and entry.version < entries[entry.uuid]: + continue + entries[entry.uuid] = entry.version + + transaction_uuids = set() + for uuid, version in entries.items(): + async for entry in self.select(uuid=uuid, version=version): + if entry.transaction_uuid != transaction_uuid: + transaction_uuids.add(entry.transaction_uuid) + return transaction_uuids + + async def commit_transaction(self, transaction_uuid: UUID, destination_transaction_uuid: UUID) -> None: + """TODO""" + async for entry in self.select(transaction_uuid=transaction_uuid): + new = EventEntry.from_another(entry, transaction_uuid=destination_transaction_uuid) + await self.submit(new, transaction_uuid_ne=transaction_uuid) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/impl.py index 0f549e33e..6d92180cd 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/impl.py @@ -36,11 +36,8 @@ def __init__(self, *args, database_key: Optional[tuple[str]] = None, **kwargs): database_key = ("aggregate", "event") super().__init__(*args, database_key=database_key, **kwargs) - async def _setup(self): - """Setup miscellaneous repository things. - - :return: This method does not return anything. - """ + async def _setup(self) -> None: + await super()._setup() operation = self.database_operation_factory.build_create() await self.execute_on_database(operation) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py index b1b7554ee..4f965cc89 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py @@ -90,12 +90,10 @@ def __init__( self._transaction_repository = transaction_repository async def _setup(self) -> None: + await super()._setup() operation = self.database_operation_factory.build_create() await self.execute_on_database(operation) - async def _destroy(self) -> None: - await super()._destroy() - # noinspection PyUnusedLocal async def _find_entries( self, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/__init__.py index 387f13660..d1cea06fe 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/__init__.py @@ -5,6 +5,9 @@ TransactionEntry, TransactionStatus, ) +from .mixins import ( + TransactionalMixin, +) from .repositories import ( DatabaseTransactionRepository, InMemoryTransactionRepository, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py index 5be5419f8..f4ffaba0b 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py @@ -41,9 +41,6 @@ ) if TYPE_CHECKING: - from ..events import ( - EventRepository, - ) from .repositories import ( TransactionRepository, ) @@ -60,7 +57,6 @@ class TransactionEntry: "destination_uuid", "updated_at", "_autocommit", - "_event_repository", "_transaction_repository", "_token", ) @@ -72,18 +68,8 @@ def __init__( destination_uuid: Optional[UUID] = None, updated_at: Optional[datetime] = None, autocommit: bool = True, - event_repository: Optional[EventRepository] = None, transaction_repository: Optional[TransactionRepository] = None, ): - - if event_repository is None: - from ..events import ( - EventRepository, - ) - - with suppress(NotProvidedException): - event_repository = Inject.resolve(EventRepository) - if transaction_repository is None: from .repositories import ( TransactionRepository, @@ -110,7 +96,6 @@ def __init__( self.updated_at = updated_at self._autocommit = autocommit - self._event_repository = event_repository self._transaction_repository = transaction_repository self._token = None @@ -152,13 +137,8 @@ async def commit(self) -> None: await self.save(status=TransactionStatus.COMMITTED) async def _commit(self) -> None: - from ..events import ( - EventEntry, - ) - - async for entry in self._event_repository.select(transaction_uuid=self.uuid): - new = EventEntry.from_another(entry, transaction_uuid=self.destination_uuid) - await self._event_repository.submit(new, transaction_uuid_ne=self.uuid) + for subscriber in self._transaction_repository.subscribers: + await subscriber.commit_transaction(self.uuid, self.destination_uuid) async def reserve(self) -> None: """Reserve transaction changes to be ensured that they can be applied. @@ -169,7 +149,10 @@ async def reserve(self) -> None: raise ValueError(f"Current status is not {TransactionStatus.PENDING!r}. Obtained: {self.status!r}") async with self._transaction_repository.write_lock(): - async with self._event_repository.write_lock(): + locks = MultiAsyncContextManager( + subscriber.write_lock() for subscriber in self._transaction_repository.subscribers + ) + async with locks: await self.save(status=TransactionStatus.RESERVING) committable = await self.validate() @@ -199,21 +182,14 @@ async def validate(self) -> bool: return False - entries = dict() - async for entry in self._event_repository.select(transaction_uuid=self.uuid): - if entry.uuid in entries and entry.version < entries[entry.uuid]: - continue - entries[entry.uuid] = entry.version - transaction_uuids = set() - for uuid, version in entries.items(): - async for entry in self._event_repository.select(uuid=uuid, version=version): - if entry.transaction_uuid == self.destination_uuid: - return False - if entry.transaction_uuid != self.uuid: - transaction_uuids.add(entry.transaction_uuid) + for subscriber in self._transaction_repository.subscribers: + transaction_uuids |= await subscriber.get_related_transactions(self.uuid) if len(transaction_uuids): + if self.destination_uuid in transaction_uuids: + return False + with suppress(StopAsyncIteration): iterable = self._transaction_repository.select( destination_uuid=self.destination_uuid, @@ -243,6 +219,9 @@ async def reject(self) -> None: ) async with self._transaction_repository.write_lock(): + for subscriber in self._transaction_repository.subscribers: + await subscriber.reject_transaction(self.uuid) + await self.save(status=TransactionStatus.REJECTED) async def save(self, *, status: Optional[TransactionStatus] = None) -> None: @@ -337,3 +316,16 @@ def value_of(cls, value: str) -> TransactionStatus: if item.value == value: return item raise ValueError(f"The given value does not match with any enum items. Obtained {value}") + + +class MultiAsyncContextManager(tuple): + """TODO""" + + async def __aenter__(self): + for value in self: + await value.__aenter__() + return self + + async def __aexit__(self, *exc): + for value in self: + await value.__aexit__(*exc) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py new file mode 100644 index 000000000..4f5e01a30 --- /dev/null +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py @@ -0,0 +1,59 @@ +from abc import ( + abstractmethod, +) +from uuid import ( + UUID, +) + +from minos.common import ( + Inject, + Lock, + NotProvidedException, + SetupMixin, +) + +from .repositories import ( + TransactionRepository, +) + + +class TransactionalMixin(SetupMixin): + """TODO""" + + @Inject() + def __init__(self, transaction_repository: TransactionRepository, *args, **kwargs): + super().__init__(*args, **kwargs) + if transaction_repository is None: + raise NotProvidedException("A transaction repository instance is required.") + self._transaction_repository = transaction_repository + + async def _setup(self) -> None: + await super()._setup() + self.subscribe_to_transactions() + + async def _destroy(self) -> None: + self.unsubscribe_from_transactions() + await super()._destroy() + + def subscribe_to_transactions(self) -> None: + """TODO""" + self._transaction_repository.add_subscriber(self) + + def unsubscribe_from_transactions(self) -> None: + """TODO""" + self._transaction_repository.remove_subscriber(self) + + @abstractmethod + async def get_related_transactions(self, transaction_uuid: UUID) -> set[UUID]: + """TODO""" + + @abstractmethod + async def commit_transaction(self, transaction_uuid: UUID, destination: UUID) -> None: + """TODO""" + + async def reject_transaction(self, transaction_uuid: UUID) -> None: + """TODO""" + + @abstractmethod + def write_lock(self) -> Lock: + """TODO""" diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py index 5521cb2a5..75361790e 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py @@ -13,6 +13,7 @@ datetime, ) from typing import ( + TYPE_CHECKING, AsyncIterator, Optional, ) @@ -38,6 +39,11 @@ TransactionStatus, ) +if TYPE_CHECKING: + from ..mixins import ( + TransactionalMixin, + ) + @Injectable("transaction_repository") class TransactionRepository(ABC, SetupMixin): @@ -57,6 +63,21 @@ def __init__( self._lock_pool = lock_pool + self._subscribers = list() + + @property + def subscribers(self) -> list[TransactionalMixin]: + """TODO""" + return self._subscribers + + def add_subscriber(self, subscriber: TransactionalMixin) -> None: + """TODO""" + self._subscribers.append(subscriber) + + def remove_subscriber(self, subscriber: TransactionalMixin) -> None: + """TODO""" + self._subscribers.remove(subscriber) + async def submit(self, transaction: TransactionEntry) -> TransactionEntry: """Submit a new or updated transaction to store it on the repository. diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/impl.py index 2b0ac0026..e33a7ed8f 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/impl.py @@ -34,7 +34,8 @@ def __init__(self, *args, database_key: Optional[tuple[str]] = None, **kwargs): database_key = ("aggregate", "transaction") super().__init__(*args, database_key=database_key, **kwargs) - async def _setup(self): + async def _setup(self) -> None: + await super()._setup() operation = self.database_operation_factory.build_create() await self.execute_on_database(operation) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py index 3795aca29..42dc15ae0 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py @@ -54,7 +54,6 @@ async def _submit(self, transaction: TransactionEntry) -> TransactionEntry: destination_uuid=transaction.destination_uuid, status=transaction.status, updated_at=transaction.updated_at, - event_repository=transaction._event_repository, transaction_repository=transaction._transaction_repository, ) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py index 90a09c8ee..80edb51fe 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py @@ -97,7 +97,6 @@ def test_transaction(self): uuid = uuid4() transaction = self.event_repository.transaction(uuid=uuid) self.assertEqual(TransactionEntry(uuid), transaction) - self.assertEqual(self.event_repository, transaction._event_repository) self.assertEqual(self.transaction_repository, transaction._transaction_repository) async def test_create(self): diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py index 7383c7279..7014b839b 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py @@ -39,7 +39,6 @@ def test_constructor(self): self.assertEqual(TransactionStatus.PENDING, transaction.status) self.assertEqual(True, transaction._autocommit) - self.assertEqual(self.event_repository, transaction._event_repository) self.assertEqual(self.transaction_repository, transaction._transaction_repository) def test_constructor_extended(self): @@ -50,7 +49,6 @@ def test_constructor_extended(self): self.assertEqual(status, transaction.status) self.assertEqual(False, transaction._autocommit) - self.assertEqual(self.event_repository, transaction._event_repository) self.assertEqual(self.transaction_repository, transaction._transaction_repository) def test_constructor_raw_status(self): From 34113f0a361d4055393d719497e4b1028fa3b27f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 20 Apr 2022 15:11:31 +0200 Subject: [PATCH 05/75] ISSUE #63 * Add missing docstring. * Minor improvements. --- .../aggregate/events/repositories/abc.py | 19 +++++-- .../events/repositories/database/impl.py | 2 +- .../minos/aggregate/transactions/entries.py | 22 ++++---- .../minos/aggregate/transactions/mixins.py | 56 +++++++++++++------ .../transactions/repositories/abc.py | 31 ++++++---- .../minos/common/locks.py | 3 + 6 files changed, 92 insertions(+), 41 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py index cd44fd6c4..dd6c7ce0e 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py @@ -76,6 +76,8 @@ class EventRepository(ABC, TransactionalMixin): """Base event repository class in ``minos``.""" + _lock_pool: LockPool + @Inject() def __init__( self, @@ -105,7 +107,7 @@ def transaction(self, **kwargs) -> TransactionEntry: :param kwargs: Additional named arguments. :return: A new ``TransactionEntry`` instance. """ - return TransactionEntry(transaction_repository=self._transaction_repository, **kwargs) + return TransactionEntry(transaction_repository=self.transaction_repository, **kwargs) async def create(self, entry: Union[Event, EventEntry]) -> EventEntry: """Store new creation entry into the repository. @@ -178,7 +180,7 @@ async def validate(self, entry: EventEntry, transaction_uuid_ne: Optional[UUID] :param kwargs: Additional named arguments. :return: ``True`` if the entry can be submitted or ``False`` otherwise. """ - iterable = self._transaction_repository.select( + iterable = self.transaction_repository.select( destination_uuid=entry.transaction_uuid, uuid_ne=transaction_uuid_ne, status_in=(TransactionStatus.RESERVING, TransactionStatus.RESERVED, TransactionStatus.COMMITTING), @@ -318,7 +320,11 @@ def write_lock(self) -> Lock: return self._lock_pool.acquire("aggregate_event_write_lock") async def get_related_transactions(self, transaction_uuid: UUID) -> set[UUID]: - """TODO""" + """Get the set of related transaction identifiers. + + :param transaction_uuid: The identifier of the transaction to be committed. + :return: A ``set`` or ``UUID`` values. + """ entries = dict() async for entry in self.select(transaction_uuid=transaction_uuid): if entry.uuid in entries and entry.version < entries[entry.uuid]: @@ -333,7 +339,12 @@ async def get_related_transactions(self, transaction_uuid: UUID) -> set[UUID]: return transaction_uuids async def commit_transaction(self, transaction_uuid: UUID, destination_transaction_uuid: UUID) -> None: - """TODO""" + """Commit the transaction with given identifier. + + :param transaction_uuid: The identifier of the transaction to be committed. + :param destination_transaction_uuid: The identifier of the destination transaction. + :return: This method does not return anything. + """ async for entry in self.select(transaction_uuid=transaction_uuid): new = EventEntry.from_another(entry, transaction_uuid=destination_transaction_uuid) await self.submit(new, transaction_uuid_ne=transaction_uuid) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/impl.py index 6d92180cd..42d492fa2 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/impl.py @@ -61,7 +61,7 @@ async def _build_submit_operation(self, entry: EventEntry) -> DatabaseOperation: lock = entry.uuid.int & (1 << 32) - 1 if entry.transaction_uuid != NULL_UUID: - transaction = await self._transaction_repository.get(uuid=entry.transaction_uuid) + transaction = await self.transaction_repository.get(uuid=entry.transaction_uuid) transaction_uuids = await transaction.uuids else: transaction_uuids = (NULL_UUID,) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py index f4ffaba0b..0413e7ea3 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py @@ -137,7 +137,7 @@ async def commit(self) -> None: await self.save(status=TransactionStatus.COMMITTED) async def _commit(self) -> None: - for subscriber in self._transaction_repository.subscribers: + for subscriber in self._transaction_repository.observers: await subscriber.commit_transaction(self.uuid, self.destination_uuid) async def reserve(self) -> None: @@ -149,10 +149,8 @@ async def reserve(self) -> None: raise ValueError(f"Current status is not {TransactionStatus.PENDING!r}. Obtained: {self.status!r}") async with self._transaction_repository.write_lock(): - locks = MultiAsyncContextManager( - subscriber.write_lock() for subscriber in self._transaction_repository.subscribers - ) - async with locks: + + async with self._get_observer_locks(): await self.save(status=TransactionStatus.RESERVING) committable = await self.validate() @@ -162,6 +160,12 @@ async def reserve(self) -> None: if not committable: raise TransactionRepositoryConflictException(f"{self!r} could not be reserved!") + def _get_observer_locks(self) -> _MultiAsyncContextManager: + locks = (subscriber.write_lock() for subscriber in self._transaction_repository.observers) + locks = (lock for lock in locks if lock is not None) + locks = _MultiAsyncContextManager(locks) + return locks + async def validate(self) -> bool: """Check if the transaction is committable. @@ -183,7 +187,7 @@ async def validate(self) -> bool: return False transaction_uuids = set() - for subscriber in self._transaction_repository.subscribers: + for subscriber in self._transaction_repository.observers: transaction_uuids |= await subscriber.get_related_transactions(self.uuid) if len(transaction_uuids): @@ -219,7 +223,7 @@ async def reject(self) -> None: ) async with self._transaction_repository.write_lock(): - for subscriber in self._transaction_repository.subscribers: + for subscriber in self._transaction_repository.observers: await subscriber.reject_transaction(self.uuid) await self.save(status=TransactionStatus.REJECTED) @@ -318,9 +322,7 @@ def value_of(cls, value: str) -> TransactionStatus: raise ValueError(f"The given value does not match with any enum items. Obtained {value}") -class MultiAsyncContextManager(tuple): - """TODO""" - +class _MultiAsyncContextManager(tuple): async def __aenter__(self): for value in self: await value.__aenter__() diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py index 4f5e01a30..10d7b5387 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py @@ -1,6 +1,9 @@ from abc import ( abstractmethod, ) +from typing import ( + Optional, +) from uuid import ( UUID, ) @@ -18,7 +21,7 @@ class TransactionalMixin(SetupMixin): - """TODO""" + """Transactional Mixin class.""" @Inject() def __init__(self, transaction_repository: TransactionRepository, *args, **kwargs): @@ -27,33 +30,54 @@ def __init__(self, transaction_repository: TransactionRepository, *args, **kwarg raise NotProvidedException("A transaction repository instance is required.") self._transaction_repository = transaction_repository + @property + def transaction_repository(self) -> TransactionRepository: + """Get the transaction repository. + + :return: A ``Transaction`` repository instance. + """ + return self._transaction_repository + async def _setup(self) -> None: await super()._setup() - self.subscribe_to_transactions() + self._register_into_transaction_repository() async def _destroy(self) -> None: - self.unsubscribe_from_transactions() + self._unregister_from_transaction_repository() await super()._destroy() - def subscribe_to_transactions(self) -> None: - """TODO""" - self._transaction_repository.add_subscriber(self) + def _register_into_transaction_repository(self) -> None: + self._transaction_repository.register_observer(self) - def unsubscribe_from_transactions(self) -> None: - """TODO""" - self._transaction_repository.remove_subscriber(self) + def _unregister_from_transaction_repository(self) -> None: + self._transaction_repository.unregister_observer(self) @abstractmethod async def get_related_transactions(self, transaction_uuid: UUID) -> set[UUID]: - """TODO""" + """Get the set of related transaction identifiers. + + :param transaction_uuid: The identifier of the transaction to be committed. + :return: A ``set`` or ``UUID`` values. + """ @abstractmethod - async def commit_transaction(self, transaction_uuid: UUID, destination: UUID) -> None: - """TODO""" + async def commit_transaction(self, transaction_uuid: UUID, destination_transaction_uuid: UUID) -> None: + """Commit the transaction with given identifier. + + :param transaction_uuid: The identifier of the transaction to be committed. + :param destination_transaction_uuid: The identifier of the destination transaction. + :return: This method does not return anything. + """ async def reject_transaction(self, transaction_uuid: UUID) -> None: - """TODO""" + """Reject the transaction with given identifier - @abstractmethod - def write_lock(self) -> Lock: - """TODO""" + :param transaction_uuid: The identifier of the transaction to be committed. + :return: This method does not return anything. + """ + + def write_lock(self) -> Optional[Lock]: + """Get a lock if available. + + :return: A ``Lock`` instance or ``None``. + """ diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py index 75361790e..75429a42b 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py @@ -63,20 +63,31 @@ def __init__( self._lock_pool = lock_pool - self._subscribers = list() + self._observers = set() @property - def subscribers(self) -> list[TransactionalMixin]: - """TODO""" - return self._subscribers + def observers(self) -> set[TransactionalMixin]: + """Get the list of observers. - def add_subscriber(self, subscriber: TransactionalMixin) -> None: - """TODO""" - self._subscribers.append(subscriber) + :return: A ``list`` of ``TransactionalMixin`` entries. + """ + return self._observers + + def register_observer(self, observer: TransactionalMixin) -> None: + """Register a new observer into the system. + + :param observer: The observer to be registered. + :return: This method does not return anything. + """ + self._observers.add(observer) + + def unregister_observer(self, observer: TransactionalMixin) -> None: + """Unregister an observer form the system - def remove_subscriber(self, subscriber: TransactionalMixin) -> None: - """TODO""" - self._subscribers.remove(subscriber) + :param observer: The observer to be unregistered + :return: This method does not return anything. + """ + self._observers.remove(observer) async def submit(self, transaction: TransactionEntry) -> TransactionEntry: """Submit a new or updated transaction to store it on the repository. diff --git a/packages/core/minos-microservice-common/minos/common/locks.py b/packages/core/minos-microservice-common/minos/common/locks.py index bf21dbf6b..ef030055a 100644 --- a/packages/core/minos-microservice-common/minos/common/locks.py +++ b/packages/core/minos-microservice-common/minos/common/locks.py @@ -7,6 +7,7 @@ abstractmethod, ) from collections.abc import ( + Callable, Hashable, ) @@ -64,3 +65,5 @@ def hashed_key(self) -> int: class LockPool(Pool[Lock], ABC): """Lock Pool class.""" + + acquire: Callable[[str], Lock] From ddc80f9ab10f64a0ac593f4c67cd20662ec3cfb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 20 Apr 2022 15:51:49 +0200 Subject: [PATCH 06/75] ISSUE #63 * Simplify variable names. --- .../aggregate/events/repositories/abc.py | 2 +- .../minos/aggregate/transactions/entries.py | 40 +++++++++++-------- .../repositories/database/impl.py | 2 +- .../transactions/repositories/memory.py | 2 +- .../test_events/test_repositories/test_abc.py | 4 +- .../test_transactions/test_entries.py | 4 +- .../test_repositories/test_abc.py | 29 ++++++++++++++ 7 files changed, 60 insertions(+), 23 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py index dd6c7ce0e..1dc807616 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py @@ -107,7 +107,7 @@ def transaction(self, **kwargs) -> TransactionEntry: :param kwargs: Additional named arguments. :return: A new ``TransactionEntry`` instance. """ - return TransactionEntry(transaction_repository=self.transaction_repository, **kwargs) + return TransactionEntry(repository=self.transaction_repository, **kwargs) async def create(self, entry: Union[Event, EventEntry]) -> EventEntry: """Store new creation entry into the repository. diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py index 0413e7ea3..ed18e5ea4 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py @@ -57,7 +57,7 @@ class TransactionEntry: "destination_uuid", "updated_at", "_autocommit", - "_transaction_repository", + "_repository", "_token", ) @@ -68,15 +68,15 @@ def __init__( destination_uuid: Optional[UUID] = None, updated_at: Optional[datetime] = None, autocommit: bool = True, - transaction_repository: Optional[TransactionRepository] = None, + repository: Optional[TransactionRepository] = None, ): - if transaction_repository is None: + if repository is None: from .repositories import ( TransactionRepository, ) with suppress(NotProvidedException): - transaction_repository = Inject.resolve(TransactionRepository) + repository = Inject.resolve(TransactionRepository) if uuid is None: uuid = uuid4() @@ -96,10 +96,18 @@ def __init__( self.updated_at = updated_at self._autocommit = autocommit - self._transaction_repository = transaction_repository + self._repository = repository self._token = None + @property + def repository(self) -> TransactionRepository: + """Get the repository. + + :return: A ``TransactionRepository``. + """ + return self._repository + async def __aenter__(self): if self.status != TransactionStatus.PENDING: raise ValueError(f"Current status is not {TransactionStatus.PENDING!r}. Obtained: {self.status!r}") @@ -131,13 +139,13 @@ async def commit(self) -> None: if self.status != TransactionStatus.RESERVED: raise ValueError(f"Current status is not {TransactionStatus.RESERVED!r}. Obtained: {self.status!r}") - async with self._transaction_repository.write_lock(): + async with self._repository.write_lock(): await self.save(status=TransactionStatus.COMMITTING) await self._commit() await self.save(status=TransactionStatus.COMMITTED) async def _commit(self) -> None: - for subscriber in self._transaction_repository.observers: + for subscriber in self._repository.observers: await subscriber.commit_transaction(self.uuid, self.destination_uuid) async def reserve(self) -> None: @@ -148,7 +156,7 @@ async def reserve(self) -> None: if self.status != TransactionStatus.PENDING: raise ValueError(f"Current status is not {TransactionStatus.PENDING!r}. Obtained: {self.status!r}") - async with self._transaction_repository.write_lock(): + async with self._repository.write_lock(): async with self._get_observer_locks(): await self.save(status=TransactionStatus.RESERVING) @@ -161,7 +169,7 @@ async def reserve(self) -> None: raise TransactionRepositoryConflictException(f"{self!r} could not be reserved!") def _get_observer_locks(self) -> _MultiAsyncContextManager: - locks = (subscriber.write_lock() for subscriber in self._transaction_repository.observers) + locks = (subscriber.write_lock() for subscriber in self._repository.observers) locks = (lock for lock in locks if lock is not None) locks = _MultiAsyncContextManager(locks) return locks @@ -172,7 +180,7 @@ async def validate(self) -> bool: :return: ``True`` if the transaction is valid or ``False`` otherwise. """ with suppress(StopAsyncIteration): - iterable = self._transaction_repository.select( + iterable = self._repository.select( uuid=self.destination_uuid, status_in=( TransactionStatus.RESERVING, @@ -187,7 +195,7 @@ async def validate(self) -> bool: return False transaction_uuids = set() - for subscriber in self._transaction_repository.observers: + for subscriber in self._repository.observers: transaction_uuids |= await subscriber.get_related_transactions(self.uuid) if len(transaction_uuids): @@ -195,7 +203,7 @@ async def validate(self) -> bool: return False with suppress(StopAsyncIteration): - iterable = self._transaction_repository.select( + iterable = self._repository.select( destination_uuid=self.destination_uuid, uuid_in=tuple(transaction_uuids), status_in=( @@ -222,8 +230,8 @@ async def reject(self) -> None: f"Obtained: {self.status!r}" ) - async with self._transaction_repository.write_lock(): - for subscriber in self._transaction_repository.observers: + async with self._repository.write_lock(): + for subscriber in self._repository.observers: await subscriber.reject_transaction(self.uuid) await self.save(status=TransactionStatus.REJECTED) @@ -238,7 +246,7 @@ async def save(self, *, status: Optional[TransactionStatus] = None) -> None: if status is not None: self.status = status - await self._transaction_repository.submit(self) + await self._repository.submit(self) @property async def uuids(self) -> tuple[UUID, ...]: @@ -269,7 +277,7 @@ async def destination(self) -> Optional[TransactionEntry]: destination = getattr(self._token, "old_value", Token.MISSING) if destination == Token.MISSING: - destination = await self._transaction_repository.get(uuid=self.destination_uuid) + destination = await self._repository.get(uuid=self.destination_uuid) return destination diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/impl.py index e33a7ed8f..730bf1f14 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/impl.py @@ -56,4 +56,4 @@ async def _submit(self, transaction: TransactionEntry) -> TransactionEntry: async def _select(self, streaming_mode: Optional[bool] = None, **kwargs) -> AsyncIterator[TransactionEntry]: operation = self.database_operation_factory.build_query(**kwargs) async for row in self.execute_on_database_and_fetch_all(operation, streaming_mode=streaming_mode): - yield TransactionEntry(*row, transaction_repository=self) + yield TransactionEntry(*row, repository=self) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py index 42dc15ae0..1c52c8530 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py @@ -54,7 +54,7 @@ async def _submit(self, transaction: TransactionEntry) -> TransactionEntry: destination_uuid=transaction.destination_uuid, status=transaction.status, updated_at=transaction.updated_at, - transaction_repository=transaction._transaction_repository, + repository=transaction.repository, ) return transaction diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py index 80edb51fe..f65484232 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py @@ -79,7 +79,7 @@ def test_abstract(self): def test_constructor(self): repository = _EventRepository() self.assertEqual(self.broker_publisher, repository._broker_publisher) - self.assertEqual(self.transaction_repository, repository._transaction_repository) + self.assertEqual(self.transaction_repository, repository.transaction_repository) self.assertEqual(self.pool_factory.get_pool("lock"), repository._lock_pool) async def test_constructor_raises(self): @@ -97,7 +97,7 @@ def test_transaction(self): uuid = uuid4() transaction = self.event_repository.transaction(uuid=uuid) self.assertEqual(TransactionEntry(uuid), transaction) - self.assertEqual(self.transaction_repository, transaction._transaction_repository) + self.assertEqual(self.transaction_repository, transaction.repository) async def test_create(self): mock = AsyncMock(side_effect=lambda x: x) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py index 7014b839b..62e1223bb 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py @@ -39,7 +39,7 @@ def test_constructor(self): self.assertEqual(TransactionStatus.PENDING, transaction.status) self.assertEqual(True, transaction._autocommit) - self.assertEqual(self.transaction_repository, transaction._transaction_repository) + self.assertEqual(self.transaction_repository, transaction.repository) def test_constructor_extended(self): uuid = uuid4() @@ -49,7 +49,7 @@ def test_constructor_extended(self): self.assertEqual(status, transaction.status) self.assertEqual(False, transaction._autocommit) - self.assertEqual(self.transaction_repository, transaction._transaction_repository) + self.assertEqual(self.transaction_repository, transaction.repository) def test_constructor_raw_status(self): transaction = TransactionEntry(status="pending") diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py index 5c8977ade..03ed3f85a 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py @@ -11,10 +11,12 @@ call, ) from uuid import ( + UUID, uuid4, ) from minos.aggregate import ( + TransactionalMixin, TransactionEntry, TransactionNotFoundException, TransactionRepository, @@ -41,6 +43,16 @@ def _select(self, **kwargs) -> AsyncIterator[TransactionEntry]: """For testing purposes.""" +class _Observer(TransactionalMixin): + """For testing purposes.""" + + async def get_related_transactions(self, transaction_uuid: UUID) -> set[UUID]: + """For testing purposes.""" + + async def commit_transaction(self, transaction_uuid: UUID, destination_transaction_uuid: UUID) -> None: + """For testing purposes.""" + + class TestTransactionRepository(AggregateTestCase): def setUp(self) -> None: super().setUp() @@ -56,6 +68,23 @@ def test_abstract(self): # noinspection PyUnresolvedReferences self.assertEqual({"_submit", "_select"}, TransactionRepository.__abstractmethods__) + def test_observers_empty(self): + self.assertEqual(set(), self.transaction_repository.observers) + + def test_register_observer(self): + observer1, observer2 = _Observer(), _Observer() + self.transaction_repository.register_observer(observer1) + self.transaction_repository.register_observer(observer2) + self.assertEqual({observer1, observer2}, self.transaction_repository.observers) + + def test_unregister_observer(self): + observer1, observer2 = _Observer(), _Observer() + self.transaction_repository.register_observer(observer1) + self.transaction_repository.register_observer(observer2) + self.assertEqual({observer1, observer2}, self.transaction_repository.observers) + self.transaction_repository.unregister_observer(observer2) + self.assertEqual({observer1}, self.transaction_repository.observers) + async def test_submit(self): transaction = TransactionEntry() mock = AsyncMock() From 6b5ced3be8b7f322eb0309b09e0533240ab13242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 20 Apr 2022 16:03:01 +0200 Subject: [PATCH 07/75] ISSUE #63 * Add tests for `TransactionalMixin`. --- .../test_transactions/test_mixins.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_mixins.py diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_mixins.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_mixins.py new file mode 100644 index 000000000..d7c9bedfb --- /dev/null +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_mixins.py @@ -0,0 +1,44 @@ +import unittest +from uuid import ( + UUID, +) + +from minos.aggregate import ( + TransactionalMixin, +) +from minos.common import ( + SetupMixin, +) +from tests.utils import ( + AggregateTestCase, +) + + +class _Observer(TransactionalMixin): + """For testing purposes.""" + + async def get_related_transactions(self, transaction_uuid: UUID) -> set[UUID]: + """For testing purposes.""" + + async def commit_transaction(self, transaction_uuid: UUID, destination_transaction_uuid: UUID) -> None: + """For testing purposes.""" + + +class TestTransactionalMixin(AggregateTestCase): + def test_abstract(self) -> None: + self.assertTrue(issubclass(TransactionalMixin, SetupMixin)) + + def test_constructor(self): + observer = _Observer() + self.assertEqual(self.transaction_repository, observer.transaction_repository) + + async def test_register_into_observable(self): + observer = _Observer() + self.assertNotIn(observer, self.transaction_repository.observers) + async with observer: + self.assertIn(observer, self.transaction_repository.observers) + self.assertNotIn(observer, self.transaction_repository.observers) + + +if __name__ == "__main__": + unittest.main() From e8c79a0f026254394b7eb1218102282e80bb6b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 20 Apr 2022 16:18:22 +0200 Subject: [PATCH 08/75] ISSUE #63 * Replace `patch` by `patch.object`. --- .../test_transactions/test_entries.py | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py index 62e1223bb..f8e8625e9 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py @@ -18,6 +18,7 @@ TRANSACTION_CONTEXT_VAR, Action, EventEntry, + EventRepository, TransactionEntry, TransactionRepositoryConflictException, TransactionStatus, @@ -64,8 +65,8 @@ async def test_async_context_manager_with_context_var(self): self.assertEqual(TRANSACTION_CONTEXT_VAR.get(), None) async def test_async_context_manager(self): - with patch("minos.aggregate.TransactionEntry.save") as save_mock, patch( - "minos.aggregate.TransactionEntry.commit" + with patch.object(TransactionEntry, "save") as save_mock, patch.object( + TransactionEntry, "commit" ) as commit_mock: async with TransactionEntry(): self.assertEqual(1, save_mock.call_count) @@ -74,7 +75,7 @@ async def test_async_context_manager(self): self.assertEqual(1, commit_mock.call_count) async def test_async_context_manager_without_autocommit(self): - with patch("minos.aggregate.TransactionEntry.commit") as commit_mock: + with patch.object(TransactionEntry, "commit") as commit_mock: async with TransactionEntry(autocommit=False) as transaction: self.assertEqual(0, commit_mock.call_count) transaction.status = TransactionStatus.PENDING @@ -109,10 +110,10 @@ async def test_reserve_success(self) -> None: transaction = TransactionEntry(uuid, TransactionStatus.PENDING) - with patch( - "minos.aggregate.EventRepository.offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) - ), patch("minos.aggregate.TransactionEntry.save") as save_mock, patch( - "minos.aggregate.TransactionEntry.validate", return_value=True + with patch.object( + EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) + ), patch.object(TransactionEntry, "save") as save_mock, patch.object( + TransactionEntry, "validate", return_value=True ) as validate_mock: await transaction.reserve() @@ -128,10 +129,10 @@ async def test_reserve_failure(self) -> None: uuid = uuid4() transaction = TransactionEntry(uuid, TransactionStatus.PENDING) - with patch( - "minos.aggregate.EventRepository.offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) - ), patch("minos.aggregate.TransactionEntry.save") as save_mock, patch( - "minos.aggregate.TransactionEntry.validate", return_value=False + with patch.object( + EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) + ), patch.object(TransactionEntry, "save") as save_mock, patch.object( + TransactionEntry, "validate", return_value=False ) as validate_mock: with self.assertRaises(TransactionRepositoryConflictException): await transaction.reserve() @@ -378,9 +379,9 @@ async def test_reject(self) -> None: transaction = TransactionEntry(uuid, TransactionStatus.RESERVED) - with patch( - "minos.aggregate.EventRepository.offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) - ), patch("minos.aggregate.TransactionEntry.save") as save_mock: + with patch.object( + EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) + ), patch.object(TransactionEntry, "save") as save_mock: await transaction.reject() self.assertEqual(1, save_mock.call_count) @@ -410,9 +411,9 @@ async def _fn(*args, **kwargs): transaction = TransactionEntry(uuid, TransactionStatus.RESERVED) - with patch( - "minos.aggregate.EventRepository.offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) - ), patch("minos.aggregate.TransactionEntry.save") as save_mock: + with patch.object( + EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) + ), patch.object(TransactionEntry, "save") as save_mock: await transaction.commit() self.assertEqual( @@ -437,12 +438,12 @@ async def test_commit_pending(self) -> None: async def _fn(): transaction.status = TransactionStatus.RESERVED - with patch( - "minos.aggregate.EventRepository.offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) - ), patch("minos.aggregate.TransactionEntry.reserve", side_effect=_fn) as reserve_mock, patch( - "minos.aggregate.TransactionEntry.save" - ) as save_mock, patch( - "minos.aggregate.TransactionEntry._commit", return_value=True + with patch.object( + EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) + ), patch.object(TransactionEntry, "reserve", side_effect=_fn) as reserve_mock, patch.object( + TransactionEntry, "save" + ) as save_mock, patch.object( + TransactionEntry, "_commit", return_value=True ) as commit_mock: await transaction.commit() From 793f29615036e75737c0ce4cd3e1454a4db6381b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 20 Apr 2022 17:05:04 +0200 Subject: [PATCH 09/75] ISSUE #63 * Improve tests. --- .../minos/aggregate/transactions/entries.py | 9 +- .../test_events/test_repositories/test_abc.py | 58 +++++++ .../test_transactions/test_entries.py | 156 ++++-------------- 3 files changed, 93 insertions(+), 130 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py index ed18e5ea4..72a79e0ed 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py @@ -146,7 +146,10 @@ async def commit(self) -> None: async def _commit(self) -> None: for subscriber in self._repository.observers: - await subscriber.commit_transaction(self.uuid, self.destination_uuid) + await subscriber.commit_transaction( + transaction_uuid=self.uuid, + destination_transaction_uuid=self.destination_uuid, + ) async def reserve(self) -> None: """Reserve transaction changes to be ensured that they can be applied. @@ -196,7 +199,7 @@ async def validate(self) -> bool: transaction_uuids = set() for subscriber in self._repository.observers: - transaction_uuids |= await subscriber.get_related_transactions(self.uuid) + transaction_uuids |= await subscriber.get_related_transactions(transaction_uuid=self.uuid) if len(transaction_uuids): if self.destination_uuid in transaction_uuids: @@ -232,7 +235,7 @@ async def reject(self) -> None: async with self._repository.write_lock(): for subscriber in self._repository.observers: - await subscriber.reject_transaction(self.uuid) + await subscriber.reject_transaction(transaction_uuid=self.uuid) await self.save(status=TransactionStatus.REJECTED) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py index f65484232..3002f8aed 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py @@ -500,6 +500,64 @@ async def test_offset(self): self.assertEqual(56, await self.event_repository.offset) self.assertEqual(1, mock.call_count) + async def test_get_related_transactions(self): + uuid = uuid4() + another = uuid4() + + agg_uuid = uuid4() + + select_event_1 = [ + EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), + EventEntry(agg_uuid, "c.Car", 3, bytes(), 2, Action.UPDATE, transaction_uuid=uuid), + EventEntry(agg_uuid, "c.Car", 2, bytes(), 3, Action.UPDATE, transaction_uuid=uuid), + ] + + select_event_2 = [ + EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), + EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=another), + ] + + select_event_mock = MagicMock( + side_effect=[FakeAsyncIterator(select_event_1), FakeAsyncIterator(select_event_2)] + ) + self.event_repository.select = select_event_mock + + expected = {another} + observed = await self.event_repository.get_related_transactions(uuid) + self.assertEqual(expected, observed) + + self.assertEqual( + [call(transaction_uuid=uuid), call(uuid=agg_uuid, version=3)], select_event_mock.call_args_list + ) + + async def test_commit(self) -> None: + uuid = uuid4() + + agg_uuid = uuid4() + + async def _fn(*args, **kwargs): + yield EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid) + yield EventEntry(agg_uuid, "c.Car", 3, bytes(), 2, Action.UPDATE, transaction_uuid=uuid) + yield EventEntry(agg_uuid, "c.Car", 2, bytes(), 3, Action.UPDATE, transaction_uuid=uuid) + + select_mock = MagicMock(side_effect=_fn) + submit_mock = AsyncMock() + + self.event_repository.select = select_mock + self.event_repository.submit = submit_mock + + with patch.object(EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55)): + await self.event_repository.commit_transaction(uuid, NULL_UUID) + + self.assertEqual( + [ + call(EventEntry(agg_uuid, "c.Car", 1, bytes(), action=Action.CREATE), transaction_uuid_ne=uuid), + call(EventEntry(agg_uuid, "c.Car", 3, bytes(), action=Action.UPDATE), transaction_uuid_ne=uuid), + call(EventEntry(agg_uuid, "c.Car", 2, bytes(), action=Action.UPDATE), transaction_uuid_ne=uuid), + ], + submit_mock.call_args_list, + ) + if __name__ == "__main__": unittest.main() diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py index f8e8625e9..416b3bf2c 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py @@ -5,7 +5,6 @@ from unittest.mock import ( AsyncMock, MagicMock, - PropertyMock, call, patch, ) @@ -16,9 +15,7 @@ from minos.aggregate import ( TRANSACTION_CONTEXT_VAR, - Action, - EventEntry, - EventRepository, + TransactionalMixin, TransactionEntry, TransactionRepositoryConflictException, TransactionStatus, @@ -110,9 +107,7 @@ async def test_reserve_success(self) -> None: transaction = TransactionEntry(uuid, TransactionStatus.PENDING) - with patch.object( - EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) - ), patch.object(TransactionEntry, "save") as save_mock, patch.object( + with patch.object(TransactionEntry, "save") as save_mock, patch.object( TransactionEntry, "validate", return_value=True ) as validate_mock: await transaction.reserve() @@ -129,9 +124,7 @@ async def test_reserve_failure(self) -> None: uuid = uuid4() transaction = TransactionEntry(uuid, TransactionStatus.PENDING) - with patch.object( - EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) - ), patch.object(TransactionEntry, "save") as save_mock, patch.object( + with patch.object(TransactionEntry, "save") as save_mock, patch.object( TransactionEntry, "validate", return_value=False ) as validate_mock: with self.assertRaises(TransactionRepositoryConflictException): @@ -157,36 +150,17 @@ async def test_validate_true(self): uuid = uuid4() another = uuid4() - agg_uuid = uuid4() - - select_event_1 = [ - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 3, bytes(), 2, Action.UPDATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 2, bytes(), 3, Action.UPDATE, transaction_uuid=uuid), - ] - - select_event_2 = [ - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=another), - ] - - transaction_event_1 = [] + observer_mock = AsyncMock(return_value={another}) + select_transaction_mock = MagicMock(return_value=FakeAsyncIterator([])) - select_event_mock = MagicMock( - side_effect=[FakeAsyncIterator(select_event_1), FakeAsyncIterator(select_event_2)] - ) - select_transaction_mock = MagicMock(return_value=FakeAsyncIterator(transaction_event_1)) - - self.event_repository.select = select_event_mock + self.event_repository.get_related_transactions = observer_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid) self.assertTrue(await transaction.validate()) - self.assertEqual( - [call(transaction_uuid=uuid), call(uuid=agg_uuid, version=3)], select_event_mock.call_args_list - ) + self.assertEqual([call(transaction_uuid=uuid)], observer_mock.call_args_list) self.assertEqual( [ call( @@ -217,27 +191,12 @@ async def test_validate_false_destination_already(self): uuid = uuid4() another = uuid4() - agg_uuid = uuid4() - - select_event_1 = [ - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 3, bytes(), 2, Action.UPDATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 2, bytes(), 3, Action.UPDATE, transaction_uuid=uuid), - ] - - select_event_2 = [ - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=another), - ] - transaction_event_1 = [TransactionEntry(another, TransactionStatus.RESERVED)] - select_event_mock = MagicMock( - side_effect=[FakeAsyncIterator(select_event_1), FakeAsyncIterator(select_event_2)] - ) + select_event_mock = AsyncMock(return_value={another}) select_transaction_mock = MagicMock(return_value=FakeAsyncIterator(transaction_event_1)) - self.event_repository.select = select_event_mock + self.event_repository.get_related_transactions = select_event_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid, destination_uuid=another) @@ -264,38 +223,21 @@ async def test_validate_false_destination_already(self): async def test_validate_false_already_committed(self): uuid = uuid4() - agg_uuid = uuid4() - - select_event_1 = [ - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 3, bytes(), 2, Action.UPDATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 2, bytes(), 3, Action.UPDATE, transaction_uuid=uuid), - ] - - select_event_2 = [ - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE), - ] - select_transaction_1 = [] - select_event_mock = MagicMock( - side_effect=[FakeAsyncIterator(select_event_1), FakeAsyncIterator(select_event_2)] - ) + select_event_mock = AsyncMock(return_value={NULL_UUID}) select_transaction_mock = MagicMock( side_effect=[FakeAsyncIterator([]), FakeAsyncIterator(select_transaction_1)], ) - self.event_repository.select = select_event_mock + self.event_repository.get_related_transactions = select_event_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid) self.assertFalse(await transaction.validate()) - self.assertEqual( - [call(transaction_uuid=uuid), call(uuid=agg_uuid, version=3)], select_event_mock.call_args_list - ) + self.assertEqual([call(transaction_uuid=uuid)], select_event_mock.call_args_list) self.assertEqual( [ call( @@ -316,38 +258,21 @@ async def test_validate_false_already_reserved(self): uuid = uuid4() another = uuid4() - agg_uuid = uuid4() - - select_event_1 = [ - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 3, bytes(), 2, Action.UPDATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 2, bytes(), 3, Action.UPDATE, transaction_uuid=uuid), - ] - - select_event_2 = [ - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=another), - ] - select_transaction_1 = [TransactionEntry(another, TransactionStatus.RESERVED)] - select_event_mock = MagicMock( - side_effect=[FakeAsyncIterator(select_event_1), FakeAsyncIterator(select_event_2)] - ) + select_event_mock = AsyncMock(return_value={another}) select_transaction_mock = MagicMock( side_effect=[FakeAsyncIterator([]), FakeAsyncIterator(select_transaction_1)], ) - self.event_repository.select = select_event_mock + self.event_repository.get_related_transactions = select_event_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid) self.assertFalse(await transaction.validate()) - self.assertEqual( - [call(transaction_uuid=uuid), call(uuid=agg_uuid, version=3)], select_event_mock.call_args_list - ) + self.assertEqual([call(transaction_uuid=uuid)], select_event_mock.call_args_list) self.assertEqual( [ call( @@ -379,13 +304,13 @@ async def test_reject(self) -> None: transaction = TransactionEntry(uuid, TransactionStatus.RESERVED) - with patch.object( - EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) - ), patch.object(TransactionEntry, "save") as save_mock: + with patch.object(TransactionalMixin, "reject_transaction") as observable_mock, patch.object( + TransactionEntry, "save" + ) as save_mock: await transaction.reject() - self.assertEqual(1, save_mock.call_count) - self.assertEqual(call(status=TransactionStatus.REJECTED), save_mock.call_args) + self.assertEqual([call(transaction_uuid=transaction.uuid)], observable_mock.call_args_list) + self.assertEqual([call(status=TransactionStatus.REJECTED)], save_mock.call_args_list) async def test_reject_raises(self) -> None: with self.assertRaises(ValueError): @@ -395,34 +320,20 @@ async def test_reject_raises(self) -> None: async def test_commit(self) -> None: uuid = uuid4() + another = uuid4() - agg_uuid = uuid4() - - async def _fn(*args, **kwargs): - yield EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid) - yield EventEntry(agg_uuid, "c.Car", 3, bytes(), 2, Action.UPDATE, transaction_uuid=uuid) - yield EventEntry(agg_uuid, "c.Car", 2, bytes(), 3, Action.UPDATE, transaction_uuid=uuid) + commit_transaction = AsyncMock() - select_mock = MagicMock(side_effect=_fn) - submit_mock = AsyncMock() + self.event_repository.commit_transaction = commit_transaction - self.event_repository.select = select_mock - self.event_repository.submit = submit_mock - - transaction = TransactionEntry(uuid, TransactionStatus.RESERVED) + transaction = TransactionEntry(uuid, TransactionStatus.RESERVED, destination_uuid=another) - with patch.object( - EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) - ), patch.object(TransactionEntry, "save") as save_mock: + with patch.object(TransactionEntry, "save") as save_mock: await transaction.commit() self.assertEqual( - [ - call(EventEntry(agg_uuid, "c.Car", 1, bytes(), action=Action.CREATE), transaction_uuid_ne=uuid), - call(EventEntry(agg_uuid, "c.Car", 3, bytes(), action=Action.UPDATE), transaction_uuid_ne=uuid), - call(EventEntry(agg_uuid, "c.Car", 2, bytes(), action=Action.UPDATE), transaction_uuid_ne=uuid), - ], - submit_mock.call_args_list, + [call(transaction_uuid=uuid, destination_transaction_uuid=another)], + commit_transaction.call_args_list, ) self.assertEqual( @@ -438,13 +349,9 @@ async def test_commit_pending(self) -> None: async def _fn(): transaction.status = TransactionStatus.RESERVED - with patch.object( - EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55) - ), patch.object(TransactionEntry, "reserve", side_effect=_fn) as reserve_mock, patch.object( + with patch.object(TransactionEntry, "reserve", side_effect=_fn) as reserve_mock, patch.object( TransactionEntry, "save" - ) as save_mock, patch.object( - TransactionEntry, "_commit", return_value=True - ) as commit_mock: + ) as save_mock, patch.object(TransactionEntry, "_commit", return_value=True) as commit_mock: await transaction.commit() self.assertEqual(1, reserve_mock.call_count) @@ -477,11 +384,6 @@ async def test_save(self) -> None: self.assertEqual(1, submit_mock.call_count) self.assertEqual(call(TransactionEntry(uuid, TransactionStatus.COMMITTED)), submit_mock.call_args) - # submit_mock.reset_mock() - # await TransactionEntry(uuid, TransactionStatus.PENDING).save(event_offset=56) - # self.assertEqual(1, submit_mock.call_count) - # self.assertEqual(call(TransactionEntry(uuid, TransactionStatus.PENDING, 56)), submit_mock.call_args) - async def test_uuids(self): first = TransactionEntry() await first.save() From 002e3dc1a31d8087dd76263d589f984808ce487d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 20 Apr 2022 17:17:18 +0200 Subject: [PATCH 10/75] ISSUE #63 * Improve `TransactionalMixin`. --- .../aggregate/events/repositories/abc.py | 4 ++-- .../minos/aggregate/transactions/entries.py | 2 +- .../minos/aggregate/transactions/mixins.py | 10 +++------- .../test_events/test_repositories/test_abc.py | 4 ++-- .../test_transactions/test_entries.py | 8 ++++---- .../test_transactions/test_mixins.py | 20 +++++++------------ .../test_repositories/test_abc.py | 15 ++------------ 7 files changed, 21 insertions(+), 42 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py index 1dc807616..ed4ce00c7 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py @@ -319,8 +319,8 @@ def write_lock(self) -> Lock: """ return self._lock_pool.acquire("aggregate_event_write_lock") - async def get_related_transactions(self, transaction_uuid: UUID) -> set[UUID]: - """Get the set of related transaction identifiers. + async def get_collided_transactions(self, transaction_uuid: UUID) -> set[UUID]: + """Get the set of collided transaction identifiers. :param transaction_uuid: The identifier of the transaction to be committed. :return: A ``set`` or ``UUID`` values. diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py index 72a79e0ed..84e45acf2 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py @@ -199,7 +199,7 @@ async def validate(self) -> bool: transaction_uuids = set() for subscriber in self._repository.observers: - transaction_uuids |= await subscriber.get_related_transactions(transaction_uuid=self.uuid) + transaction_uuids |= await subscriber.get_collided_transactions(transaction_uuid=self.uuid) if len(transaction_uuids): if self.destination_uuid in transaction_uuids: diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py index 10d7b5387..10689ef8e 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py @@ -1,6 +1,3 @@ -from abc import ( - abstractmethod, -) from typing import ( Optional, ) @@ -52,15 +49,14 @@ def _register_into_transaction_repository(self) -> None: def _unregister_from_transaction_repository(self) -> None: self._transaction_repository.unregister_observer(self) - @abstractmethod - async def get_related_transactions(self, transaction_uuid: UUID) -> set[UUID]: - """Get the set of related transaction identifiers. + async def get_collided_transactions(self, transaction_uuid: UUID) -> set[UUID]: + """Get the set of collided transaction identifiers. :param transaction_uuid: The identifier of the transaction to be committed. :return: A ``set`` or ``UUID`` values. """ + return set() - @abstractmethod async def commit_transaction(self, transaction_uuid: UUID, destination_transaction_uuid: UUID) -> None: """Commit the transaction with given identifier. diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py index 3002f8aed..19f160822 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py @@ -500,7 +500,7 @@ async def test_offset(self): self.assertEqual(56, await self.event_repository.offset) self.assertEqual(1, mock.call_count) - async def test_get_related_transactions(self): + async def test_get_collided_transactions(self): uuid = uuid4() another = uuid4() @@ -523,7 +523,7 @@ async def test_get_related_transactions(self): self.event_repository.select = select_event_mock expected = {another} - observed = await self.event_repository.get_related_transactions(uuid) + observed = await self.event_repository.get_collided_transactions(uuid) self.assertEqual(expected, observed) self.assertEqual( diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py index 416b3bf2c..a27ae3e3a 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py @@ -153,7 +153,7 @@ async def test_validate_true(self): observer_mock = AsyncMock(return_value={another}) select_transaction_mock = MagicMock(return_value=FakeAsyncIterator([])) - self.event_repository.get_related_transactions = observer_mock + self.event_repository.get_collided_transactions = observer_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid) @@ -196,7 +196,7 @@ async def test_validate_false_destination_already(self): select_event_mock = AsyncMock(return_value={another}) select_transaction_mock = MagicMock(return_value=FakeAsyncIterator(transaction_event_1)) - self.event_repository.get_related_transactions = select_event_mock + self.event_repository.get_collided_transactions = select_event_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid, destination_uuid=another) @@ -230,7 +230,7 @@ async def test_validate_false_already_committed(self): side_effect=[FakeAsyncIterator([]), FakeAsyncIterator(select_transaction_1)], ) - self.event_repository.get_related_transactions = select_event_mock + self.event_repository.get_collided_transactions = select_event_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid) @@ -265,7 +265,7 @@ async def test_validate_false_already_reserved(self): side_effect=[FakeAsyncIterator([]), FakeAsyncIterator(select_transaction_1)], ) - self.event_repository.get_related_transactions = select_event_mock + self.event_repository.get_collided_transactions = select_event_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_mixins.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_mixins.py index d7c9bedfb..78ed050e6 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_mixins.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_mixins.py @@ -1,6 +1,6 @@ import unittest from uuid import ( - UUID, + uuid4, ) from minos.aggregate import ( @@ -14,31 +14,25 @@ ) -class _Observer(TransactionalMixin): - """For testing purposes.""" - - async def get_related_transactions(self, transaction_uuid: UUID) -> set[UUID]: - """For testing purposes.""" - - async def commit_transaction(self, transaction_uuid: UUID, destination_transaction_uuid: UUID) -> None: - """For testing purposes.""" - - class TestTransactionalMixin(AggregateTestCase): def test_abstract(self) -> None: self.assertTrue(issubclass(TransactionalMixin, SetupMixin)) def test_constructor(self): - observer = _Observer() + observer = TransactionalMixin() self.assertEqual(self.transaction_repository, observer.transaction_repository) async def test_register_into_observable(self): - observer = _Observer() + observer = TransactionalMixin() self.assertNotIn(observer, self.transaction_repository.observers) async with observer: self.assertIn(observer, self.transaction_repository.observers) self.assertNotIn(observer, self.transaction_repository.observers) + async def test_get_collided_transactions(self): + mixin = TransactionalMixin() + self.assertEqual(set(), await mixin.get_collided_transactions(uuid4())) + if __name__ == "__main__": unittest.main() diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py index 03ed3f85a..6ecd4c59d 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py @@ -11,7 +11,6 @@ call, ) from uuid import ( - UUID, uuid4, ) @@ -43,16 +42,6 @@ def _select(self, **kwargs) -> AsyncIterator[TransactionEntry]: """For testing purposes.""" -class _Observer(TransactionalMixin): - """For testing purposes.""" - - async def get_related_transactions(self, transaction_uuid: UUID) -> set[UUID]: - """For testing purposes.""" - - async def commit_transaction(self, transaction_uuid: UUID, destination_transaction_uuid: UUID) -> None: - """For testing purposes.""" - - class TestTransactionRepository(AggregateTestCase): def setUp(self) -> None: super().setUp() @@ -72,13 +61,13 @@ def test_observers_empty(self): self.assertEqual(set(), self.transaction_repository.observers) def test_register_observer(self): - observer1, observer2 = _Observer(), _Observer() + observer1, observer2 = TransactionalMixin(), TransactionalMixin() self.transaction_repository.register_observer(observer1) self.transaction_repository.register_observer(observer2) self.assertEqual({observer1, observer2}, self.transaction_repository.observers) def test_unregister_observer(self): - observer1, observer2 = _Observer(), _Observer() + observer1, observer2 = TransactionalMixin(), TransactionalMixin() self.transaction_repository.register_observer(observer1) self.transaction_repository.register_observer(observer2) self.assertEqual({observer1, observer2}, self.transaction_repository.observers) From 36fcd1d438347437f6f2c09d0daeca6f5a27b3b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 20 Apr 2022 17:30:10 +0200 Subject: [PATCH 11/75] ISSUE #65 * Add `minos-microservice-transactions` package skeleton. --- .../AUTHORS.md | 15 + .../HISTORY.md | 1 + .../minos-microservice-transactions/LICENSE | 21 + .../minos-microservice-transactions/Makefile | 37 + .../minos-microservice-transactions/README.md | 36 + .../RUNTHETESTS.md | 20 + .../minos/transactions/__init__.py | 5 + .../poetry.lock | 725 ++++++++++++++++++ .../poetry.toml | 2 + .../pyproject.toml | 47 ++ .../minos-microservice-transactions/setup.cfg | 28 + .../tests/__init__.py | 0 .../tests/test_config.yml | 9 + .../tests/test_transactions/__init__.py | 0 .../tests/utils.py | 67 ++ 15 files changed, 1013 insertions(+) create mode 100644 packages/core/minos-microservice-transactions/AUTHORS.md create mode 100644 packages/core/minos-microservice-transactions/HISTORY.md create mode 100644 packages/core/minos-microservice-transactions/LICENSE create mode 100644 packages/core/minos-microservice-transactions/Makefile create mode 100644 packages/core/minos-microservice-transactions/README.md create mode 100644 packages/core/minos-microservice-transactions/RUNTHETESTS.md create mode 100644 packages/core/minos-microservice-transactions/minos/transactions/__init__.py create mode 100644 packages/core/minos-microservice-transactions/poetry.lock create mode 100644 packages/core/minos-microservice-transactions/poetry.toml create mode 100644 packages/core/minos-microservice-transactions/pyproject.toml create mode 100644 packages/core/minos-microservice-transactions/setup.cfg create mode 100644 packages/core/minos-microservice-transactions/tests/__init__.py create mode 100644 packages/core/minos-microservice-transactions/tests/test_config.yml create mode 100644 packages/core/minos-microservice-transactions/tests/test_transactions/__init__.py create mode 100644 packages/core/minos-microservice-transactions/tests/utils.py diff --git a/packages/core/minos-microservice-transactions/AUTHORS.md b/packages/core/minos-microservice-transactions/AUTHORS.md new file mode 100644 index 000000000..30ff94991 --- /dev/null +++ b/packages/core/minos-microservice-transactions/AUTHORS.md @@ -0,0 +1,15 @@ +# Credits + +## Development Lead + +* Andrea Mucci + +## Core Devs + +* Sergio Garcia Prado +* Vladyslav Fenchak +* Alberto Amigo Alonso + +## Contributors + +None yet. Why not be the first? diff --git a/packages/core/minos-microservice-transactions/HISTORY.md b/packages/core/minos-microservice-transactions/HISTORY.md new file mode 100644 index 000000000..e061a5372 --- /dev/null +++ b/packages/core/minos-microservice-transactions/HISTORY.md @@ -0,0 +1 @@ +# History diff --git a/packages/core/minos-microservice-transactions/LICENSE b/packages/core/minos-microservice-transactions/LICENSE new file mode 100644 index 000000000..4daf85bf2 --- /dev/null +++ b/packages/core/minos-microservice-transactions/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Clariteia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/core/minos-microservice-transactions/Makefile b/packages/core/minos-microservice-transactions/Makefile new file mode 100644 index 000000000..ef814b8bc --- /dev/null +++ b/packages/core/minos-microservice-transactions/Makefile @@ -0,0 +1,37 @@ +.PHONY: docs dist + +lint: + poetry run flake8 + +test: + poetry run pytest + +coverage: + poetry run coverage run -m pytest + poetry run coverage report -m + poetry run coverage xml + +reformat: + poetry run black --line-length 120 minos tests + poetry run isort minos tests + +release: + $(MAKE) dist + poetry publish + +dist: + poetry build + ls -l dist + +install: + poetry install + +update: + poetry update + +check: + $(MAKE) install + $(MAKE) reformat + $(MAKE) lint + $(MAKE) test + $(MAKE) dist diff --git a/packages/core/minos-microservice-transactions/README.md b/packages/core/minos-microservice-transactions/README.md new file mode 100644 index 000000000..2fc738247 --- /dev/null +++ b/packages/core/minos-microservice-transactions/README.md @@ -0,0 +1,36 @@ +

+ Minos logo +

+ +## minos-microservice-transactions + +[![PyPI Latest Release](https://img.shields.io/pypi/v/minos-microservice-transactions.svg)](https://pypi.org/project/minos-microservice-transactions/) +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/minos-framework/minos-python/pages%20build%20and%20deployment?label=docs)](https://minos-framework.github.io/minos-python) +[![License](https://img.shields.io/github/license/minos-framework/minos-python.svg)](https://github.com/minos-framework/minos-python/blob/main/LICENSE) +[![Coverage](https://codecov.io/github/minos-framework/minos-python/coverage.svg?branch=main)](https://codecov.io/gh/minos-framework/minos-python) +[![Stack Overflow](https://img.shields.io/badge/Stack%20Overflow-Ask%20a%20question-green)](https://stackoverflow.com/questions/tagged/minos) + +## Summary + +Minos is a framework which helps you create [reactive](https://www.reactivemanifesto.org/) microservices in Python. +Internally, it leverages Event Sourcing, CQRS and a message driven architecture to fulfil the commitments of an +asynchronous environment. + +## Documentation + +The official API Reference is publicly available at the [GitHub Pages](https://minos-framework.github.io/minos-python). + +## Source Code + +The source code of this project is hosted at the [GitHub Repository](https://github.com/minos-framework/minos-python). + +## Getting Help + +For usage questions, the best place to go to is [StackOverflow](https://stackoverflow.com/questions/tagged/minos). + +## Discussion and Development +Most development discussions take place over the [GitHub Issues](https://github.com/minos-framework/minos-python/issues). In addition, a [Gitter channel](https://gitter.im/minos-framework/community) is available for development-related questions. + +## License + +This project is distributed under the [MIT](https://raw.githubusercontent.com/minos-framework/minos-python/main/LICENSE) license. diff --git a/packages/core/minos-microservice-transactions/RUNTHETESTS.md b/packages/core/minos-microservice-transactions/RUNTHETESTS.md new file mode 100644 index 000000000..386e2b0e7 --- /dev/null +++ b/packages/core/minos-microservice-transactions/RUNTHETESTS.md @@ -0,0 +1,20 @@ +# Run the tests + +In order to run the tests, please make sure you have the `Docker Engine `_ +and `Docker Compose `_ installed. + +Move into tests/ directory + +`cd tests/` + +Run service dependencies: + +`docker-compose up -d` + +Install library dependencies: + +`make install` + +Run tests: + +`make test` diff --git a/packages/core/minos-microservice-transactions/minos/transactions/__init__.py b/packages/core/minos-microservice-transactions/minos/transactions/__init__.py new file mode 100644 index 000000000..2f933ee0d --- /dev/null +++ b/packages/core/minos-microservice-transactions/minos/transactions/__init__.py @@ -0,0 +1,5 @@ +"""The transactions core of the Minos Framework.""" + +__author__ = "Minos Framework Devs" +__email__ = "hey@minos.run" +__version__ = "0.7.0.dev1" diff --git a/packages/core/minos-microservice-transactions/poetry.lock b/packages/core/minos-microservice-transactions/poetry.lock new file mode 100644 index 000000000..4817307d2 --- /dev/null +++ b/packages/core/minos-microservice-transactions/poetry.lock @@ -0,0 +1,725 @@ +[[package]] +name = "aiomisc" +version = "15.7.3" +description = "aiomisc - miscellaneous utils for asyncio" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +colorlog = "*" + +[package.extras] +aiohttp = ["aiohttp"] +asgi = ["aiohttp-asgi"] +carbon = ["aiocarbon (>=0.15,<1.0)"] +contextvars = ["contextvars (>=2.4,<3.0)"] +cron = ["croniter (>=0.3.34,<0.4.0)"] +develop = ["aiocontextvars (==0.2.2)", "aiohttp-asgi", "aiohttp (<4)", "async-timeout", "coveralls", "croniter (>=0.3.34,<0.4.0)", "fastapi", "freezegun (<1.1)", "mypy (>=0.782,<1.0)", "pylava", "pytest", "pytest-cov (>=3.0,<4.0)", "pytest-freezegun (>=0.4.2,<0.5.0)", "pytest-rst", "pytest-subtests", "rich", "setproctitle", "sphinx-autobuild", "sphinx-intl", "sphinx (>=3.5.1)", "timeout-decorator", "tox (>=2.4)", "types-croniter"] +raven = ["raven-aiohttp"] +uvloop = ["uvloop (>=0.14,<1)"] + +[[package]] +name = "atomicwrites" +version = "1.4.0" +description = "Atomic file writes." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "attrs" +version = "21.4.0" +description = "Classes Without Boilerplate" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.extras] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] + +[[package]] +name = "black" +version = "22.3.0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.6.2" + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "cached-property" +version = "1.5.2" +description = "A decorator for caching properties in classes." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "click" +version = "8.1.2" +description = "Composable command line interface toolkit" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.4" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "colorlog" +version = "6.6.0" +description = "Add colours to the output of Python's logging module." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +development = ["black", "flake8", "mypy", "pytest", "types-colorama"] + +[[package]] +name = "coverage" +version = "6.3.2" +description = "Code coverage measurement for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "dependency-injector" +version = "4.39.1" +description = "Dependency injection framework for Python" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = ">=1.7.0,<=1.16.0" + +[package.extras] +aiohttp = ["aiohttp"] +flask = ["flask"] +pydantic = ["pydantic"] +yaml = ["pyyaml"] + +[[package]] +name = "fastavro" +version = "1.4.10" +description = "Fast read/write of AVRO files" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +codecs = ["python-snappy", "zstandard", "lz4"] +lz4 = ["lz4"] +snappy = ["python-snappy"] +zstandard = ["zstandard"] + +[[package]] +name = "flake8" +version = "4.0.1" +description = "the modular source code checker: pep8 pyflakes and co" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +mccabe = ">=0.6.0,<0.7.0" +pycodestyle = ">=2.8.0,<2.9.0" +pyflakes = ">=2.4.0,<2.5.0" + +[[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "isort" +version = "5.10.1" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.6.1,<4.0" + +[package.extras] +pipfile_deprecated_finder = ["pipreqs", "requirementslib"] +requirements_deprecated_finder = ["pipreqs", "pip-api"] +colors = ["colorama (>=0.4.3,<0.5.0)"] +plugins = ["setuptools"] + +[[package]] +name = "lmdb" +version = "1.3.0" +description = "Universal Python binding for the LMDB 'Lightning' Database" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "mccabe" +version = "0.6.1" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "minos-microservice-common" +version = "0.7.0.dev1" +description = "The common core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +aiomisc = ">=14.0.3,<15.8.0" +cached-property = "^1.5.2" +dependency-injector = "^4.32.2" +fastavro = "^1.4.0" +lmdb = "^1.2.1" +orjson = "^3.5.2" +PyYAML = ">=5.4.1,<7.0.0" +uvloop = "^0.16.0" + +[package.source] +type = "directory" +url = "../minos-microservice-common" + +[[package]] +name = "mypy-extensions" +version = "0.4.3" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "orjson" +version = "3.6.8" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "packaging" +version = "21.3" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" + +[[package]] +name = "pathspec" +version = "0.9.0" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[[package]] +name = "platformdirs" +version = "2.5.2" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] +test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] + +[[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pycodestyle" +version = "2.8.0" +description = "Python style guide checker" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "pyflakes" +version = "2.4.0" +description = "passive checker of Python programs" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "pyparsing" +version = "3.0.8" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "dev" +optional = false +python-versions = ">=3.6.8" + +[package.extras] +diagrams = ["railroad-diagrams", "jinja2"] + +[[package]] +name = "pytest" +version = "7.1.1" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +tomli = ">=1.0.0" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "typing-extensions" +version = "4.2.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "uvloop" +version = "0.16.0" +description = "Fast implementation of asyncio event loop on top of libuv" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +dev = ["Cython (>=0.29.24,<0.30.0)", "pytest (>=3.6.0)", "Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,<2.8.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"] +docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)"] +test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,<2.8.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.9" +content-hash = "4c34a5eab6efb983f4ab2f609f54e5a8475bad1de65c75cce36989757379ea2d" + +[metadata.files] +aiomisc = [ + {file = "aiomisc-15.7.3-py3-none-any.whl", hash = "sha256:0403e83268e98d0f2a125a70d13303fe1a2358e36db3daf02df032c7fa4f1525"}, + {file = "aiomisc-15.7.3.tar.gz", hash = "sha256:ba250a34bd4609ced36111cb50580f57c3d52f3955f953a53ecb2986988baedc"}, +] +atomicwrites = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] +attrs = [ + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, +] +black = [ + {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"}, + {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"}, + {file = "black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a"}, + {file = "black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968"}, + {file = "black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"}, + {file = "black-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce"}, + {file = "black-22.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82"}, + {file = "black-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b"}, + {file = "black-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015"}, + {file = "black-22.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b"}, + {file = "black-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a"}, + {file = "black-22.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163"}, + {file = "black-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464"}, + {file = "black-22.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0"}, + {file = "black-22.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176"}, + {file = "black-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0"}, + {file = "black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20"}, + {file = "black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a"}, + {file = "black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad"}, + {file = "black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21"}, + {file = "black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265"}, + {file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"}, + {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"}, +] +cached-property = [ + {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, + {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, +] +click = [ + {file = "click-8.1.2-py3-none-any.whl", hash = "sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e"}, + {file = "click-8.1.2.tar.gz", hash = "sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"}, +] +colorama = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, +] +colorlog = [ + {file = "colorlog-6.6.0-py2.py3-none-any.whl", hash = "sha256:351c51e866c86c3217f08e4b067a7974a678be78f07f85fc2d55b8babde6d94e"}, + {file = "colorlog-6.6.0.tar.gz", hash = "sha256:344f73204009e4c83c5b6beb00b3c45dc70fcdae3c80db919e0a4171d006fde8"}, +] +coverage = [ + {file = "coverage-6.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf"}, + {file = "coverage-6.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9987b0354b06d4df0f4d3e0ec1ae76d7ce7cbca9a2f98c25041eb79eec766f1"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26e2deacd414fc2f97dd9f7676ee3eaecd299ca751412d89f40bc01557a6b1b4"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd8bafa458b5c7d061540f1ee9f18025a68e2d8471b3e858a9dad47c8d41903"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:46191097ebc381fbf89bdce207a6c107ac4ec0890d8d20f3360345ff5976155c"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6f89d05e028d274ce4fa1a86887b071ae1755082ef94a6740238cd7a8178804f"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:58303469e9a272b4abdb9e302a780072c0633cdcc0165db7eec0f9e32f901e05"}, + {file = "coverage-6.3.2-cp310-cp310-win32.whl", hash = "sha256:2fea046bfb455510e05be95e879f0e768d45c10c11509e20e06d8fcaa31d9e39"}, + {file = "coverage-6.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:a2a8b8bcc399edb4347a5ca8b9b87e7524c0967b335fbb08a83c8421489ddee1"}, + {file = "coverage-6.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f1555ea6d6da108e1999b2463ea1003fe03f29213e459145e70edbaf3e004aaa"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5f4e1edcf57ce94e5475fe09e5afa3e3145081318e5fd1a43a6b4539a97e518"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a15dc0a14008f1da3d1ebd44bdda3e357dbabdf5a0b5034d38fcde0b5c234b7"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b7745788866028adeb1e0eca3bf1101109e2dc58456cb49d2d9b99a8c516e6"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8ce257cac556cb03be4a248d92ed36904a59a4a5ff55a994e92214cde15c5bad"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b0be84e5a6209858a1d3e8d1806c46214e867ce1b0fd32e4ea03f4bd8b2e3359"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:acf53bc2cf7282ab9b8ba346746afe703474004d9e566ad164c91a7a59f188a4"}, + {file = "coverage-6.3.2-cp37-cp37m-win32.whl", hash = "sha256:8bdde1177f2311ee552f47ae6e5aa7750c0e3291ca6b75f71f7ffe1f1dab3dca"}, + {file = "coverage-6.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b31651d018b23ec463e95cf10070d0b2c548aa950a03d0b559eaa11c7e5a6fa3"}, + {file = "coverage-6.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d"}, + {file = "coverage-6.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c6dbb42f3ad25760010c45191e9757e7dce981cbfb90e42feef301d71540059"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76aeef1b95aff3905fb2ae2d96e319caca5b76fa41d3470b19d4e4a3a313512"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cf5cfcb1521dc3255d845d9dca3ff204b3229401994ef8d1984b32746bb45ca"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fbbdc8d55990eac1b0919ca69eb5a988a802b854488c34b8f37f3e2025fa90d"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ec6bc7fe73a938933d4178c9b23c4e0568e43e220aef9472c4f6044bfc6dd0f0"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9baff2a45ae1f17c8078452e9e5962e518eab705e50a0aa8083733ea7d45f3a6"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd9e830e9d8d89b20ab1e5af09b32d33e1a08ef4c4e14411e559556fd788e6b2"}, + {file = "coverage-6.3.2-cp38-cp38-win32.whl", hash = "sha256:f7331dbf301b7289013175087636bbaf5b2405e57259dd2c42fdcc9fcc47325e"}, + {file = "coverage-6.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:68353fe7cdf91f109fc7d474461b46e7f1f14e533e911a2a2cbb8b0fc8613cf1"}, + {file = "coverage-6.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b78e5afb39941572209f71866aa0b206c12f0109835aa0d601e41552f9b3e620"}, + {file = "coverage-6.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e21876082ed887baed0146fe222f861b5815455ada3b33b890f4105d806128d"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34626a7eee2a3da12af0507780bb51eb52dca0e1751fd1471d0810539cefb536"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ebf730d2381158ecf3dfd4453fbca0613e16eaa547b4170e2450c9707665ce7"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd6fe30bd519694b356cbfcaca9bd5c1737cddd20778c6a581ae20dc8c04def2"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96f8a1cb43ca1422f36492bebe63312d396491a9165ed3b9231e778d43a7fca4"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dd035edafefee4d573140a76fdc785dc38829fe5a455c4bb12bac8c20cfc3d69"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ca5aeb4344b30d0bec47481536b8ba1181d50dbe783b0e4ad03c95dc1296684"}, + {file = "coverage-6.3.2-cp39-cp39-win32.whl", hash = "sha256:f5fa5803f47e095d7ad8443d28b01d48c0359484fec1b9d8606d0e3282084bc4"}, + {file = "coverage-6.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9548f10d8be799551eb3a9c74bbf2b4934ddb330e08a73320123c07f95cc2d92"}, + {file = "coverage-6.3.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf"}, + {file = "coverage-6.3.2.tar.gz", hash = "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9"}, +] +dependency-injector = [ + {file = "dependency-injector-4.39.1.tar.gz", hash = "sha256:9ab76dc5e19b2692aaca49e00f9b41a087138d139b0ec985f92ff0498f038772"}, + {file = "dependency_injector-4.39.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c788a3d5482e63b5fd55e14fc258f1ff0b51b411927ab132ef0f689cb5d1183f"}, + {file = "dependency_injector-4.39.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0832e0457a360725cd1d1037b77b85478aeeaacc60e85ecceeb8020409e7b62"}, + {file = "dependency_injector-4.39.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d51998fff9704fd01d11c3c48f4e88d8506cb6afa1ee41409a881a5a51dae3fc"}, + {file = "dependency_injector-4.39.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea484cd13fc62966bf5582df0816205feee072d18f228aac75f7807b43f223ae"}, + {file = "dependency_injector-4.39.1-cp310-cp310-win32.whl", hash = "sha256:17389e53ec29ca13570319cf2065dcc4c2f6d36db5dd792bb1e8f2c39a9f146b"}, + {file = "dependency_injector-4.39.1-cp310-cp310-win_amd64.whl", hash = "sha256:55b0988489267c5a580f419133770ffe293057f2064da1c9ad6a2cc69666739b"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b297c3e79d3633cc56366386ae1f7dbce1587673cca2f559c368c1e936a1fa94"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2728827c5abb2420c5811e218262ae1b77a48e76cc9eebc6b4f55fee48a1a18d"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:029e42b064ab8cb5b2559be040ff682c7aa81592f1654a82355475956df17803"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:305e3db3f4bf40f64caaa1303e03005174e78d2339d2ae517b34c011ec2300f9"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-win32.whl", hash = "sha256:a661dd23a5e4e2f6bf4a729de7fadbe148c9a4a298dbcadfc5a94584b6930970"}, + {file = "dependency_injector-4.39.1-cp36-cp36m-win_amd64.whl", hash = "sha256:340d6e7af5c4729d20c837d6d1e8a2626c24a05259dff746406cc823e26ba1e7"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a1553dac1c95f0de1f910b0025ee4570ea078a07d576bcdc2168990e719cea50"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c7baaa64d93359ee08c15d68579cc803e11d9becaf961f5a66b94ff627248e1"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7a27bf1951a066cf347b886cc7ab0f37dcbd1ad59bffcfe721c8c12a189a150d"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da6e2d685f7d0c65257f08133b68d9bf74ec319b90a0f21b4f629d168ce5f68f"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-win32.whl", hash = "sha256:a8ddd03ca86e67e9d3cc038793d34fbfccab12e6145df813e72bf14f9371f2ea"}, + {file = "dependency_injector-4.39.1-cp37-cp37m-win_amd64.whl", hash = "sha256:e01a319ea05cd86b520201386dcb53a81a5400cb82fcc2f006bd7e92c0c51a0a"}, + {file = "dependency_injector-4.39.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4704804bde25b694aa65201927937a9d82d8bc055cb3dadc68eb05988bd34fa9"}, + {file = "dependency_injector-4.39.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0935d50b263169e7b0826a2fb6be80d6a4f2a7c59e6dd9876f86da3243bea9eb"}, + {file = "dependency_injector-4.39.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3c34aa5abb1826b6189f47daf6e469d4293c1d01693233da2c1b923816270cc5"}, + {file = "dependency_injector-4.39.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:db64904c9b9a88756cfece3e3ed078a2b57127642711dd08af342dba8abf9667"}, + {file = "dependency_injector-4.39.1-cp38-cp38-win32.whl", hash = "sha256:66ebe728194adc8720dbc4d662edbbfa55659ff23c9c493fb2dae0bfd4df5734"}, + {file = "dependency_injector-4.39.1-cp38-cp38-win_amd64.whl", hash = "sha256:4349974620f630d6726808e1291ec99713b64d449b84eb01581ee807a5a5c224"}, + {file = "dependency_injector-4.39.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d87cad0899b05cd08931bfb68ddf7be77711a67b0649c37f2045d7808977b082"}, + {file = "dependency_injector-4.39.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8efd965e5cfdd9f339ec895e73c119569851adedc175088d34a670f5206fea63"}, + {file = "dependency_injector-4.39.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:27f69485ca6b85c31d162ee86cf6ef71bb71dce9cd2b5d0745425dfc551eefa1"}, + {file = "dependency_injector-4.39.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a25b63de59dff04ec78f5161f00c0222a04a23def5d1f0eda14e389a32baf428"}, + {file = "dependency_injector-4.39.1-cp39-cp39-win32.whl", hash = "sha256:a14274f50d125b4579314c355e22af07def1a96641ca94bd75edcf1400b89477"}, + {file = "dependency_injector-4.39.1-cp39-cp39-win_amd64.whl", hash = "sha256:9950039d00625f9252cd26378a4406342b256886bb61e4db8b65e9f01270f53e"}, + {file = "dependency_injector-4.39.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6d7f39cd54678741e132e13da3a1367ac18058cbda61fe39d61c8583aa6fd757"}, + {file = "dependency_injector-4.39.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2368c7ba3c9ffaf816ea0f2d14c78d481491b805f62ac8496a78a51397d4689"}, + {file = "dependency_injector-4.39.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:84e32407bb16c58aa0d4b5ed8485537bc66ccc14cfffae7022f1204e35ec939a"}, + {file = "dependency_injector-4.39.1-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f2d80a42c546e1f934d427b071630d86653cd4a60c74b570c4ffb03025c1f1f9"}, + {file = "dependency_injector-4.39.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ca126bbed370b8c002c859ebeb76f6d83eba2d7fb5d66f37f47cfc19661d2889"}, +] +fastavro = [ + {file = "fastavro-1.4.10-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:f225c81e869b3cefef6f2b478cd452693181ed7e645be3cea4d82024354ecaa0"}, + {file = "fastavro-1.4.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7669302c9124b7cd6c1bdff80c77116b2290c984814077fb7d01d7389586054"}, + {file = "fastavro-1.4.10-cp310-cp310-win_amd64.whl", hash = "sha256:995525bdfbdfef205ea148b5bc6a9fe5ccf921931123c39d9aad75a2b661681e"}, + {file = "fastavro-1.4.10-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:64244c53f1e4853184c2f7383d0332e1dcb34c38c05e6613530ade0378e8acfc"}, + {file = "fastavro-1.4.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c60965da6dc7a91e00ccd84d84797fad746555f44e8a816c4cc460fb231c44fe"}, + {file = "fastavro-1.4.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10eb25378f37dc00c10e83c4c0442c1a6d1b871f74a6dfdfc12b6447962bbdd0"}, + {file = "fastavro-1.4.10-cp37-cp37m-win_amd64.whl", hash = "sha256:d5719adf6045fc743de5fa738d561a81e58dc782c94f1b16cb21b5dd6253e7fd"}, + {file = "fastavro-1.4.10-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:24c4a1a8cc92e135ecfcd9cbd1f6cfa088cbc74d78c18e02a609cb11fa33778d"}, + {file = "fastavro-1.4.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0934490b0c3bcfd6bcbacbcb5144c6b5e4298cda209fbb17c856adf5405127dd"}, + {file = "fastavro-1.4.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a23763d73412c077aee401a0368c64cbc23859e26711dbae78a3cf0227f65165"}, + {file = "fastavro-1.4.10-cp38-cp38-win_amd64.whl", hash = "sha256:09f1dfdd8192ae09e0f477d1f024d8054fccdb099ad495d2a796bcee3cadebd1"}, + {file = "fastavro-1.4.10-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:0c6695753fa3035bbd0fa5cb21bf1b5dad39483c669b32ca0bb55fb07c1ccc87"}, + {file = "fastavro-1.4.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35f960dbba04647d8d6d5616f879622d2a1e8a84eb2d2e02a883a22e0803463a"}, + {file = "fastavro-1.4.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9660878ca01e3dbbee12385c5902a2b6b12ecbb5af4733d1026175a14b1ef67f"}, + {file = "fastavro-1.4.10-cp39-cp39-win_amd64.whl", hash = "sha256:64cbd386e408b3bcb2de53b1f847163073eb0d0d0338db65f76051c6ba9a9bc1"}, + {file = "fastavro-1.4.10.tar.gz", hash = "sha256:a24f9dd803c44bfb599476b000f9bd0088f7ac2401e6c20818f38d8af12785a0"}, +] +flake8 = [ + {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, + {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, +] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] +isort = [ + {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, + {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, +] +lmdb = [ + {file = "lmdb-1.3.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:63cb73fe7ce9eb93d992d632c85a0476b4332670d9e6a2802b5062f603b7809f"}, + {file = "lmdb-1.3.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:abbc439cd9fe60ffd6197009087ea885ac150017dc85384093b1d376f83f0ec4"}, + {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6260a526e4ad85b1f374a5ba9475bf369fb07e7728ea6ec57226b02c40d1976b"}, + {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e568ae0887ae196340947d9800136e90feaed6b86a261ef01f01b2ba65fc8106"}, + {file = "lmdb-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6a816954d212f40fd15007cd81ab7a6bebb77436d949a6a9ae04af57fc127f3"}, + {file = "lmdb-1.3.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fa6439356e591d3249ab0e1778a6f8d8408e993f66dc911914c78208f5310309"}, + {file = "lmdb-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:c6adbd6f7f9048e97f31a069e652eb51020a81e80a0ce92dbb9810d21da2409a"}, + {file = "lmdb-1.3.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:eefb392f6b5cd43aada49258c5a79be11cb2c8cd3fc3e2d9319a1e0b9f906458"}, + {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a14aca2651c3af6f0d0a6b9168200eea0c8f2d27c40b01a442f33329a6e8dff"}, + {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfa4aa9c67f8aee89b23005e98d1f3f32490b6b905fd1cb604b207cbd5755ab"}, + {file = "lmdb-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7da05d70fcc6561ac6b09e9fb1bf64b7ca294652c64c8a2889273970cee796b9"}, + {file = "lmdb-1.3.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:008243762decf8f6c90430a9bced56290ebbcdb5e877d90e42343bb97033e494"}, + {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:17215a42a4b9814c383deabecb160581e4fb75d00198eef0e3cea54f230ffbea"}, + {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65334eafa5d430b18d81ebd5362559a41483c362e1931f6e1b15bab2ecb7d75d"}, + {file = "lmdb-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:18c69fabdaf04efaf246587739cc1062b3e57c6ef0743f5c418df89e5e7e7b9b"}, + {file = "lmdb-1.3.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:41318717ab5d15ad2d6d263d34fbf614a045210f64b25e59ce734bb2105e421f"}, + {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:df2724bad7820114a205472994091097d0fa65a3e5fff5a8e688d123fb8c6326"}, + {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddd590e1c7fcb395931aa3782fb89b9db4550ab2d81d006ecd239e0d462bc41"}, + {file = "lmdb-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:4172fba19417d7b29409beca7d73c067b54e5d8ab1fb9b51d7b4c1445d20a167"}, + {file = "lmdb-1.3.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2df38115dd9428a54d59ae7c712a4c7cce0d6b1d66056de4b1a8c38718066106"}, + {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9103aa4908f0bca43c5911ca067d4e3d01f682dff0c0381a1239bd2bd757984"}, + {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:394df860c3f93cfd92b6f4caba785f38208cc9614c18b3803f83a2cc1695042f"}, + {file = "lmdb-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:62ab28e3593bdc318ea2f2fa1574e5fca3b6d1f264686d773ba54a637d4f563b"}, + {file = "lmdb-1.3.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:e6a704b3baced9182836c7f77b769f23856f3a8f62d0282b1bc1feaf81a86712"}, + {file = "lmdb-1.3.0-pp27-pypy_73-win_amd64.whl", hash = "sha256:08f4b5129f4683802569b02581142e415c8dcc0ff07605983ec1b07804cecbad"}, + {file = "lmdb-1.3.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:f291e3f561f58dddf63a92a5a6a4b8af3a0920b6705d35e2f80e52e86ee238a2"}, + {file = "lmdb-1.3.0.tar.gz", hash = "sha256:60a11efc21aaf009d06518996360eed346f6000bfc9de05114374230879f992e"}, +] +mccabe = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] +minos-microservice-common = [] +mypy-extensions = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] +orjson = [ + {file = "orjson-3.6.8-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:3a287a650458de2211db03681b71c3e5cb2212b62f17a39df8ad99fc54855d0f"}, + {file = "orjson-3.6.8-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5204e25c12cea58e524fc82f7c27ed0586f592f777b33075a92ab7b3eb3687c2"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77e8386393add64f959c044e0fb682364fd0e611a6f477aa13f0e6a733bd6a28"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:279f2d2af393fdf8601020744cb206b91b54ad60fb8401e0761819c7bda1f4e4"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:c31c9f389be7906f978ed4192eb58a4b74a37ad60556a0b88ddc47c576697770"}, + {file = "orjson-3.6.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0db5c5a0c5b89f092d52f6e5a3701660a9d6ffa9e2968b3ce17c2bc4f5eb0414"}, + {file = "orjson-3.6.8-cp310-none-win_amd64.whl", hash = "sha256:eb22485847b9a0c4bbedc668df860126ac931edbed1d456cf41a59f3cb961ed8"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:1a5fe569310bc819279bd4d5f2c349910b104ed3207936246dd5d5e0b085e74a"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:ccb356a47ab1067cd3549847e9db1d279a63fe0482d315b3ffd6e7abef35ef77"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab29c069c222248ce302a25855b4e1664f9436e8ae5a131fb0859daf31676d2b"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d2b5e4cba9e774ac011071d9d27760f97f4b8cd46003e971d122e712f971345"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:c311ec504414d22834d5b972a209619925b48263856a11a14d90230f9682d49c"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:a3dfec7950b90fb8d143743503ee53fa06b32e6068bdea792fc866284da3d71d"}, + {file = "orjson-3.6.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b890dbbada2cbb26eb29bd43a848426f007f094bb0758df10dfe7a438e1cb4b4"}, + {file = "orjson-3.6.8-cp37-none-win_amd64.whl", hash = "sha256:9143ae2c52771525be9ad11a7a8cc8e7fd75391b107e7e644a9e0050496f6b4f"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:33a82199fd42f6436f833e210ae5129c922a5c355629356ca7a8e82964da7285"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:90159ea8b9a5a2a98fa33dc7b421cfac4d2ae91ba5e1058f5909e7f059f6b467"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:656fbe15d9ef0733e740d9def78f4fdb4153102f4836ee774a05123499005931"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7be3be6153843e0f01351b1313a5ad4723595427680dac2dfff22a37e652ce02"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:dd24f66b6697ee7424f7da575ec6cbffc8ede441114d53470949cda4d97c6e56"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:b07c780f7345ecf5901356dc21dee0669defc489c38ce7b9ab0f5e008cc0385c"}, + {file = "orjson-3.6.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ea32015a5d8a4ce00d348a0de5dc7040e0ad58f970a8fcbb5713a1eac129e493"}, + {file = "orjson-3.6.8-cp38-none-win_amd64.whl", hash = "sha256:c5a3e382194c838988ec128a26b08aa92044e5e055491cc4056142af0c1c54d7"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:83a8424e857ae1bf53530e88b4eb2f16ca2b489073b924e655f1575cacd7f52a"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:81e1a6a2d67f15007dadacbf9ba5d3d79237e5e33786c028557fe5a2b72f1c9a"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:137b539881c77866eba86ff6a11df910daf2eb9ab8f1acae62f879e83d7c38af"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cbd358f3b3ad539a27e36900e8e7d172d0e1b72ad9dd7d69544dcbc0f067ee7"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:6ab94701542d40b90903ecfc339333f458884979a01cb9268bc662cc67a5f6d8"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:32b6f26593a9eb606b40775826beb0dac152e3d224ea393688fced036045a821"}, + {file = "orjson-3.6.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:afd9e329ebd3418cac3cd747769b1d52daa25fa672bbf414ab59f0e0881b32b9"}, + {file = "orjson-3.6.8-cp39-none-win_amd64.whl", hash = "sha256:0c89b419914d3d1f65a1b0883f377abe42a6e44f6624ba1c63e8846cbfc2fa60"}, + {file = "orjson-3.6.8.tar.gz", hash = "sha256:e19d23741c5de13689bb316abfccea15a19c264e3ec8eb332a5319a583595ace"}, +] +packaging = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +pathspec = [ + {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, + {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, +] +platformdirs = [ + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, +] +pluggy = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] +pycodestyle = [ + {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, + {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, +] +pyflakes = [ + {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, + {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, +] +pyparsing = [ + {file = "pyparsing-3.0.8-py3-none-any.whl", hash = "sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06"}, + {file = "pyparsing-3.0.8.tar.gz", hash = "sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954"}, +] +pytest = [ + {file = "pytest-7.1.1-py3-none-any.whl", hash = "sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea"}, + {file = "pytest-7.1.1.tar.gz", hash = "sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63"}, +] +pyyaml = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +tomli = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] +typing-extensions = [ + {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, + {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, +] +uvloop = [ + {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, + {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30ba9dcbd0965f5c812b7c2112a1ddf60cf904c1c160f398e7eed3a6b82dcd9c"}, + {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bd53f7f5db562f37cd64a3af5012df8cac2c464c97e732ed556800129505bd64"}, + {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:772206116b9b57cd625c8a88f2413df2fcfd0b496eb188b82a43bed7af2c2ec9"}, + {file = "uvloop-0.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b572256409f194521a9895aef274cea88731d14732343da3ecdb175228881638"}, + {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450"}, + {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a19828c4f15687675ea912cc28bbcb48e9bb907c801873bd1519b96b04fb805"}, + {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e814ac2c6f9daf4c36eb8e85266859f42174a4ff0d71b99405ed559257750382"}, + {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd8f42ea1ea8f4e84d265769089964ddda95eb2bb38b5cbe26712b0616c3edee"}, + {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:647e481940379eebd314c00440314c81ea547aa636056f554d491e40503c8464"}, + {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e0d26fa5875d43ddbb0d9d79a447d2ace4180d9e3239788208527c4784f7cab"}, + {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6ccd57ae8db17d677e9e06192e9c9ec4bd2066b77790f9aa7dede2cc4008ee8f"}, + {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:089b4834fd299d82d83a25e3335372f12117a7d38525217c2258e9b9f4578897"}, + {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98d117332cc9e5ea8dfdc2b28b0a23f60370d02e1395f88f40d1effd2cb86c4f"}, + {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861"}, + {file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"}, +] diff --git a/packages/core/minos-microservice-transactions/poetry.toml b/packages/core/minos-microservice-transactions/poetry.toml new file mode 100644 index 000000000..ab1033bd3 --- /dev/null +++ b/packages/core/minos-microservice-transactions/poetry.toml @@ -0,0 +1,2 @@ +[virtualenvs] +in-project = true diff --git a/packages/core/minos-microservice-transactions/pyproject.toml b/packages/core/minos-microservice-transactions/pyproject.toml new file mode 100644 index 000000000..8a9906365 --- /dev/null +++ b/packages/core/minos-microservice-transactions/pyproject.toml @@ -0,0 +1,47 @@ +[tool.poetry] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +readme = "README.md" +repository = "https://github.com/minos-framework/minos-python" +homepage = "https://www.minos.run" +authors = ["Minos Framework Devs "] +license = "MIT" +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Natural Language :: English", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", +] +keywords = [ + "clariteia", + "minos", + "microservice", + "saga", +] +packages = [ + { include = "minos" } +] +include = [ + "AUTHORS.md", + "HISTORY.md", + "LICENSE", +] + +[tool.poetry.dependencies] +python = "^3.9" +minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true } +cached-property = "^1.5.2" + +[tool.poetry.dev-dependencies] +minos-microservice-common = { path = "../minos-microservice-common", develop = true } +black = "^22.3" +isort = "^5.8.0" +pytest = "^7.0.1" +coverage = "^6.3" +flake8 = "^4.0.1" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/packages/core/minos-microservice-transactions/setup.cfg b/packages/core/minos-microservice-transactions/setup.cfg new file mode 100644 index 000000000..55a397725 --- /dev/null +++ b/packages/core/minos-microservice-transactions/setup.cfg @@ -0,0 +1,28 @@ +[coverage:run] +source = + minos + +[coverage:report] +exclude_lines = + pragma: no cover + raise NotImplementedError + if TYPE_CHECKING: + pass + if __name__ == "__main__": + +[flake8] +filename = + ./minos/**/*.py, + ./tests/**/*.py, + ./examples/**/*.py +max-line-length = 120 +per-file-ignores = + ./**/__init__.py:F401,W391 + +[isort] +known_first_party=minos +multi_line_output = 3 +include_trailing_comma = True +force_grid_wrap = 1 +use_parentheses = True +line_length = 120 diff --git a/packages/core/minos-microservice-transactions/tests/__init__.py b/packages/core/minos-microservice-transactions/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/core/minos-microservice-transactions/tests/test_config.yml b/packages/core/minos-microservice-transactions/tests/test_config.yml new file mode 100644 index 000000000..7a417f9ca --- /dev/null +++ b/packages/core/minos-microservice-transactions/tests/test_config.yml @@ -0,0 +1,9 @@ +service: + name: Order +repository: + client: minos.common.testing.MockedDatabaseClient + database: order_db + user: minos + password: min0s + host: localhost + port: 5432 \ No newline at end of file diff --git a/packages/core/minos-microservice-transactions/tests/test_transactions/__init__.py b/packages/core/minos-microservice-transactions/tests/test_transactions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/core/minos-microservice-transactions/tests/utils.py b/packages/core/minos-microservice-transactions/tests/utils.py new file mode 100644 index 000000000..d8ee94c00 --- /dev/null +++ b/packages/core/minos-microservice-transactions/tests/utils.py @@ -0,0 +1,67 @@ +from __future__ import ( + annotations, +) + +from abc import ( + ABC, +) +from pathlib import ( + Path, +) + +from minos.common import ( + Lock, + LockPool, +) +from minos.common.testing import ( + MinosTestCase, +) + +BASE_PATH = Path(__file__).parent +CONFIG_FILE_PATH = BASE_PATH / "test_config.yml" + + +class TransactionsTestCase(MinosTestCase, ABC): + def get_config_file_path(self): + return CONFIG_FILE_PATH + + +class FakeAsyncIterator: + """For testing purposes.""" + + def __init__(self, seq): + self.iter = iter(seq) + + def __aiter__(self): + return self + + async def __anext__(self): + try: + return next(self.iter) + except StopIteration: + raise StopAsyncIteration + + +class FakeLock(Lock): + """For testing purposes.""" + + def __init__(self, key=None, *args, **kwargs): + if key is None: + key = "fake" + super().__init__(key, *args, **kwargs) + + async def acquire(self) -> None: + """For testing purposes.""" + + async def release(self): + """For testing purposes.""" + + +class FakeLockPool(LockPool): + """For testing purposes.""" + + async def _create_instance(self): + return FakeLock() + + async def _destroy_instance(self, instance) -> None: + """For testing purposes.""" From 74b7f928fc9693d729a1ea042b1557966d03b194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 21 Apr 2022 09:31:11 +0200 Subject: [PATCH 12/75] ISSUE #65 * Move `minos.aggregate.transactions` to `minos.transactions`. --- .../minos/aggregate/__init__.py | 14 - .../minos/aggregate/aggregate.py | 6 +- .../aggregate/events/repositories/abc.py | 12 +- .../minos/aggregate/exceptions.py | 12 - .../aggregate/snapshots/repositories/abc.py | 8 +- .../snapshots/repositories/database/impl.py | 12 +- .../snapshots/repositories/memory.py | 10 +- .../minos/aggregate/testing/__init__.py | 4 - .../testing/events/repositories/testcases.py | 4 +- .../snapshots/repositories/testcases.py | 6 +- .../minos/aggregate/transactions/__init__.py | 19 -- .../minos-microservice-aggregate/poetry.lock | 144 ++++------ .../pyproject.toml | 2 + .../test_root/test_with_postgresql.py | 4 +- .../test_events/test_entries.py | 4 +- .../test_events/test_repositories/test_abc.py | 8 +- .../tests/test_aggregate/test_exceptions.py | 12 - .../test_repositories/test_abc.py | 6 +- .../tests/utils.py | 10 +- .../minos/saga/executions/executors/abc.py | 2 +- .../minos/saga/middleware.py | 6 +- .../core/minos-microservice-saga/poetry.lock | 265 +++++------------- .../minos-microservice-saga/pyproject.toml | 4 +- .../test_executors/test_abc.py | 6 +- .../tests/test_saga/test_middleware.py | 6 +- .../minos-microservice-saga/tests/utils.py | 18 +- .../minos/transactions/__init__.py | 25 ++ .../minos}/transactions/contextvars.py | 0 .../minos}/transactions/entries.py | 6 +- .../minos/transactions/exceptions.py | 15 + .../minos}/transactions/mixins.py | 0 .../transactions/repositories/__init__.py | 0 .../minos}/transactions/repositories/abc.py | 6 +- .../repositories/database/__init__.py | 0 .../repositories/database/factories.py | 0 .../repositories/database/impl.py | 6 +- .../transactions/repositories/memory.py | 6 +- .../minos}/transactions/services.py | 8 +- .../minos/transactions/testing}/__init__.py | 0 .../testing}/repositories/__init__.py | 0 .../testing}/repositories/factories.py | 6 +- .../testing}/repositories/testcases.py | 15 +- .../poetry.lock | 69 ++--- .../pyproject.toml | 2 + .../tests}/test_transactions/test_entries.py | 118 ++++---- .../test_transactions/test_exceptions.py | 28 ++ .../tests}/test_transactions/test_mixins.py | 17 +- .../test_repositories}/__init__.py | 0 .../test_repositories/test_abc.py | 14 +- .../test_repositories/test_database.py | 18 +- .../test_repositories/test_memory.py | 8 +- .../tests}/test_transactions/test_services.py | 37 ++- .../tests/utils.py | 17 +- .../minos/plugins/aiopg/factories/__init__.py | 4 +- .../aiopg/factories/aggregate/__init__.py | 3 - .../factories/{aggregate => }/transactions.py | 12 +- .../plugins/minos-database-aiopg/poetry.lock | 60 ++-- .../minos-database-aiopg/pyproject.toml | 2 + .../test_transactions/__init__.py | 0 .../test_transactions}/__init__.py | 0 .../test_transactions/test_factory.py | 8 +- .../test_transactions/test_repository.py | 14 +- .../minos-database-aiopg/tests/utils.py | 4 +- .../plugins/minos-database-lmdb/poetry.lock | 43 ++- .../minos-database-lmdb/pyproject.toml | 2 +- .../minos-database-lmdb/tests/utils.py | 19 +- 66 files changed, 526 insertions(+), 670 deletions(-) delete mode 100644 packages/core/minos-microservice-aggregate/minos/aggregate/transactions/__init__.py rename packages/core/{minos-microservice-aggregate/minos/aggregate => minos-microservice-transactions/minos}/transactions/contextvars.py (100%) rename packages/core/{minos-microservice-aggregate/minos/aggregate => minos-microservice-transactions/minos}/transactions/entries.py (99%) create mode 100644 packages/core/minos-microservice-transactions/minos/transactions/exceptions.py rename packages/core/{minos-microservice-aggregate/minos/aggregate => minos-microservice-transactions/minos}/transactions/mixins.py (100%) rename packages/core/{minos-microservice-aggregate/minos/aggregate => minos-microservice-transactions/minos}/transactions/repositories/__init__.py (100%) rename packages/core/{minos-microservice-aggregate/minos/aggregate => minos-microservice-transactions/minos}/transactions/repositories/abc.py (99%) rename packages/core/{minos-microservice-aggregate/minos/aggregate => minos-microservice-transactions/minos}/transactions/repositories/database/__init__.py (100%) rename packages/core/{minos-microservice-aggregate/minos/aggregate => minos-microservice-transactions/minos}/transactions/repositories/database/factories.py (100%) rename packages/core/{minos-microservice-aggregate/minos/aggregate => minos-microservice-transactions/minos}/transactions/repositories/database/impl.py (98%) rename packages/core/{minos-microservice-aggregate/minos/aggregate => minos-microservice-transactions/minos}/transactions/repositories/memory.py (99%) rename packages/core/{minos-microservice-aggregate/minos/aggregate => minos-microservice-transactions/minos}/transactions/services.py (99%) rename packages/core/{minos-microservice-aggregate/minos/aggregate/testing/transactions => minos-microservice-transactions/minos/transactions/testing}/__init__.py (100%) rename packages/core/{minos-microservice-aggregate/minos/aggregate/testing/transactions => minos-microservice-transactions/minos/transactions/testing}/repositories/__init__.py (100%) rename packages/core/{minos-microservice-aggregate/minos/aggregate/testing/transactions => minos-microservice-transactions/minos/transactions/testing}/repositories/factories.py (96%) rename packages/core/{minos-microservice-aggregate/minos/aggregate/testing/transactions => minos-microservice-transactions/minos/transactions/testing}/repositories/testcases.py (99%) rename packages/core/{minos-microservice-aggregate/tests/test_aggregate => minos-microservice-transactions/tests}/test_transactions/test_entries.py (81%) create mode 100644 packages/core/minos-microservice-transactions/tests/test_transactions/test_exceptions.py rename packages/core/{minos-microservice-aggregate/tests/test_aggregate => minos-microservice-transactions/tests}/test_transactions/test_mixins.py (73%) rename packages/core/{minos-microservice-aggregate/tests/test_aggregate/test_transactions => minos-microservice-transactions/tests/test_transactions/test_repositories}/__init__.py (100%) rename packages/core/{minos-microservice-aggregate/tests/test_aggregate => minos-microservice-transactions/tests}/test_transactions/test_repositories/test_abc.py (97%) rename packages/core/{minos-microservice-aggregate/tests/test_aggregate => minos-microservice-transactions/tests}/test_transactions/test_repositories/test_database.py (97%) rename packages/core/{minos-microservice-aggregate/tests/test_aggregate => minos-microservice-transactions/tests}/test_transactions/test_repositories/test_memory.py (63%) rename packages/core/{minos-microservice-aggregate/tests/test_aggregate => minos-microservice-transactions/tests}/test_transactions/test_services.py (90%) rename packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/{aggregate => }/transactions.py (98%) delete mode 100644 packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/__init__.py rename packages/{core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories => plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_transactions}/__init__.py (100%) rename packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/{test_aggregate => }/test_transactions/test_factory.py (98%) rename packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/{test_aggregate => }/test_transactions/test_repository.py (95%) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py index 80032ab10..21483c513 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py @@ -48,9 +48,6 @@ RefException, SnapshotRepositoryConflictException, SnapshotRepositoryException, - TransactionNotFoundException, - TransactionRepositoryConflictException, - TransactionRepositoryException, ValueObjectException, ) from .queries import ( @@ -65,17 +62,6 @@ SnapshotRepository, SnapshotService, ) -from .transactions import ( - TRANSACTION_CONTEXT_VAR, - DatabaseTransactionRepository, - InMemoryTransactionRepository, - TransactionalMixin, - TransactionDatabaseOperationFactory, - TransactionEntry, - TransactionRepository, - TransactionService, - TransactionStatus, -) from .value_objects import ( ValueObject, ValueObjectSet, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py index 15d64c7fe..7f8bf18a1 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py @@ -14,6 +14,9 @@ NotProvidedException, SetupMixin, ) +from minos.transactions import ( + TransactionRepository, +) from .entities import ( RootEntity, @@ -24,9 +27,6 @@ from .snapshots import ( SnapshotRepository, ) -from .transactions import ( - TransactionRepository, -) RT = TypeVar("RT", bound=RootEntity) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py index ed4ce00c7..fc552bdaa 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py @@ -39,6 +39,12 @@ BrokerMessageV1Strategy, BrokerPublisher, ) +from minos.transactions import ( + TRANSACTION_CONTEXT_VAR, + TransactionalMixin, + TransactionEntry, + TransactionStatus, +) from ...actions import ( Action, @@ -50,12 +56,6 @@ EventRepositoryConflictException, EventRepositoryException, ) -from ...transactions import ( - TRANSACTION_CONTEXT_VAR, - TransactionalMixin, - TransactionEntry, - TransactionStatus, -) from ..entries import ( EventEntry, ) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py b/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py index 6958a2a48..4f44d70d1 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py @@ -35,18 +35,6 @@ def __init__(self, error_message: str, offset: int): self.offset = offset -class TransactionRepositoryException(AggregateException): - """Base transaction repository exception.""" - - -class TransactionRepositoryConflictException(TransactionRepositoryException): - """Exception to be raised when a transaction has invalid status.""" - - -class TransactionNotFoundException(TransactionRepositoryException): - """Exception to be raised when some transaction is not found on the repository.""" - - class SnapshotRepositoryException(AggregateException): """Base snapshot exception.""" diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py index 29f923ff1..00530c1cf 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py @@ -22,6 +22,10 @@ SetupMixin, classname, ) +from minos.transactions import ( + TRANSACTION_CONTEXT_VAR, + TransactionEntry, +) from ...exceptions import ( NotFoundException, @@ -32,10 +36,6 @@ _EqualCondition, _Ordering, ) -from ...transactions import ( - TRANSACTION_CONTEXT_VAR, - TransactionEntry, -) from ..entries import ( SnapshotEntry, ) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py index 4f965cc89..4777db37b 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py @@ -24,6 +24,12 @@ ProgrammingException, import_module, ) +from minos.transactions import ( + TransactionEntry, + TransactionNotFoundException, + TransactionRepository, + TransactionStatus, +) from ....events import ( Event, @@ -33,17 +39,11 @@ from ....exceptions import ( NotFoundException, SnapshotRepositoryConflictException, - TransactionNotFoundException, ) from ....queries import ( _Condition, _Ordering, ) -from ....transactions import ( - TransactionEntry, - TransactionRepository, - TransactionStatus, -) from ...entries import ( SnapshotEntry, ) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py index cc8ecfb69..2771caabd 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py @@ -24,6 +24,11 @@ Inject, NotProvidedException, ) +from minos.transactions import ( + TransactionEntry, + TransactionRepository, + TransactionStatus, +) from ...events import ( EventEntry, @@ -36,11 +41,6 @@ _Condition, _Ordering, ) -from ...transactions import ( - TransactionEntry, - TransactionRepository, - TransactionStatus, -) from ..entries import ( SnapshotEntry, ) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/__init__.py index 9d205beed..1ec1456db 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/__init__.py @@ -6,7 +6,3 @@ MockedSnapshotDatabaseOperationFactory, SnapshotRepositoryTestCase, ) -from .transactions import ( - MockedTransactionDatabaseOperationFactory, - TransactionRepositoryTestCase, -) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/testcases.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/testcases.py index e7d8ee72e..2ac3d71f7 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/testcases.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/testcases.py @@ -22,7 +22,6 @@ EventRepositoryConflictException, EventRepositoryException, FieldDiffContainer, - TransactionEntry, ) from minos.common import ( NULL_UUID, @@ -31,6 +30,9 @@ from minos.common.testing import ( MinosTestCase, ) +from minos.transactions import ( + TransactionEntry, +) class EventRepositoryTestCase(MinosTestCase, ABC): diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py index 2fd005412..1495d8bbd 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py @@ -33,8 +33,6 @@ RootEntity, SnapshotEntry, SnapshotRepository, - TransactionEntry, - TransactionStatus, ) from minos.common import ( classname, @@ -43,6 +41,10 @@ from minos.common.testing import ( MinosTestCase, ) +from minos.transactions import ( + TransactionEntry, + TransactionStatus, +) class SnapshotRepositoryTestCase(MinosTestCase, ABC): diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/__init__.py deleted file mode 100644 index d1cea06fe..000000000 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -from .contextvars import ( - TRANSACTION_CONTEXT_VAR, -) -from .entries import ( - TransactionEntry, - TransactionStatus, -) -from .mixins import ( - TransactionalMixin, -) -from .repositories import ( - DatabaseTransactionRepository, - InMemoryTransactionRepository, - TransactionDatabaseOperationFactory, - TransactionRepository, -) -from .services import ( - TransactionService, -) diff --git a/packages/core/minos-microservice-aggregate/poetry.lock b/packages/core/minos-microservice-aggregate/poetry.lock index 6a47dc8e4..b6abf872c 100644 --- a/packages/core/minos-microservice-aggregate/poetry.lock +++ b/packages/core/minos-microservice-aggregate/poetry.lock @@ -189,14 +189,6 @@ requirements_deprecated_finder = ["pipreqs", "pip-api"] colors = ["colorama (>=0.4.3,<0.5.0)"] plugins = ["setuptools"] -[[package]] -name = "lmdb" -version = "1.3.0" -description = "Universal Python binding for the LMDB 'Lightning' Database" -category = "main" -optional = false -python-versions = "*" - [[package]] name = "mccabe" version = "0.6.1" @@ -219,7 +211,6 @@ aiomisc = ">=14.0.3,<15.8.0" cached-property = "^1.5.2" dependency-injector = "^4.32.2" fastavro = "^1.4.0" -lmdb = "^1.2.1" orjson = "^3.5.2" PyYAML = ">=5.4.1,<7.0.0" uvloop = "^0.16.0" @@ -245,6 +236,23 @@ minos-microservice-common = "^0.7.0*" type = "directory" url = "../minos-microservice-networks" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" + +[package.source] +type = "directory" +url = "../minos-microservice-transactions" + [[package]] name = "mypy-extensions" version = "0.4.3" @@ -255,7 +263,7 @@ python-versions = "*" [[package]] name = "orjson" -version = "3.6.7" +version = "3.6.8" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" category = "main" optional = false @@ -282,15 +290,15 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] name = "platformdirs" -version = "2.5.1" +version = "2.5.2" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] +test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] [[package]] name = "pluggy" @@ -386,11 +394,11 @@ python-versions = ">=3.7" [[package]] name = "typing-extensions" -version = "4.1.1" -description = "Backported and Experimental Type Hints for Python 3.6+" +version = "4.2.0" +description = "Backported and Experimental Type Hints for Python 3.7+" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "uvloop" @@ -408,7 +416,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "9c9ca4862b7363ae69ed21727f7a65a29a33e373df45250938f7c75f398b8da5" +content-hash = "0db237d303b06dd9fc7f7bf21e39e84845e915b71fd12bc90c4c2cf7563caf93" [metadata.files] aiomisc = [ @@ -578,78 +586,50 @@ isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] -lmdb = [ - {file = "lmdb-1.3.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:63cb73fe7ce9eb93d992d632c85a0476b4332670d9e6a2802b5062f603b7809f"}, - {file = "lmdb-1.3.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:abbc439cd9fe60ffd6197009087ea885ac150017dc85384093b1d376f83f0ec4"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6260a526e4ad85b1f374a5ba9475bf369fb07e7728ea6ec57226b02c40d1976b"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e568ae0887ae196340947d9800136e90feaed6b86a261ef01f01b2ba65fc8106"}, - {file = "lmdb-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6a816954d212f40fd15007cd81ab7a6bebb77436d949a6a9ae04af57fc127f3"}, - {file = "lmdb-1.3.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fa6439356e591d3249ab0e1778a6f8d8408e993f66dc911914c78208f5310309"}, - {file = "lmdb-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:c6adbd6f7f9048e97f31a069e652eb51020a81e80a0ce92dbb9810d21da2409a"}, - {file = "lmdb-1.3.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:eefb392f6b5cd43aada49258c5a79be11cb2c8cd3fc3e2d9319a1e0b9f906458"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a14aca2651c3af6f0d0a6b9168200eea0c8f2d27c40b01a442f33329a6e8dff"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfa4aa9c67f8aee89b23005e98d1f3f32490b6b905fd1cb604b207cbd5755ab"}, - {file = "lmdb-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7da05d70fcc6561ac6b09e9fb1bf64b7ca294652c64c8a2889273970cee796b9"}, - {file = "lmdb-1.3.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:008243762decf8f6c90430a9bced56290ebbcdb5e877d90e42343bb97033e494"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:17215a42a4b9814c383deabecb160581e4fb75d00198eef0e3cea54f230ffbea"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65334eafa5d430b18d81ebd5362559a41483c362e1931f6e1b15bab2ecb7d75d"}, - {file = "lmdb-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:18c69fabdaf04efaf246587739cc1062b3e57c6ef0743f5c418df89e5e7e7b9b"}, - {file = "lmdb-1.3.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:41318717ab5d15ad2d6d263d34fbf614a045210f64b25e59ce734bb2105e421f"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:df2724bad7820114a205472994091097d0fa65a3e5fff5a8e688d123fb8c6326"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddd590e1c7fcb395931aa3782fb89b9db4550ab2d81d006ecd239e0d462bc41"}, - {file = "lmdb-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:4172fba19417d7b29409beca7d73c067b54e5d8ab1fb9b51d7b4c1445d20a167"}, - {file = "lmdb-1.3.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2df38115dd9428a54d59ae7c712a4c7cce0d6b1d66056de4b1a8c38718066106"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9103aa4908f0bca43c5911ca067d4e3d01f682dff0c0381a1239bd2bd757984"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:394df860c3f93cfd92b6f4caba785f38208cc9614c18b3803f83a2cc1695042f"}, - {file = "lmdb-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:62ab28e3593bdc318ea2f2fa1574e5fca3b6d1f264686d773ba54a637d4f563b"}, - {file = "lmdb-1.3.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:e6a704b3baced9182836c7f77b769f23856f3a8f62d0282b1bc1feaf81a86712"}, - {file = "lmdb-1.3.0-pp27-pypy_73-win_amd64.whl", hash = "sha256:08f4b5129f4683802569b02581142e415c8dcc0ff07605983ec1b07804cecbad"}, - {file = "lmdb-1.3.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:f291e3f561f58dddf63a92a5a6a4b8af3a0920b6705d35e2f80e52e86ee238a2"}, - {file = "lmdb-1.3.0.tar.gz", hash = "sha256:60a11efc21aaf009d06518996360eed346f6000bfc9de05114374230879f992e"}, -] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] minos-microservice-common = [] minos-microservice-networks = [] +minos-microservice-transactions = [] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] orjson = [ - {file = "orjson-3.6.7-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:93188a9d6eb566419ad48befa202dfe7cd7a161756444b99c4ec77faea9352a4"}, - {file = "orjson-3.6.7-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:82515226ecb77689a029061552b5df1802b75d861780c401e96ca6bc8495f775"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3af57ffab7848aaec6ba6b9e9b41331250b57bf696f9d502bacdc71a0ebab0ba"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:a7297504d1142e7efa236ffc53f056d73934a993a08646dbcee89fc4308a8fcf"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:5a50cde0dbbde255ce751fd1bca39d00ecd878ba0903c0480961b31984f2fab7"}, - {file = "orjson-3.6.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d21f9a2d1c30e58070f93988db4cad154b9009fafbde238b52c1c760e3607fbe"}, - {file = "orjson-3.6.7-cp310-none-win_amd64.whl", hash = "sha256:e152464c4606b49398afd911777decebcf9749cc8810c5b4199039e1afb0991e"}, - {file = "orjson-3.6.7-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:0a65f3c403f38b0117c6dd8e76e85a7bd51fcd92f06c5598dfeddbc44697d3e5"}, - {file = "orjson-3.6.7-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:6c47cfca18e41f7f37b08ff3e7abf5ada2d0f27b5ade934f05be5fc5bb956e9d"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:63185af814c243fad7a72441e5f98120c9ecddf2675befa486d669fb65539e9b"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2da6fde42182b80b40df2e6ab855c55090ebfa3fcc21c182b7ad1762b61d55c"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:48c5831ec388b4e2682d4ff56d6bfa4a2ef76c963f5e75f4ff4785f9cf338a80"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:913fac5d594ccabf5e8fbac15b9b3bb9c576d537d49eeec9f664e7a64dde4c4b"}, - {file = "orjson-3.6.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:58f244775f20476e5851e7546df109f75160a5178d44257d437ba6d7e562bfe8"}, - {file = "orjson-3.6.7-cp37-none-win_amd64.whl", hash = "sha256:2d5f45c6b85e5f14646df2d32ecd7ff20fcccc71c0ea1155f4d3df8c5299bbb7"}, - {file = "orjson-3.6.7-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:612d242493afeeb2068bc72ff2544aa3b1e627578fcf92edee9daebb5893ffea"}, - {file = "orjson-3.6.7-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:539cdc5067db38db27985e257772d073cd2eb9462d0a41bde96da4e4e60bd99b"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d103b721bbc4f5703f62b3882e638c0b65fcdd48622531c7ffd45047ef8e87c"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb10a20f80e95102dd35dfbc3a22531661b44a09b55236b012a446955846b023"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:bb68d0da349cf8a68971a48ad179434f75256159fe8b0715275d9b49fa23b7a3"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:4a2c7d0a236aaeab7f69c17b7ab4c078874e817da1bfbb9827cb8c73058b3050"}, - {file = "orjson-3.6.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3be045ca3b96119f592904cf34b962969ce97bd7843cbfca084009f6c8d2f268"}, - {file = "orjson-3.6.7-cp38-none-win_amd64.whl", hash = "sha256:bd765c06c359d8a814b90f948538f957fa8a1f55ad1aaffcdc5771996aaea061"}, - {file = "orjson-3.6.7-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7dd9e1e46c0776eee9e0649e3ae9584ea368d96851bcaeba18e217fa5d755283"}, - {file = "orjson-3.6.7-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c4b4f20a1e3df7e7c83717aff0ef4ab69e42ce2fb1f5234682f618153c458406"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7107a5673fd0b05adbb58bf71c1578fc84d662d29c096eb6d998982c8635c221"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a08b6940dd9a98ccf09785890112a0f81eadb4f35b51b9a80736d1725437e22c"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:f5d1648e5a9d1070f3628a69a7c6c17634dbb0caf22f2085eca6910f7427bf1f"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:e6201494e8dff2ce7fd21da4e3f6dfca1a3fed38f9dcefc972f552f6596a7621"}, - {file = "orjson-3.6.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:70d0386abe02879ebaead2f9632dd2acb71000b4721fd8c1a2fb8c031a38d4d5"}, - {file = "orjson-3.6.7-cp39-none-win_amd64.whl", hash = "sha256:d9a3288861bfd26f3511fb4081561ca768674612bac59513cb9081bb61fcc87f"}, - {file = "orjson-3.6.7.tar.gz", hash = "sha256:a4bb62b11289b7620eead2f25695212e9ac77fcfba76f050fa8a540fb5c32401"}, + {file = "orjson-3.6.8-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:3a287a650458de2211db03681b71c3e5cb2212b62f17a39df8ad99fc54855d0f"}, + {file = "orjson-3.6.8-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5204e25c12cea58e524fc82f7c27ed0586f592f777b33075a92ab7b3eb3687c2"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77e8386393add64f959c044e0fb682364fd0e611a6f477aa13f0e6a733bd6a28"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:279f2d2af393fdf8601020744cb206b91b54ad60fb8401e0761819c7bda1f4e4"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:c31c9f389be7906f978ed4192eb58a4b74a37ad60556a0b88ddc47c576697770"}, + {file = "orjson-3.6.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0db5c5a0c5b89f092d52f6e5a3701660a9d6ffa9e2968b3ce17c2bc4f5eb0414"}, + {file = "orjson-3.6.8-cp310-none-win_amd64.whl", hash = "sha256:eb22485847b9a0c4bbedc668df860126ac931edbed1d456cf41a59f3cb961ed8"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:1a5fe569310bc819279bd4d5f2c349910b104ed3207936246dd5d5e0b085e74a"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:ccb356a47ab1067cd3549847e9db1d279a63fe0482d315b3ffd6e7abef35ef77"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab29c069c222248ce302a25855b4e1664f9436e8ae5a131fb0859daf31676d2b"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d2b5e4cba9e774ac011071d9d27760f97f4b8cd46003e971d122e712f971345"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:c311ec504414d22834d5b972a209619925b48263856a11a14d90230f9682d49c"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:a3dfec7950b90fb8d143743503ee53fa06b32e6068bdea792fc866284da3d71d"}, + {file = "orjson-3.6.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b890dbbada2cbb26eb29bd43a848426f007f094bb0758df10dfe7a438e1cb4b4"}, + {file = "orjson-3.6.8-cp37-none-win_amd64.whl", hash = "sha256:9143ae2c52771525be9ad11a7a8cc8e7fd75391b107e7e644a9e0050496f6b4f"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:33a82199fd42f6436f833e210ae5129c922a5c355629356ca7a8e82964da7285"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:90159ea8b9a5a2a98fa33dc7b421cfac4d2ae91ba5e1058f5909e7f059f6b467"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:656fbe15d9ef0733e740d9def78f4fdb4153102f4836ee774a05123499005931"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7be3be6153843e0f01351b1313a5ad4723595427680dac2dfff22a37e652ce02"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:dd24f66b6697ee7424f7da575ec6cbffc8ede441114d53470949cda4d97c6e56"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:b07c780f7345ecf5901356dc21dee0669defc489c38ce7b9ab0f5e008cc0385c"}, + {file = "orjson-3.6.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ea32015a5d8a4ce00d348a0de5dc7040e0ad58f970a8fcbb5713a1eac129e493"}, + {file = "orjson-3.6.8-cp38-none-win_amd64.whl", hash = "sha256:c5a3e382194c838988ec128a26b08aa92044e5e055491cc4056142af0c1c54d7"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:83a8424e857ae1bf53530e88b4eb2f16ca2b489073b924e655f1575cacd7f52a"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:81e1a6a2d67f15007dadacbf9ba5d3d79237e5e33786c028557fe5a2b72f1c9a"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:137b539881c77866eba86ff6a11df910daf2eb9ab8f1acae62f879e83d7c38af"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cbd358f3b3ad539a27e36900e8e7d172d0e1b72ad9dd7d69544dcbc0f067ee7"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:6ab94701542d40b90903ecfc339333f458884979a01cb9268bc662cc67a5f6d8"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:32b6f26593a9eb606b40775826beb0dac152e3d224ea393688fced036045a821"}, + {file = "orjson-3.6.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:afd9e329ebd3418cac3cd747769b1d52daa25fa672bbf414ab59f0e0881b32b9"}, + {file = "orjson-3.6.8-cp39-none-win_amd64.whl", hash = "sha256:0c89b419914d3d1f65a1b0883f377abe42a6e44f6624ba1c63e8846cbfc2fa60"}, + {file = "orjson-3.6.8.tar.gz", hash = "sha256:e19d23741c5de13689bb316abfccea15a19c264e3ec8eb332a5319a583595ace"}, ] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, @@ -660,8 +640,8 @@ pathspec = [ {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, ] platformdirs = [ - {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, - {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, @@ -731,8 +711,8 @@ tomli = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] typing-extensions = [ - {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, - {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, + {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, + {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, ] uvloop = [ {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, diff --git a/packages/core/minos-microservice-aggregate/pyproject.toml b/packages/core/minos-microservice-aggregate/pyproject.toml index d8b52373b..9c4ae39fa 100644 --- a/packages/core/minos-microservice-aggregate/pyproject.toml +++ b/packages/core/minos-microservice-aggregate/pyproject.toml @@ -33,11 +33,13 @@ include = [ python = "^3.9" minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true } minos-microservice-networks = { version ="^0.7.0*", allow-prereleases = true } +minos-microservice-transactions = { version ="^0.0.0*", allow-prereleases = true } cached-property = "^1.5.2" [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../minos-microservice-common", develop = true } minos-microservice-networks = { path = "../minos-microservice-networks", develop = true } +minos-microservice-transactions = { path = "../minos-microservice-transactions", develop = true } black = "^22.3" isort = "^5.8.0" pytest = "^7.0.1" diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_with_postgresql.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_with_postgresql.py index 923dafd53..530651395 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_with_postgresql.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_with_postgresql.py @@ -4,13 +4,15 @@ AlreadyDeletedException, DatabaseEventRepository, DatabaseSnapshotRepository, - DatabaseTransactionRepository, EntitySet, ValueObjectSet, ) from minos.common.testing import ( DatabaseMinosTestCase, ) +from minos.transactions import ( + DatabaseTransactionRepository, +) from tests.utils import ( AggregateTestCase, Car, diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_entries.py index cf57c6055..266c39575 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_entries.py @@ -12,12 +12,14 @@ EventEntry, FieldDiff, FieldDiffContainer, - TransactionEntry, ) from minos.common import ( NULL_UUID, current_datetime, ) +from minos.transactions import ( + TransactionEntry, +) from tests.utils import ( Car, ) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py index 19f160822..5331b4834 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py @@ -18,7 +18,6 @@ from minos.aggregate import ( IS_REPOSITORY_SERIALIZATION_CONTEXT_VAR, - TRANSACTION_CONTEXT_VAR, Action, Event, EventEntry, @@ -28,8 +27,6 @@ FieldDiff, FieldDiffContainer, IncrementalFieldDiff, - TransactionEntry, - TransactionStatus, ) from minos.common import ( NULL_UUID, @@ -41,6 +38,11 @@ from minos.networks import ( BrokerMessageV1, ) +from minos.transactions import ( + TRANSACTION_CONTEXT_VAR, + TransactionEntry, + TransactionStatus, +) from tests.utils import ( AggregateTestCase, Car, diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py index 6f1ca4a4a..b11622997 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py @@ -9,8 +9,6 @@ NotFoundException, SnapshotRepositoryConflictException, SnapshotRepositoryException, - TransactionRepositoryConflictException, - TransactionRepositoryException, ) from minos.common import ( MinosException, @@ -55,16 +53,6 @@ def test_snapshot_not_found(self): def test_snapshot_already_deleted(self): self.assertTrue(issubclass(AlreadyDeletedException, SnapshotRepositoryException)) - def test_transaction(self): - self.assertTrue(issubclass(TransactionRepositoryException, AggregateException)) - - def test_transaction_conflict(self): - message = "There was a conflict" - exception = TransactionRepositoryConflictException(message) - - self.assertIsInstance(exception, TransactionRepositoryException) - self.assertEqual(message, str(exception)) - if __name__ == "__main__": unittest.main() diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py index 4413415b2..0ea408447 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py @@ -15,12 +15,10 @@ ) from minos.aggregate import ( - TRANSACTION_CONTEXT_VAR, Condition, Ordering, SnapshotEntry, SnapshotRepository, - TransactionEntry, ) from minos.aggregate.queries import ( _EqualCondition, @@ -28,6 +26,10 @@ from minos.common import ( SetupMixin, ) +from minos.transactions import ( + TRANSACTION_CONTEXT_VAR, + TransactionEntry, +) from tests.utils import ( AggregateTestCase, Car, diff --git a/packages/core/minos-microservice-aggregate/tests/utils.py b/packages/core/minos-microservice-aggregate/tests/utils.py index aa9333287..4d1495332 100644 --- a/packages/core/minos-microservice-aggregate/tests/utils.py +++ b/packages/core/minos-microservice-aggregate/tests/utils.py @@ -22,7 +22,6 @@ ExternalEntity, InMemoryEventRepository, InMemorySnapshotRepository, - InMemoryTransactionRepository, Ref, RootEntity, ValueObject, @@ -43,13 +42,20 @@ InMemoryBrokerPublisher, InMemoryBrokerSubscriberBuilder, ) +from minos.transactions import ( + InMemoryTransactionRepository, +) +from minos.transactions import testing as transactions_testing BASE_PATH = Path(__file__).parent CONFIG_FILE_PATH = BASE_PATH / "test_config.yml" class AggregateTestCase(MinosTestCase, ABC): - testing_module = testing + testing_module = { + "aggregate": testing, + "transactions": transactions_testing, + } def get_config_file_path(self): return CONFIG_FILE_PATH diff --git a/packages/core/minos-microservice-saga/minos/saga/executions/executors/abc.py b/packages/core/minos-microservice-saga/minos/saga/executions/executors/abc.py index b17af68db..0a5c6cf88 100644 --- a/packages/core/minos-microservice-saga/minos/saga/executions/executors/abc.py +++ b/packages/core/minos-microservice-saga/minos/saga/executions/executors/abc.py @@ -7,7 +7,7 @@ UUID, ) -from minos.aggregate import ( +from minos.transactions import ( TransactionEntry, ) diff --git a/packages/core/minos-microservice-saga/minos/saga/middleware.py b/packages/core/minos-microservice-saga/minos/saga/middleware.py index 2781f5ed6..3cd0e18d0 100644 --- a/packages/core/minos-microservice-saga/minos/saga/middleware.py +++ b/packages/core/minos-microservice-saga/minos/saga/middleware.py @@ -9,15 +9,15 @@ UUID, ) -from minos.aggregate import ( - TransactionEntry, -) from minos.networks import ( REQUEST_HEADERS_CONTEXT_VAR, BrokerRequest, Request, Response, ) +from minos.transactions import ( + TransactionEntry, +) from .utils import ( get_service_name, diff --git a/packages/core/minos-microservice-saga/poetry.lock b/packages/core/minos-microservice-saga/poetry.lock index 9b8d56bdf..49dcd480e 100644 --- a/packages/core/minos-microservice-saga/poetry.lock +++ b/packages/core/minos-microservice-saga/poetry.lock @@ -19,29 +19,6 @@ develop = ["aiocontextvars (==0.2.2)", "aiohttp-asgi", "aiohttp (<4)", "async-ti raven = ["raven-aiohttp"] uvloop = ["uvloop (>=0.14,<1)"] -[[package]] -name = "aiopg" -version = "1.3.3" -description = "Postgres integration with asyncio." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -async-timeout = ">=3.0,<5.0" -psycopg2-binary = ">=2.8.4" - -[package.extras] -sa = ["sqlalchemy[postgresql_psycopg2binary] (>=1.3,<1.5)"] - -[[package]] -name = "async-timeout" -version = "4.0.2" -description = "Timeout context manager for asyncio programs" -category = "main" -optional = false -python-versions = ">=3.6" - [[package]] name = "atomicwrites" version = "1.4.0" @@ -212,14 +189,6 @@ requirements_deprecated_finder = ["pipreqs", "pip-api"] colors = ["colorama (>=0.4.3,<0.5.0)"] plugins = ["setuptools"] -[[package]] -name = "lmdb" -version = "1.3.0" -description = "Universal Python binding for the LMDB 'Lightning' Database" -category = "main" -optional = false -python-versions = "*" - [[package]] name = "mccabe" version = "0.6.1" @@ -228,25 +197,6 @@ category = "dev" optional = false python-versions = "*" -[[package]] -name = "minos-microservice-aggregate" -version = "0.7.0.dev1" -description = "The Aggregate pattern of the Minos Framework" -category = "main" -optional = false -python-versions = "^3.9" -develop = true - -[package.dependencies] -cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" -minos-microservice-networks = "^0.7.0*" -psycopg2-binary = "^2.9.3" - -[package.source] -type = "directory" -url = "../minos-microservice-aggregate" - [[package]] name = "minos-microservice-common" version = "0.7.0.dev1" @@ -258,11 +208,9 @@ develop = true [package.dependencies] aiomisc = ">=14.0.3,<15.8.0" -aiopg = "^1.2.1" cached-property = "^1.5.2" dependency-injector = "^4.32.2" fastavro = "^1.4.0" -lmdb = "^1.2.1" orjson = "^3.5.2" PyYAML = ">=5.4.1,<7.0.0" uvloop = "^0.16.0" @@ -281,15 +229,31 @@ python-versions = "^3.9" develop = true [package.dependencies] -aiopg = "^1.2.1" crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" -psycopg2-binary = "^2.9.3" [package.source] type = "directory" url = "../minos-microservice-networks" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" +minos-microservice-networks = "^0.7.0*" + +[package.source] +type = "directory" +url = "../minos-microservice-transactions" + [[package]] name = "mypy-extensions" version = "0.4.3" @@ -300,7 +264,7 @@ python-versions = "*" [[package]] name = "orjson" -version = "3.6.7" +version = "3.6.8" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" category = "main" optional = false @@ -327,15 +291,15 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] name = "platformdirs" -version = "2.5.1" +version = "2.5.2" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] +test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] [[package]] name = "pluggy" @@ -349,14 +313,6 @@ python-versions = ">=3.6" dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "psycopg2-binary" -version = "2.9.3" -description = "psycopg2 - Python-PostgreSQL Database Adapter" -category = "main" -optional = false -python-versions = ">=3.6" - [[package]] name = "py" version = "1.11.0" @@ -439,11 +395,11 @@ python-versions = ">=3.7" [[package]] name = "typing-extensions" -version = "4.1.1" -description = "Backported and Experimental Type Hints for Python 3.6+" +version = "4.2.0" +description = "Backported and Experimental Type Hints for Python 3.7+" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "uvloop" @@ -461,21 +417,13 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "78161968a697862a222239c4016779c6140d2f39f8fb4ed614bb596f76413aee" +content-hash = "0db237d303b06dd9fc7f7bf21e39e84845e915b71fd12bc90c4c2cf7563caf93" [metadata.files] aiomisc = [ {file = "aiomisc-15.7.3-py3-none-any.whl", hash = "sha256:0403e83268e98d0f2a125a70d13303fe1a2358e36db3daf02df032c7fa4f1525"}, {file = "aiomisc-15.7.3.tar.gz", hash = "sha256:ba250a34bd4609ced36111cb50580f57c3d52f3955f953a53ecb2986988baedc"}, ] -aiopg = [ - {file = "aiopg-1.3.3-py3-none-any.whl", hash = "sha256:2842dd8741460eeef940032dcb577bfba4d4115205dd82a73ce13b3271f5bf0a"}, - {file = "aiopg-1.3.3.tar.gz", hash = "sha256:547c6ba4ea0d73c2a11a2f44387d7133cc01d3c6f3b8ed976c0ac1eff4f595d7"}, -] -async-timeout = [ - {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, - {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, -] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, @@ -639,79 +587,50 @@ isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] -lmdb = [ - {file = "lmdb-1.3.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:63cb73fe7ce9eb93d992d632c85a0476b4332670d9e6a2802b5062f603b7809f"}, - {file = "lmdb-1.3.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:abbc439cd9fe60ffd6197009087ea885ac150017dc85384093b1d376f83f0ec4"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6260a526e4ad85b1f374a5ba9475bf369fb07e7728ea6ec57226b02c40d1976b"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e568ae0887ae196340947d9800136e90feaed6b86a261ef01f01b2ba65fc8106"}, - {file = "lmdb-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6a816954d212f40fd15007cd81ab7a6bebb77436d949a6a9ae04af57fc127f3"}, - {file = "lmdb-1.3.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fa6439356e591d3249ab0e1778a6f8d8408e993f66dc911914c78208f5310309"}, - {file = "lmdb-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:c6adbd6f7f9048e97f31a069e652eb51020a81e80a0ce92dbb9810d21da2409a"}, - {file = "lmdb-1.3.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:eefb392f6b5cd43aada49258c5a79be11cb2c8cd3fc3e2d9319a1e0b9f906458"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a14aca2651c3af6f0d0a6b9168200eea0c8f2d27c40b01a442f33329a6e8dff"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfa4aa9c67f8aee89b23005e98d1f3f32490b6b905fd1cb604b207cbd5755ab"}, - {file = "lmdb-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7da05d70fcc6561ac6b09e9fb1bf64b7ca294652c64c8a2889273970cee796b9"}, - {file = "lmdb-1.3.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:008243762decf8f6c90430a9bced56290ebbcdb5e877d90e42343bb97033e494"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:17215a42a4b9814c383deabecb160581e4fb75d00198eef0e3cea54f230ffbea"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65334eafa5d430b18d81ebd5362559a41483c362e1931f6e1b15bab2ecb7d75d"}, - {file = "lmdb-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:18c69fabdaf04efaf246587739cc1062b3e57c6ef0743f5c418df89e5e7e7b9b"}, - {file = "lmdb-1.3.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:41318717ab5d15ad2d6d263d34fbf614a045210f64b25e59ce734bb2105e421f"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:df2724bad7820114a205472994091097d0fa65a3e5fff5a8e688d123fb8c6326"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddd590e1c7fcb395931aa3782fb89b9db4550ab2d81d006ecd239e0d462bc41"}, - {file = "lmdb-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:4172fba19417d7b29409beca7d73c067b54e5d8ab1fb9b51d7b4c1445d20a167"}, - {file = "lmdb-1.3.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2df38115dd9428a54d59ae7c712a4c7cce0d6b1d66056de4b1a8c38718066106"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9103aa4908f0bca43c5911ca067d4e3d01f682dff0c0381a1239bd2bd757984"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:394df860c3f93cfd92b6f4caba785f38208cc9614c18b3803f83a2cc1695042f"}, - {file = "lmdb-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:62ab28e3593bdc318ea2f2fa1574e5fca3b6d1f264686d773ba54a637d4f563b"}, - {file = "lmdb-1.3.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:e6a704b3baced9182836c7f77b769f23856f3a8f62d0282b1bc1feaf81a86712"}, - {file = "lmdb-1.3.0-pp27-pypy_73-win_amd64.whl", hash = "sha256:08f4b5129f4683802569b02581142e415c8dcc0ff07605983ec1b07804cecbad"}, - {file = "lmdb-1.3.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:f291e3f561f58dddf63a92a5a6a4b8af3a0920b6705d35e2f80e52e86ee238a2"}, - {file = "lmdb-1.3.0.tar.gz", hash = "sha256:60a11efc21aaf009d06518996360eed346f6000bfc9de05114374230879f992e"}, -] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] -minos-microservice-aggregate = [] minos-microservice-common = [] minos-microservice-networks = [] +minos-microservice-transactions = [] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] orjson = [ - {file = "orjson-3.6.7-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:93188a9d6eb566419ad48befa202dfe7cd7a161756444b99c4ec77faea9352a4"}, - {file = "orjson-3.6.7-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:82515226ecb77689a029061552b5df1802b75d861780c401e96ca6bc8495f775"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3af57ffab7848aaec6ba6b9e9b41331250b57bf696f9d502bacdc71a0ebab0ba"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:a7297504d1142e7efa236ffc53f056d73934a993a08646dbcee89fc4308a8fcf"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:5a50cde0dbbde255ce751fd1bca39d00ecd878ba0903c0480961b31984f2fab7"}, - {file = "orjson-3.6.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d21f9a2d1c30e58070f93988db4cad154b9009fafbde238b52c1c760e3607fbe"}, - {file = "orjson-3.6.7-cp310-none-win_amd64.whl", hash = "sha256:e152464c4606b49398afd911777decebcf9749cc8810c5b4199039e1afb0991e"}, - {file = "orjson-3.6.7-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:0a65f3c403f38b0117c6dd8e76e85a7bd51fcd92f06c5598dfeddbc44697d3e5"}, - {file = "orjson-3.6.7-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:6c47cfca18e41f7f37b08ff3e7abf5ada2d0f27b5ade934f05be5fc5bb956e9d"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:63185af814c243fad7a72441e5f98120c9ecddf2675befa486d669fb65539e9b"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2da6fde42182b80b40df2e6ab855c55090ebfa3fcc21c182b7ad1762b61d55c"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:48c5831ec388b4e2682d4ff56d6bfa4a2ef76c963f5e75f4ff4785f9cf338a80"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:913fac5d594ccabf5e8fbac15b9b3bb9c576d537d49eeec9f664e7a64dde4c4b"}, - {file = "orjson-3.6.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:58f244775f20476e5851e7546df109f75160a5178d44257d437ba6d7e562bfe8"}, - {file = "orjson-3.6.7-cp37-none-win_amd64.whl", hash = "sha256:2d5f45c6b85e5f14646df2d32ecd7ff20fcccc71c0ea1155f4d3df8c5299bbb7"}, - {file = "orjson-3.6.7-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:612d242493afeeb2068bc72ff2544aa3b1e627578fcf92edee9daebb5893ffea"}, - {file = "orjson-3.6.7-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:539cdc5067db38db27985e257772d073cd2eb9462d0a41bde96da4e4e60bd99b"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d103b721bbc4f5703f62b3882e638c0b65fcdd48622531c7ffd45047ef8e87c"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb10a20f80e95102dd35dfbc3a22531661b44a09b55236b012a446955846b023"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:bb68d0da349cf8a68971a48ad179434f75256159fe8b0715275d9b49fa23b7a3"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:4a2c7d0a236aaeab7f69c17b7ab4c078874e817da1bfbb9827cb8c73058b3050"}, - {file = "orjson-3.6.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3be045ca3b96119f592904cf34b962969ce97bd7843cbfca084009f6c8d2f268"}, - {file = "orjson-3.6.7-cp38-none-win_amd64.whl", hash = "sha256:bd765c06c359d8a814b90f948538f957fa8a1f55ad1aaffcdc5771996aaea061"}, - {file = "orjson-3.6.7-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7dd9e1e46c0776eee9e0649e3ae9584ea368d96851bcaeba18e217fa5d755283"}, - {file = "orjson-3.6.7-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c4b4f20a1e3df7e7c83717aff0ef4ab69e42ce2fb1f5234682f618153c458406"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7107a5673fd0b05adbb58bf71c1578fc84d662d29c096eb6d998982c8635c221"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a08b6940dd9a98ccf09785890112a0f81eadb4f35b51b9a80736d1725437e22c"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:f5d1648e5a9d1070f3628a69a7c6c17634dbb0caf22f2085eca6910f7427bf1f"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:e6201494e8dff2ce7fd21da4e3f6dfca1a3fed38f9dcefc972f552f6596a7621"}, - {file = "orjson-3.6.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:70d0386abe02879ebaead2f9632dd2acb71000b4721fd8c1a2fb8c031a38d4d5"}, - {file = "orjson-3.6.7-cp39-none-win_amd64.whl", hash = "sha256:d9a3288861bfd26f3511fb4081561ca768674612bac59513cb9081bb61fcc87f"}, - {file = "orjson-3.6.7.tar.gz", hash = "sha256:a4bb62b11289b7620eead2f25695212e9ac77fcfba76f050fa8a540fb5c32401"}, + {file = "orjson-3.6.8-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:3a287a650458de2211db03681b71c3e5cb2212b62f17a39df8ad99fc54855d0f"}, + {file = "orjson-3.6.8-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5204e25c12cea58e524fc82f7c27ed0586f592f777b33075a92ab7b3eb3687c2"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77e8386393add64f959c044e0fb682364fd0e611a6f477aa13f0e6a733bd6a28"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:279f2d2af393fdf8601020744cb206b91b54ad60fb8401e0761819c7bda1f4e4"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:c31c9f389be7906f978ed4192eb58a4b74a37ad60556a0b88ddc47c576697770"}, + {file = "orjson-3.6.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0db5c5a0c5b89f092d52f6e5a3701660a9d6ffa9e2968b3ce17c2bc4f5eb0414"}, + {file = "orjson-3.6.8-cp310-none-win_amd64.whl", hash = "sha256:eb22485847b9a0c4bbedc668df860126ac931edbed1d456cf41a59f3cb961ed8"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:1a5fe569310bc819279bd4d5f2c349910b104ed3207936246dd5d5e0b085e74a"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:ccb356a47ab1067cd3549847e9db1d279a63fe0482d315b3ffd6e7abef35ef77"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab29c069c222248ce302a25855b4e1664f9436e8ae5a131fb0859daf31676d2b"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d2b5e4cba9e774ac011071d9d27760f97f4b8cd46003e971d122e712f971345"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:c311ec504414d22834d5b972a209619925b48263856a11a14d90230f9682d49c"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:a3dfec7950b90fb8d143743503ee53fa06b32e6068bdea792fc866284da3d71d"}, + {file = "orjson-3.6.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b890dbbada2cbb26eb29bd43a848426f007f094bb0758df10dfe7a438e1cb4b4"}, + {file = "orjson-3.6.8-cp37-none-win_amd64.whl", hash = "sha256:9143ae2c52771525be9ad11a7a8cc8e7fd75391b107e7e644a9e0050496f6b4f"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:33a82199fd42f6436f833e210ae5129c922a5c355629356ca7a8e82964da7285"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:90159ea8b9a5a2a98fa33dc7b421cfac4d2ae91ba5e1058f5909e7f059f6b467"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:656fbe15d9ef0733e740d9def78f4fdb4153102f4836ee774a05123499005931"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7be3be6153843e0f01351b1313a5ad4723595427680dac2dfff22a37e652ce02"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:dd24f66b6697ee7424f7da575ec6cbffc8ede441114d53470949cda4d97c6e56"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:b07c780f7345ecf5901356dc21dee0669defc489c38ce7b9ab0f5e008cc0385c"}, + {file = "orjson-3.6.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ea32015a5d8a4ce00d348a0de5dc7040e0ad58f970a8fcbb5713a1eac129e493"}, + {file = "orjson-3.6.8-cp38-none-win_amd64.whl", hash = "sha256:c5a3e382194c838988ec128a26b08aa92044e5e055491cc4056142af0c1c54d7"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:83a8424e857ae1bf53530e88b4eb2f16ca2b489073b924e655f1575cacd7f52a"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:81e1a6a2d67f15007dadacbf9ba5d3d79237e5e33786c028557fe5a2b72f1c9a"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:137b539881c77866eba86ff6a11df910daf2eb9ab8f1acae62f879e83d7c38af"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cbd358f3b3ad539a27e36900e8e7d172d0e1b72ad9dd7d69544dcbc0f067ee7"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:6ab94701542d40b90903ecfc339333f458884979a01cb9268bc662cc67a5f6d8"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:32b6f26593a9eb606b40775826beb0dac152e3d224ea393688fced036045a821"}, + {file = "orjson-3.6.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:afd9e329ebd3418cac3cd747769b1d52daa25fa672bbf414ab59f0e0881b32b9"}, + {file = "orjson-3.6.8-cp39-none-win_amd64.whl", hash = "sha256:0c89b419914d3d1f65a1b0883f377abe42a6e44f6624ba1c63e8846cbfc2fa60"}, + {file = "orjson-3.6.8.tar.gz", hash = "sha256:e19d23741c5de13689bb316abfccea15a19c264e3ec8eb332a5319a583595ace"}, ] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, @@ -722,71 +641,13 @@ pathspec = [ {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, ] platformdirs = [ - {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, - {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] -psycopg2-binary = [ - {file = "psycopg2-binary-2.9.3.tar.gz", hash = "sha256:761df5313dc15da1502b21453642d7599d26be88bff659382f8f9747c7ebea4e"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:539b28661b71da7c0e428692438efbcd048ca21ea81af618d845e06ebfd29478"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e82d38390a03da28c7985b394ec3f56873174e2c88130e6966cb1c946508e65"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57804fc02ca3ce0dbfbef35c4b3a4a774da66d66ea20f4bda601294ad2ea6092"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:083a55275f09a62b8ca4902dd11f4b33075b743cf0d360419e2051a8a5d5ff76"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:0a29729145aaaf1ad8bafe663131890e2111f13416b60e460dae0a96af5905c9"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a79d622f5206d695d7824cbf609a4f5b88ea6d6dab5f7c147fc6d333a8787e4"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:090f3348c0ab2cceb6dfbe6bf721ef61262ddf518cd6cc6ecc7d334996d64efa"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a9e1f75f96ea388fbcef36c70640c4efbe4650658f3d6a2967b4cc70e907352e"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c3ae8e75eb7160851e59adc77b3a19a976e50622e44fd4fd47b8b18208189d42"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-win32.whl", hash = "sha256:7b1e9b80afca7b7a386ef087db614faebbf8839b7f4db5eb107d0f1a53225029"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:8b344adbb9a862de0c635f4f0425b7958bf5a4b927c8594e6e8d261775796d53"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:e847774f8ffd5b398a75bc1c18fbb56564cda3d629fe68fd81971fece2d3c67e"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68641a34023d306be959101b345732360fc2ea4938982309b786f7be1b43a4a1"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3303f8807f342641851578ee7ed1f3efc9802d00a6f83c101d21c608cb864460"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:e3699852e22aa68c10de06524a3721ade969abf382da95884e6a10ff798f9281"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:526ea0378246d9b080148f2d6681229f4b5964543c170dd10bf4faaab6e0d27f"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:b1c8068513f5b158cf7e29c43a77eb34b407db29aca749d3eb9293ee0d3103ca"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:15803fa813ea05bef089fa78835118b5434204f3a17cb9f1e5dbfd0b9deea5af"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:152f09f57417b831418304c7f30d727dc83a12761627bb826951692cc6491e57"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:404224e5fef3b193f892abdbf8961ce20e0b6642886cfe1fe1923f41aaa75c9d"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-win32.whl", hash = "sha256:1f6b813106a3abdf7b03640d36e24669234120c72e91d5cbaeb87c5f7c36c65b"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:2d872e3c9d5d075a2e104540965a1cf898b52274a5923936e5bfddb58c59c7c2"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:10bb90fb4d523a2aa67773d4ff2b833ec00857f5912bafcfd5f5414e45280fb1"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:874a52ecab70af13e899f7847b3e074eeb16ebac5615665db33bce8a1009cf33"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a29b3ca4ec9defec6d42bf5feb36bb5817ba3c0230dd83b4edf4bf02684cd0ae"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:12b11322ea00ad8db8c46f18b7dfc47ae215e4df55b46c67a94b4effbaec7094"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:53293533fcbb94c202b7c800a12c873cfe24599656b341f56e71dd2b557be063"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c381bda330ddf2fccbafab789d83ebc6c53db126e4383e73794c74eedce855ef"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d29409b625a143649d03d0fd7b57e4b92e0ecad9726ba682244b73be91d2fdb"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:183a517a3a63503f70f808b58bfbf962f23d73b6dccddae5aa56152ef2bcb232"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:15c4e4cfa45f5a60599d9cec5f46cd7b1b29d86a6390ec23e8eebaae84e64554"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-win32.whl", hash = "sha256:adf20d9a67e0b6393eac162eb81fb10bc9130a80540f4df7e7355c2dd4af9fba"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:2f9ffd643bc7349eeb664eba8864d9e01f057880f510e4681ba40a6532f93c71"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:def68d7c21984b0f8218e8a15d514f714d96904265164f75f8d3a70f9c295667"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dffc08ca91c9ac09008870c9eb77b00a46b3378719584059c034b8945e26b272"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:280b0bb5cbfe8039205c7981cceb006156a675362a00fe29b16fbc264e242834"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:af9813db73395fb1fc211bac696faea4ca9ef53f32dc0cfa27e4e7cf766dcf24"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:63638d875be8c2784cfc952c9ac34e2b50e43f9f0a0660b65e2a87d656b3116c"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ffb7a888a047696e7f8240d649b43fb3644f14f0ee229077e7f6b9f9081635bd"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0c9d5450c566c80c396b7402895c4369a410cab5a82707b11aee1e624da7d004"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:d1c1b569ecafe3a69380a94e6ae09a4789bbb23666f3d3a08d06bbd2451f5ef1"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8fc53f9af09426a61db9ba357865c77f26076d48669f2e1bb24d85a22fb52307"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-win32.whl", hash = "sha256:6472a178e291b59e7f16ab49ec8b4f3bdada0a879c68d3817ff0963e722a82ce"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:35168209c9d51b145e459e05c31a9eaeffa9a6b0fd61689b48e07464ffd1a83e"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:47133f3f872faf28c1e87d4357220e809dfd3fa7c64295a4a148bcd1e6e34ec9"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91920527dea30175cc02a1099f331aa8c1ba39bf8b7762b7b56cbf54bc5cce42"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887dd9aac71765ac0d0bac1d0d4b4f2c99d5f5c1382d8b770404f0f3d0ce8a39"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:1f14c8b0942714eb3c74e1e71700cbbcb415acbc311c730370e70c578a44a25c"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:7af0dd86ddb2f8af5da57a976d27cd2cd15510518d582b478fbb2292428710b4"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93cd1967a18aa0edd4b95b1dfd554cf15af657cb606280996d393dadc88c3c35"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bda845b664bb6c91446ca9609fc69f7db6c334ec5e4adc87571c34e4f47b7ddb"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:01310cf4cf26db9aea5158c217caa92d291f0500051a6469ac52166e1a16f5b7"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:99485cab9ba0fa9b84f1f9e1fef106f44a46ef6afdeec8885e0b88d0772b49e8"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-win32.whl", hash = "sha256:46f0e0a6b5fa5851bbd9ab1bc805eef362d3a230fbdfbc209f4a236d0a7a990d"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:accfe7e982411da3178ec690baaceaad3c278652998b2c45828aaac66cd8285f"}, -] py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, @@ -851,8 +712,8 @@ tomli = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] typing-extensions = [ - {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, - {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, + {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, + {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, ] uvloop = [ {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, diff --git a/packages/core/minos-microservice-saga/pyproject.toml b/packages/core/minos-microservice-saga/pyproject.toml index 2aeb27abb..91aca7cba 100644 --- a/packages/core/minos-microservice-saga/pyproject.toml +++ b/packages/core/minos-microservice-saga/pyproject.toml @@ -31,7 +31,7 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-aggregate = { version ="^0.7.0*", allow-prereleases = true } +minos-microservice-transactions = { version ="^0.0.0*", allow-prereleases = true } minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true } minos-microservice-networks = { version ="^0.7.0*", allow-prereleases = true } cached-property = "^1.5.2" @@ -39,7 +39,7 @@ cached-property = "^1.5.2" [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../minos-microservice-common", develop = true } minos-microservice-networks = { path = "../minos-microservice-networks", develop = true } -minos-microservice-aggregate = { path = "../minos-microservice-aggregate", develop = true } +minos-microservice-transactions = { path = "../minos-microservice-transactions", develop = true } black = "^22.3" isort = "^5.8.0" pytest = "^7.0.1" diff --git a/packages/core/minos-microservice-saga/tests/test_saga/test_executions/test_executors/test_abc.py b/packages/core/minos-microservice-saga/tests/test_saga/test_executions/test_executors/test_abc.py index b6b1dcaf2..e976034cd 100644 --- a/packages/core/minos-microservice-saga/tests/test_saga/test_executions/test_executors/test_abc.py +++ b/packages/core/minos-microservice-saga/tests/test_saga/test_executions/test_executors/test_abc.py @@ -3,14 +3,14 @@ uuid4, ) -from minos.aggregate import ( - TransactionStatus, -) from minos.saga import ( Executor, SagaContext, SagaOperation, ) +from minos.transactions import ( + TransactionStatus, +) from tests.utils import ( SagaTestCase, ) diff --git a/packages/core/minos-microservice-saga/tests/test_saga/test_middleware.py b/packages/core/minos-microservice-saga/tests/test_saga/test_middleware.py index d18ab3ede..a08aa3403 100644 --- a/packages/core/minos-microservice-saga/tests/test_saga/test_middleware.py +++ b/packages/core/minos-microservice-saga/tests/test_saga/test_middleware.py @@ -6,9 +6,6 @@ uuid4, ) -from minos.aggregate import ( - TransactionStatus, -) from minos.networks import ( REQUEST_HEADERS_CONTEXT_VAR, BrokerRequest, @@ -18,6 +15,9 @@ from minos.saga import ( transactional_command, ) +from minos.transactions import ( + TransactionStatus, +) from tests.utils import ( SagaTestCase, ) diff --git a/packages/core/minos-microservice-saga/tests/utils.py b/packages/core/minos-microservice-saga/tests/utils.py index 4a4203831..7c1870a25 100644 --- a/packages/core/minos-microservice-saga/tests/utils.py +++ b/packages/core/minos-microservice-saga/tests/utils.py @@ -9,11 +9,6 @@ Any, ) -from minos.aggregate import ( - InMemoryEventRepository, - InMemorySnapshotRepository, - InMemoryTransactionRepository, -) from minos.common import ( DeclarativeModel, Lock, @@ -36,6 +31,9 @@ SagaResponse, testing, ) +from minos.transactions import ( + InMemoryTransactionRepository, +) BASE_PATH = Path(__file__).parent CONFIG_FILE_PATH = BASE_PATH / "config.yml" @@ -55,21 +53,11 @@ def get_injections(self): broker_publisher = InMemoryBrokerPublisher() broker_subscriber_builder = InMemoryBrokerSubscriberBuilder() transaction_repository = InMemoryTransactionRepository(lock_pool=pool_factory.get_pool("lock")) - event_repository = InMemoryEventRepository( - broker_publisher=broker_publisher, - transaction_repository=transaction_repository, - lock_pool=pool_factory.get_pool("lock"), - ) - snapshot_repository = InMemorySnapshotRepository( - event_repository=event_repository, transaction_repository=transaction_repository - ) return [ pool_factory, broker_publisher, broker_subscriber_builder, transaction_repository, - event_repository, - snapshot_repository, ] diff --git a/packages/core/minos-microservice-transactions/minos/transactions/__init__.py b/packages/core/minos-microservice-transactions/minos/transactions/__init__.py index 2f933ee0d..fb9f69663 100644 --- a/packages/core/minos-microservice-transactions/minos/transactions/__init__.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/__init__.py @@ -3,3 +3,28 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" __version__ = "0.7.0.dev1" + +from .contextvars import ( + TRANSACTION_CONTEXT_VAR, +) +from .entries import ( + TransactionEntry, + TransactionStatus, +) +from .exceptions import ( + TransactionNotFoundException, + TransactionRepositoryConflictException, + TransactionRepositoryException, +) +from .mixins import ( + TransactionalMixin, +) +from .repositories import ( + DatabaseTransactionRepository, + InMemoryTransactionRepository, + TransactionDatabaseOperationFactory, + TransactionRepository, +) +from .services import ( + TransactionService, +) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/contextvars.py b/packages/core/minos-microservice-transactions/minos/transactions/contextvars.py similarity index 100% rename from packages/core/minos-microservice-aggregate/minos/aggregate/transactions/contextvars.py rename to packages/core/minos-microservice-transactions/minos/transactions/contextvars.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py b/packages/core/minos-microservice-transactions/minos/transactions/entries.py similarity index 99% rename from packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py rename to packages/core/minos-microservice-transactions/minos/transactions/entries.py index 84e45acf2..68c7af08e 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/entries.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/entries.py @@ -33,12 +33,12 @@ NotProvidedException, ) -from ..exceptions import ( - TransactionRepositoryConflictException, -) from .contextvars import ( TRANSACTION_CONTEXT_VAR, ) +from .exceptions import ( + TransactionRepositoryConflictException, +) if TYPE_CHECKING: from .repositories import ( diff --git a/packages/core/minos-microservice-transactions/minos/transactions/exceptions.py b/packages/core/minos-microservice-transactions/minos/transactions/exceptions.py new file mode 100644 index 000000000..100a7459f --- /dev/null +++ b/packages/core/minos-microservice-transactions/minos/transactions/exceptions.py @@ -0,0 +1,15 @@ +from minos.common import ( + MinosException, +) + + +class TransactionRepositoryException(MinosException): + """Base transaction repository exception.""" + + +class TransactionRepositoryConflictException(TransactionRepositoryException): + """Exception to be raised when a transaction has invalid status.""" + + +class TransactionNotFoundException(TransactionRepositoryException): + """Exception to be raised when some transaction is not found on the repository.""" diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py b/packages/core/minos-microservice-transactions/minos/transactions/mixins.py similarity index 100% rename from packages/core/minos-microservice-aggregate/minos/aggregate/transactions/mixins.py rename to packages/core/minos-microservice-transactions/minos/transactions/mixins.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/__init__.py b/packages/core/minos-microservice-transactions/minos/transactions/repositories/__init__.py similarity index 100% rename from packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/__init__.py rename to packages/core/minos-microservice-transactions/minos/transactions/repositories/__init__.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py b/packages/core/minos-microservice-transactions/minos/transactions/repositories/abc.py similarity index 99% rename from packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py rename to packages/core/minos-microservice-transactions/minos/transactions/repositories/abc.py index 75429a42b..da029fc04 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/abc.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/repositories/abc.py @@ -31,13 +31,13 @@ SetupMixin, ) -from ...exceptions import ( - TransactionNotFoundException, -) from ..entries import ( TransactionEntry, TransactionStatus, ) +from ..exceptions import ( + TransactionNotFoundException, +) if TYPE_CHECKING: from ..mixins import ( diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/__init__.py b/packages/core/minos-microservice-transactions/minos/transactions/repositories/database/__init__.py similarity index 100% rename from packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/__init__.py rename to packages/core/minos-microservice-transactions/minos/transactions/repositories/database/__init__.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/factories.py b/packages/core/minos-microservice-transactions/minos/transactions/repositories/database/factories.py similarity index 100% rename from packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/factories.py rename to packages/core/minos-microservice-transactions/minos/transactions/repositories/database/factories.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/impl.py b/packages/core/minos-microservice-transactions/minos/transactions/repositories/database/impl.py similarity index 98% rename from packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/impl.py rename to packages/core/minos-microservice-transactions/minos/transactions/repositories/database/impl.py index 730bf1f14..4a320cb3c 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/database/impl.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/repositories/database/impl.py @@ -12,12 +12,12 @@ ProgrammingException, ) -from ....exceptions import ( - TransactionRepositoryConflictException, -) from ...entries import ( TransactionEntry, ) +from ...exceptions import ( + TransactionRepositoryConflictException, +) from ..abc import ( TransactionRepository, ) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py b/packages/core/minos-microservice-transactions/minos/transactions/repositories/memory.py similarity index 99% rename from packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py rename to packages/core/minos-microservice-transactions/minos/transactions/repositories/memory.py index 1c52c8530..115820091 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/repositories/memory.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/repositories/memory.py @@ -13,13 +13,13 @@ current_datetime, ) -from ...exceptions import ( - TransactionRepositoryConflictException, -) from ..entries import ( TransactionEntry, ) from ..entries import TransactionStatus as s +from ..exceptions import ( + TransactionRepositoryConflictException, +) from .abc import ( TransactionRepository, ) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/services.py b/packages/core/minos-microservice-transactions/minos/transactions/services.py similarity index 99% rename from packages/core/minos-microservice-aggregate/minos/aggregate/transactions/services.py rename to packages/core/minos-microservice-transactions/minos/transactions/services.py index c40c75e92..ec1aae562 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/transactions/services.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/services.py @@ -15,13 +15,13 @@ enroute, ) -from ..exceptions import ( - TransactionNotFoundException, - TransactionRepositoryConflictException, -) from .entries import ( TransactionStatus, ) +from .exceptions import ( + TransactionNotFoundException, + TransactionRepositoryConflictException, +) from .repositories import ( TransactionRepository, ) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/__init__.py b/packages/core/minos-microservice-transactions/minos/transactions/testing/__init__.py similarity index 100% rename from packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/__init__.py rename to packages/core/minos-microservice-transactions/minos/transactions/testing/__init__.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/__init__.py b/packages/core/minos-microservice-transactions/minos/transactions/testing/repositories/__init__.py similarity index 100% rename from packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/__init__.py rename to packages/core/minos-microservice-transactions/minos/transactions/testing/repositories/__init__.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/factories.py b/packages/core/minos-microservice-transactions/minos/transactions/testing/repositories/factories.py similarity index 96% rename from packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/factories.py rename to packages/core/minos-microservice-transactions/minos/transactions/testing/repositories/factories.py index eef9e3564..be37d48d4 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/factories.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/testing/repositories/factories.py @@ -19,10 +19,12 @@ MockedDatabaseOperation, ) -from ....transactions import ( - TransactionDatabaseOperationFactory, +from ...entries import ( TransactionStatus, ) +from ...repositories import ( + TransactionDatabaseOperationFactory, +) class MockedTransactionDatabaseOperationFactory(TransactionDatabaseOperationFactory): diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/testcases.py b/packages/core/minos-microservice-transactions/minos/transactions/testing/repositories/testcases.py similarity index 99% rename from packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/testcases.py rename to packages/core/minos-microservice-transactions/minos/transactions/testing/repositories/testcases.py index c5257bb1d..4bc55847e 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/transactions/repositories/testcases.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/testing/repositories/testcases.py @@ -6,14 +6,19 @@ uuid4, ) -from minos.aggregate import ( +from minos.common.testing import ( + MinosTestCase, +) + +from ...entries import ( TransactionEntry, - TransactionRepository, - TransactionRepositoryConflictException, TransactionStatus, ) -from minos.common.testing import ( - MinosTestCase, +from ...exceptions import ( + TransactionRepositoryConflictException, +) +from ...repositories import ( + TransactionRepository, ) diff --git a/packages/core/minos-microservice-transactions/poetry.lock b/packages/core/minos-microservice-transactions/poetry.lock index 4817307d2..ac8ec33d1 100644 --- a/packages/core/minos-microservice-transactions/poetry.lock +++ b/packages/core/minos-microservice-transactions/poetry.lock @@ -115,6 +115,14 @@ python-versions = ">=3.7" [package.extras] toml = ["tomli"] +[[package]] +name = "crontab" +version = "0.23.0" +description = "Parse and use crontab schedules in Python" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "dependency-injector" version = "4.39.1" @@ -181,14 +189,6 @@ requirements_deprecated_finder = ["pipreqs", "pip-api"] colors = ["colorama (>=0.4.3,<0.5.0)"] plugins = ["setuptools"] -[[package]] -name = "lmdb" -version = "1.3.0" -description = "Universal Python binding for the LMDB 'Lightning' Database" -category = "main" -optional = false -python-versions = "*" - [[package]] name = "mccabe" version = "0.6.1" @@ -211,7 +211,6 @@ aiomisc = ">=14.0.3,<15.8.0" cached-property = "^1.5.2" dependency-injector = "^4.32.2" fastavro = "^1.4.0" -lmdb = "^1.2.1" orjson = "^3.5.2" PyYAML = ">=5.4.1,<7.0.0" uvloop = "^0.16.0" @@ -220,6 +219,23 @@ uvloop = "^0.16.0" type = "directory" url = "../minos-microservice-common" +[[package]] +name = "minos-microservice-networks" +version = "0.7.0.dev1" +description = "The networks core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +crontab = "^0.23.0" +minos-microservice-common = "^0.7.0*" + +[package.source] +type = "directory" +url = "../minos-microservice-networks" + [[package]] name = "mypy-extensions" version = "0.4.3" @@ -383,7 +399,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "4c34a5eab6efb983f4ab2f609f54e5a8475bad1de65c75cce36989757379ea2d" +content-hash = "9c9ca4862b7363ae69ed21727f7a65a29a33e373df45250938f7c75f398b8da5" [metadata.files] aiomisc = [ @@ -482,6 +498,9 @@ coverage = [ {file = "coverage-6.3.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf"}, {file = "coverage-6.3.2.tar.gz", hash = "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9"}, ] +crontab = [ + {file = "crontab-0.23.0.tar.gz", hash = "sha256:ca79dede9c2f572bb32f38703e8fddcf3427e86edc838f2ffe7ae4b9ee2b0733"}, +] dependency-injector = [ {file = "dependency-injector-4.39.1.tar.gz", hash = "sha256:9ab76dc5e19b2692aaca49e00f9b41a087138d139b0ec985f92ff0498f038772"}, {file = "dependency_injector-4.39.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c788a3d5482e63b5fd55e14fc258f1ff0b51b411927ab132ef0f689cb5d1183f"}, @@ -550,40 +569,12 @@ isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] -lmdb = [ - {file = "lmdb-1.3.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:63cb73fe7ce9eb93d992d632c85a0476b4332670d9e6a2802b5062f603b7809f"}, - {file = "lmdb-1.3.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:abbc439cd9fe60ffd6197009087ea885ac150017dc85384093b1d376f83f0ec4"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6260a526e4ad85b1f374a5ba9475bf369fb07e7728ea6ec57226b02c40d1976b"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e568ae0887ae196340947d9800136e90feaed6b86a261ef01f01b2ba65fc8106"}, - {file = "lmdb-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6a816954d212f40fd15007cd81ab7a6bebb77436d949a6a9ae04af57fc127f3"}, - {file = "lmdb-1.3.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fa6439356e591d3249ab0e1778a6f8d8408e993f66dc911914c78208f5310309"}, - {file = "lmdb-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:c6adbd6f7f9048e97f31a069e652eb51020a81e80a0ce92dbb9810d21da2409a"}, - {file = "lmdb-1.3.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:eefb392f6b5cd43aada49258c5a79be11cb2c8cd3fc3e2d9319a1e0b9f906458"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a14aca2651c3af6f0d0a6b9168200eea0c8f2d27c40b01a442f33329a6e8dff"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfa4aa9c67f8aee89b23005e98d1f3f32490b6b905fd1cb604b207cbd5755ab"}, - {file = "lmdb-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7da05d70fcc6561ac6b09e9fb1bf64b7ca294652c64c8a2889273970cee796b9"}, - {file = "lmdb-1.3.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:008243762decf8f6c90430a9bced56290ebbcdb5e877d90e42343bb97033e494"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:17215a42a4b9814c383deabecb160581e4fb75d00198eef0e3cea54f230ffbea"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65334eafa5d430b18d81ebd5362559a41483c362e1931f6e1b15bab2ecb7d75d"}, - {file = "lmdb-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:18c69fabdaf04efaf246587739cc1062b3e57c6ef0743f5c418df89e5e7e7b9b"}, - {file = "lmdb-1.3.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:41318717ab5d15ad2d6d263d34fbf614a045210f64b25e59ce734bb2105e421f"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:df2724bad7820114a205472994091097d0fa65a3e5fff5a8e688d123fb8c6326"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddd590e1c7fcb395931aa3782fb89b9db4550ab2d81d006ecd239e0d462bc41"}, - {file = "lmdb-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:4172fba19417d7b29409beca7d73c067b54e5d8ab1fb9b51d7b4c1445d20a167"}, - {file = "lmdb-1.3.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2df38115dd9428a54d59ae7c712a4c7cce0d6b1d66056de4b1a8c38718066106"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9103aa4908f0bca43c5911ca067d4e3d01f682dff0c0381a1239bd2bd757984"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:394df860c3f93cfd92b6f4caba785f38208cc9614c18b3803f83a2cc1695042f"}, - {file = "lmdb-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:62ab28e3593bdc318ea2f2fa1574e5fca3b6d1f264686d773ba54a637d4f563b"}, - {file = "lmdb-1.3.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:e6a704b3baced9182836c7f77b769f23856f3a8f62d0282b1bc1feaf81a86712"}, - {file = "lmdb-1.3.0-pp27-pypy_73-win_amd64.whl", hash = "sha256:08f4b5129f4683802569b02581142e415c8dcc0ff07605983ec1b07804cecbad"}, - {file = "lmdb-1.3.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:f291e3f561f58dddf63a92a5a6a4b8af3a0920b6705d35e2f80e52e86ee238a2"}, - {file = "lmdb-1.3.0.tar.gz", hash = "sha256:60a11efc21aaf009d06518996360eed346f6000bfc9de05114374230879f992e"}, -] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] minos-microservice-common = [] +minos-microservice-networks = [] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, diff --git a/packages/core/minos-microservice-transactions/pyproject.toml b/packages/core/minos-microservice-transactions/pyproject.toml index 8a9906365..4cc1b8889 100644 --- a/packages/core/minos-microservice-transactions/pyproject.toml +++ b/packages/core/minos-microservice-transactions/pyproject.toml @@ -32,10 +32,12 @@ include = [ [tool.poetry.dependencies] python = "^3.9" minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true } +minos-microservice-networks = { version ="^0.7.0*", allow-prereleases = true } cached-property = "^1.5.2" [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../minos-microservice-common", develop = true } +minos-microservice-networks = { path = "../minos-microservice-networks", develop = true } black = "^22.3" isort = "^5.8.0" pytest = "^7.0.1" diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_entries.py similarity index 81% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py rename to packages/core/minos-microservice-transactions/tests/test_transactions/test_entries.py index a27ae3e3a..3fb85c318 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_entries.py +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_entries.py @@ -2,6 +2,7 @@ from datetime import ( datetime, ) +from typing import Optional from unittest.mock import ( AsyncMock, MagicMock, @@ -13,23 +14,31 @@ uuid4, ) -from minos.aggregate import ( +from minos.common import ( + NULL_UUID, Lock, +) +from minos.transactions import ( TRANSACTION_CONTEXT_VAR, TransactionalMixin, TransactionEntry, TransactionRepositoryConflictException, TransactionStatus, ) -from minos.common import ( - NULL_UUID, -) from tests.utils import ( - AggregateTestCase, - FakeAsyncIterator, + TransactionsTestCase, + FakeAsyncIterator, FakeLock, ) -class TestTransactionEntry(AggregateTestCase): +class _TransactionalObserver(TransactionalMixin): + """For testing purposes.""" + + def write_lock(self) -> Optional[Lock]: + """For testing purposes.""" + return FakeLock("foo") + + +class TestTransactionEntry(TransactionsTestCase): def test_constructor(self): transaction = TransactionEntry() @@ -62,9 +71,9 @@ async def test_async_context_manager_with_context_var(self): self.assertEqual(TRANSACTION_CONTEXT_VAR.get(), None) async def test_async_context_manager(self): - with patch.object(TransactionEntry, "save") as save_mock, patch.object( - TransactionEntry, "commit" - ) as commit_mock: + p1 = patch.object(TransactionEntry, "save") + p2 = patch.object(TransactionEntry, "commit") + with p1 as save_mock, p2 as commit_mock: async with TransactionEntry(): self.assertEqual(1, save_mock.call_count) self.assertEqual(0, commit_mock.call_count) @@ -72,7 +81,8 @@ async def test_async_context_manager(self): self.assertEqual(1, commit_mock.call_count) async def test_async_context_manager_without_autocommit(self): - with patch.object(TransactionEntry, "commit") as commit_mock: + p1 = patch.object(TransactionEntry, "commit") + with p1 as commit_mock: async with TransactionEntry(autocommit=False) as transaction: self.assertEqual(0, commit_mock.call_count) transaction.status = TransactionStatus.PENDING @@ -107,10 +117,11 @@ async def test_reserve_success(self) -> None: transaction = TransactionEntry(uuid, TransactionStatus.PENDING) - with patch.object(TransactionEntry, "save") as save_mock, patch.object( - TransactionEntry, "validate", return_value=True - ) as validate_mock: - await transaction.reserve() + p1 = patch.object(TransactionEntry, "save") + p2 = patch.object(TransactionEntry, "validate", return_value=True) + with p1 as save_mock, p2 as validate_mock: + async with _TransactionalObserver(): + await transaction.reserve() self.assertEqual(1, validate_mock.call_count) self.assertEqual(call(), validate_mock.call_args) @@ -124,9 +135,9 @@ async def test_reserve_failure(self) -> None: uuid = uuid4() transaction = TransactionEntry(uuid, TransactionStatus.PENDING) - with patch.object(TransactionEntry, "save") as save_mock, patch.object( - TransactionEntry, "validate", return_value=False - ) as validate_mock: + p1 = patch.object(TransactionEntry, "save") + p2 = patch.object(TransactionEntry, "validate", return_value=False) + with p1 as save_mock, p2 as validate_mock: with self.assertRaises(TransactionRepositoryConflictException): await transaction.reserve() @@ -150,17 +161,17 @@ async def test_validate_true(self): uuid = uuid4() another = uuid4() - observer_mock = AsyncMock(return_value={another}) select_transaction_mock = MagicMock(return_value=FakeAsyncIterator([])) - self.event_repository.get_collided_transactions = observer_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid) + p1 = patch.object(TransactionalMixin, "get_collided_transactions", return_value={another}) + with p1 as get_collided_mock: + async with _TransactionalObserver(): + self.assertTrue(await transaction.validate()) - self.assertTrue(await transaction.validate()) - - self.assertEqual([call(transaction_uuid=uuid)], observer_mock.call_args_list) + self.assertEqual([call(transaction_uuid=uuid)], get_collided_mock.call_args_list) self.assertEqual( [ call( @@ -193,17 +204,17 @@ async def test_validate_false_destination_already(self): transaction_event_1 = [TransactionEntry(another, TransactionStatus.RESERVED)] - select_event_mock = AsyncMock(return_value={another}) select_transaction_mock = MagicMock(return_value=FakeAsyncIterator(transaction_event_1)) - self.event_repository.get_collided_transactions = select_event_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid, destination_uuid=another) + p1 = patch.object(TransactionalMixin, "get_collided_transactions", return_value={another}) + with p1 as get_collided_mock: + async with _TransactionalObserver(): + self.assertFalse(await transaction.validate()) - self.assertFalse(await transaction.validate()) - - self.assertEqual([], select_event_mock.call_args_list) + self.assertEqual([], get_collided_mock.call_args_list) self.assertEqual( [ call( @@ -225,19 +236,20 @@ async def test_validate_false_already_committed(self): select_transaction_1 = [] - select_event_mock = AsyncMock(return_value={NULL_UUID}) select_transaction_mock = MagicMock( side_effect=[FakeAsyncIterator([]), FakeAsyncIterator(select_transaction_1)], ) - self.event_repository.get_collided_transactions = select_event_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid) - self.assertFalse(await transaction.validate()) + p1 = patch.object(TransactionalMixin, "get_collided_transactions", return_value={NULL_UUID}) + with p1 as get_collided_mock: + async with _TransactionalObserver(): + self.assertFalse(await transaction.validate()) - self.assertEqual([call(transaction_uuid=uuid)], select_event_mock.call_args_list) + self.assertEqual([call(transaction_uuid=uuid)], get_collided_mock.call_args_list) self.assertEqual( [ call( @@ -260,19 +272,19 @@ async def test_validate_false_already_reserved(self): select_transaction_1 = [TransactionEntry(another, TransactionStatus.RESERVED)] - select_event_mock = AsyncMock(return_value={another}) select_transaction_mock = MagicMock( side_effect=[FakeAsyncIterator([]), FakeAsyncIterator(select_transaction_1)], ) - self.event_repository.get_collided_transactions = select_event_mock self.transaction_repository.select = select_transaction_mock transaction = TransactionEntry(uuid) + p1 = patch.object(TransactionalMixin, "get_collided_transactions", return_value={another}) + with p1 as get_collided_mock: + async with _TransactionalObserver(): + self.assertFalse(await transaction.validate()) - self.assertFalse(await transaction.validate()) - - self.assertEqual([call(transaction_uuid=uuid)], select_event_mock.call_args_list) + self.assertEqual([call(transaction_uuid=uuid)], get_collided_mock.call_args_list) self.assertEqual( [ call( @@ -304,12 +316,13 @@ async def test_reject(self) -> None: transaction = TransactionEntry(uuid, TransactionStatus.RESERVED) - with patch.object(TransactionalMixin, "reject_transaction") as observable_mock, patch.object( - TransactionEntry, "save" - ) as save_mock: - await transaction.reject() + p1 = patch.object(TransactionalMixin, "reject_transaction") + p2 = patch.object(TransactionEntry, "save") + with p1 as reject_mock, p2 as save_mock: + async with _TransactionalObserver(): + await transaction.reject() - self.assertEqual([call(transaction_uuid=transaction.uuid)], observable_mock.call_args_list) + self.assertEqual([call(transaction_uuid=transaction.uuid)], reject_mock.call_args_list) self.assertEqual([call(status=TransactionStatus.REJECTED)], save_mock.call_args_list) async def test_reject_raises(self) -> None: @@ -322,18 +335,16 @@ async def test_commit(self) -> None: uuid = uuid4() another = uuid4() - commit_transaction = AsyncMock() - - self.event_repository.commit_transaction = commit_transaction - transaction = TransactionEntry(uuid, TransactionStatus.RESERVED, destination_uuid=another) - - with patch.object(TransactionEntry, "save") as save_mock: - await transaction.commit() + p1 = patch.object(TransactionalMixin, "commit_transaction", return_value={another}) + p2 = patch.object(TransactionEntry, "save") + with p1 as commit_mock, p2 as save_mock: + async with _TransactionalObserver(): + await transaction.commit() self.assertEqual( [call(transaction_uuid=uuid, destination_transaction_uuid=another)], - commit_transaction.call_args_list, + commit_mock.call_args_list, ) self.assertEqual( @@ -349,9 +360,10 @@ async def test_commit_pending(self) -> None: async def _fn(): transaction.status = TransactionStatus.RESERVED - with patch.object(TransactionEntry, "reserve", side_effect=_fn) as reserve_mock, patch.object( - TransactionEntry, "save" - ) as save_mock, patch.object(TransactionEntry, "_commit", return_value=True) as commit_mock: + p1 = patch.object(TransactionEntry, "reserve", side_effect=_fn) + p2 = patch.object(TransactionEntry, "save") + p3 = patch.object(TransactionEntry, "_commit", return_value=True) + with p1 as reserve_mock, p2 as save_mock, p3 as commit_mock: await transaction.commit() self.assertEqual(1, reserve_mock.call_count) diff --git a/packages/core/minos-microservice-transactions/tests/test_transactions/test_exceptions.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_exceptions.py new file mode 100644 index 000000000..ec65334d9 --- /dev/null +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_exceptions.py @@ -0,0 +1,28 @@ +import unittest + +from minos.common import ( + MinosException, +) +from minos.transactions import ( + TransactionRepositoryConflictException, + TransactionRepositoryException, +) +from tests.utils import ( + TransactionsTestCase, +) + + +class TestExceptions(TransactionsTestCase): + def test_transaction(self): + self.assertTrue(issubclass(TransactionRepositoryException, MinosException)) + + def test_transaction_conflict(self): + message = "There was a conflict" + exception = TransactionRepositoryConflictException(message) + + self.assertIsInstance(exception, TransactionRepositoryException) + self.assertEqual(message, str(exception)) + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_mixins.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_mixins.py similarity index 73% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_mixins.py rename to packages/core/minos-microservice-transactions/tests/test_transactions/test_mixins.py index 78ed050e6..24c8710db 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_mixins.py +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_mixins.py @@ -3,18 +3,18 @@ uuid4, ) -from minos.aggregate import ( - TransactionalMixin, -) from minos.common import ( - SetupMixin, + SetupMixin, NotProvidedException, +) +from minos.transactions import ( + TransactionalMixin, ) from tests.utils import ( - AggregateTestCase, + TransactionsTestCase, ) -class TestTransactionalMixin(AggregateTestCase): +class TestTransactionalMixin(TransactionsTestCase): def test_abstract(self) -> None: self.assertTrue(issubclass(TransactionalMixin, SetupMixin)) @@ -22,6 +22,11 @@ def test_constructor(self): observer = TransactionalMixin() self.assertEqual(self.transaction_repository, observer.transaction_repository) + def test_constructor_raises(self): + with self.assertRaises(NotProvidedException): + # noinspection PyTypeChecker + TransactionalMixin(transaction_repository=None) + async def test_register_into_observable(self): observer = TransactionalMixin() self.assertNotIn(observer, self.transaction_repository.observers) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/__init__.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/__init__.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/__init__.py rename to packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/__init__.py diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_abc.py similarity index 97% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py rename to packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_abc.py index 6ecd4c59d..215d65f39 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_abc.py @@ -14,19 +14,19 @@ uuid4, ) -from minos.aggregate import ( +from minos.common import ( + NotProvidedException, + SetupMixin, +) +from minos.transactions import ( TransactionalMixin, TransactionEntry, TransactionNotFoundException, TransactionRepository, TransactionStatus, ) -from minos.common import ( - NotProvidedException, - SetupMixin, -) from tests.utils import ( - AggregateTestCase, + TransactionsTestCase, FakeAsyncIterator, FakeLock, ) @@ -42,7 +42,7 @@ def _select(self, **kwargs) -> AsyncIterator[TransactionEntry]: """For testing purposes.""" -class TestTransactionRepository(AggregateTestCase): +class TestTransactionRepository(TransactionsTestCase): def setUp(self) -> None: super().setUp() self.transaction_repository = _TransactionRepository() diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_database.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_database.py similarity index 97% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_database.py rename to packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_database.py index b99fac437..35fac3d7d 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_database.py +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_database.py @@ -3,27 +3,27 @@ patch, ) -from minos.aggregate import ( +from minos.common import ( + DatabaseClient, + ProgrammingException, + current_datetime, +) +from minos.transactions import ( DatabaseTransactionRepository, TransactionRepository, TransactionStatus, ) -from minos.aggregate.testing import ( +from minos.transactions.testing import ( TransactionRepositoryTestCase, ) -from minos.common import ( - DatabaseClient, - ProgrammingException, - current_datetime, -) from tests.utils import ( - AggregateTestCase, + TransactionsTestCase, FakeAsyncIterator, ) # noinspection SqlNoDataSourceInspection -class TestDatabaseTransactionRepository(AggregateTestCase, TransactionRepositoryTestCase): +class TestDatabaseTransactionRepository(TransactionsTestCase, TransactionRepositoryTestCase): __test__ = True def build_transaction_repository(self) -> TransactionRepository: diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_memory.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_memory.py similarity index 63% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_memory.py rename to packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_memory.py index 95ba70979..f22dd3301 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/test_memory.py +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_memory.py @@ -1,18 +1,18 @@ import unittest -from minos.aggregate import ( +from minos.transactions import ( InMemoryTransactionRepository, TransactionRepository, ) -from minos.aggregate.testing import ( +from minos.transactions.testing import ( TransactionRepositoryTestCase, ) from tests.utils import ( - AggregateTestCase, + TransactionsTestCase, ) -class TestInMemoryTransactionRepository(AggregateTestCase, TransactionRepositoryTestCase): +class TestInMemoryTransactionRepository(TransactionsTestCase, TransactionRepositoryTestCase): __test__ = True def build_transaction_repository(self) -> TransactionRepository: diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_services.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_services.py similarity index 90% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_services.py rename to packages/core/minos-microservice-transactions/tests/test_transactions/test_services.py index fdb1a12f5..d86b610f1 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_services.py +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_services.py @@ -10,14 +10,6 @@ uuid4, ) -from minos.aggregate import ( - TransactionEntry, - TransactionNotFoundException, - TransactionRepository, - TransactionRepositoryConflictException, - TransactionService, - TransactionStatus, -) from minos.common import ( current_datetime, ) @@ -30,13 +22,21 @@ PeriodicEventEnrouteDecorator, ResponseException, ) +from minos.transactions import ( + TransactionEntry, + TransactionNotFoundException, + TransactionRepository, + TransactionRepositoryConflictException, + TransactionService, + TransactionStatus, +) from tests.utils import ( - AggregateTestCase, + TransactionsTestCase, FakeAsyncIterator, ) -class TestSnapshotService(AggregateTestCase, DatabaseMinosTestCase): +class TestSnapshotService(TransactionsTestCase, DatabaseMinosTestCase): def setUp(self) -> None: super().setUp() @@ -83,8 +83,9 @@ async def test_reject(self): async def test_reject_already(self): uuid = uuid4() with patch.object(TransactionEntry, "reject") as reject_mock: - with patch( - "minos.aggregate.TransactionRepository.get", + with patch.object( + TransactionRepository, + "get", return_value=TransactionEntry(uuid, status=TransactionStatus.REJECTED), ) as get_mock: response = await self.service.__reject__(InMemoryRequest(uuid)) @@ -98,9 +99,7 @@ async def test_reject_raises(self): await self.service.__reject__(InMemoryRequest(None)) with patch.object(TransactionRepository, "get", return_value=TransactionEntry()): - with patch( - "minos.aggregate.TransactionEntry.reject", side_effect=TransactionRepositoryConflictException("") - ): + with patch.object(TransactionEntry, "reject", side_effect=TransactionRepositoryConflictException("")): with self.assertRaises(ResponseException): await self.service.__reject__(InMemoryRequest(None)) @@ -119,17 +118,15 @@ async def test_commit_raises(self): await self.service.__commit__(InMemoryRequest(None)) with patch.object(TransactionRepository, "get", return_value=TransactionEntry()): - with patch( - "minos.aggregate.TransactionEntry.commit", side_effect=TransactionRepositoryConflictException("") - ): + with patch.object(TransactionEntry, "commit", side_effect=TransactionRepositoryConflictException("")): with self.assertRaises(ResponseException): await self.service.__commit__(InMemoryRequest(None)) async def test_reject_blocked(self): uuid = uuid4() with patch.object(TransactionEntry, "reject") as reject_mock: - with patch( - "minos.aggregate.TransactionRepository.select", return_value=FakeAsyncIterator([TransactionEntry(uuid)]) + with patch.object( + TransactionRepository, "select", return_value=FakeAsyncIterator([TransactionEntry(uuid)]) ) as select_mock: response = await self.service.__reject_blocked__(InMemoryRequest(uuid)) diff --git a/packages/core/minos-microservice-transactions/tests/utils.py b/packages/core/minos-microservice-transactions/tests/utils.py index d8ee94c00..9054ed43b 100644 --- a/packages/core/minos-microservice-transactions/tests/utils.py +++ b/packages/core/minos-microservice-transactions/tests/utils.py @@ -8,14 +8,17 @@ from pathlib import ( Path, ) +from typing import Union from minos.common import ( Lock, - LockPool, + LockPool, DatabaseClientPool, PoolFactory, InjectableMixin, ) from minos.common.testing import ( MinosTestCase, ) +from minos.networks import BrokerClientPool +from minos.transactions import InMemoryTransactionRepository BASE_PATH = Path(__file__).parent CONFIG_FILE_PATH = BASE_PATH / "test_config.yml" @@ -25,6 +28,18 @@ class TransactionsTestCase(MinosTestCase, ABC): def get_config_file_path(self): return CONFIG_FILE_PATH + def get_injections(self) -> list[Union[InjectableMixin, type[InjectableMixin], str]]: + pool_factory = PoolFactory.from_config( + self.config, + default_classes={"broker": BrokerClientPool, "lock": FakeLockPool, "database": DatabaseClientPool}, + ) + transaction_repository = InMemoryTransactionRepository(lock_pool=pool_factory.get_pool("lock")) + + return [ + pool_factory, + transaction_repository, + ] + class FakeAsyncIterator: """For testing purposes.""" diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py index 0a9416f42..e75be0303 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py @@ -2,7 +2,6 @@ AiopgEventDatabaseOperationFactory, AiopgSnapshotDatabaseOperationFactory, AiopgSnapshotQueryDatabaseOperationBuilder, - AiopgTransactionDatabaseOperationFactory, ) from .common import ( AiopgLockDatabaseOperationFactory, @@ -14,3 +13,6 @@ AiopgBrokerSubscriberDuplicateValidatorDatabaseOperationFactory, AiopgBrokerSubscriberQueueDatabaseOperationFactory, ) +from .transactions import ( + AiopgTransactionDatabaseOperationFactory, +) diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/__init__.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/__init__.py index 7ab92c103..9441bc05d 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/__init__.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/__init__.py @@ -5,6 +5,3 @@ AiopgSnapshotDatabaseOperationFactory, AiopgSnapshotQueryDatabaseOperationBuilder, ) -from .transactions import ( - AiopgTransactionDatabaseOperationFactory, -) diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/transactions.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/transactions.py similarity index 98% rename from packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/transactions.py rename to packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/transactions.py index 660855dc8..034d0caec 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/transactions.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/transactions.py @@ -15,19 +15,19 @@ UUID, ) -from minos.aggregate import ( - TransactionDatabaseOperationFactory, - TransactionStatus, -) from minos.common import ( ComposedDatabaseOperation, DatabaseOperation, ) +from minos.transactions import ( + TransactionDatabaseOperationFactory, + TransactionStatus, +) -from ...clients import ( +from ..clients import ( AiopgDatabaseClient, ) -from ...operations import ( +from ..operations import ( AiopgDatabaseOperation, ) diff --git a/packages/plugins/minos-database-aiopg/poetry.lock b/packages/plugins/minos-database-aiopg/poetry.lock index 594d758c3..51b87641a 100644 --- a/packages/plugins/minos-database-aiopg/poetry.lock +++ b/packages/plugins/minos-database-aiopg/poetry.lock @@ -212,14 +212,6 @@ requirements_deprecated_finder = ["pipreqs", "pip-api"] colors = ["colorama (>=0.4.3,<0.5.0)"] plugins = ["setuptools"] -[[package]] -name = "lmdb" -version = "1.3.0" -description = "Universal Python binding for the LMDB 'Lightning' Database" -category = "main" -optional = false -python-versions = "*" - [[package]] name = "mccabe" version = "0.6.1" @@ -241,6 +233,7 @@ develop = true cached-property = "^1.5.2" minos-microservice-common = "^0.7.0*" minos-microservice-networks = "^0.7.0*" +minos-microservice-transactions = "^0.0.0*" [package.source] type = "directory" @@ -260,7 +253,6 @@ aiomisc = ">=14.0.3,<15.8.0" cached-property = "^1.5.2" dependency-injector = "^4.32.2" fastavro = "^1.4.0" -lmdb = "^1.2.1" orjson = "^3.5.2" PyYAML = ">=5.4.1,<7.0.0" uvloop = "^0.16.0" @@ -286,6 +278,24 @@ minos-microservice-common = "^0.7.0*" type = "directory" url = "../../core/minos-microservice-networks" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" +minos-microservice-networks = "^0.7.0*" + +[package.source] +type = "directory" +url = "../../core/minos-microservice-transactions" + [[package]] name = "mypy-extensions" version = "0.4.3" @@ -457,7 +467,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "b43594cabd6bbb5636025c9351168e25f8c2e066080128dabe87e8e7cbc1188e" +content-hash = "f321d3408cb81d58e84018c0009cb373d9622926f2d3e611bfdf86c40a944817" [metadata.files] aiomisc = [ @@ -635,35 +645,6 @@ isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] -lmdb = [ - {file = "lmdb-1.3.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:63cb73fe7ce9eb93d992d632c85a0476b4332670d9e6a2802b5062f603b7809f"}, - {file = "lmdb-1.3.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:abbc439cd9fe60ffd6197009087ea885ac150017dc85384093b1d376f83f0ec4"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6260a526e4ad85b1f374a5ba9475bf369fb07e7728ea6ec57226b02c40d1976b"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e568ae0887ae196340947d9800136e90feaed6b86a261ef01f01b2ba65fc8106"}, - {file = "lmdb-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6a816954d212f40fd15007cd81ab7a6bebb77436d949a6a9ae04af57fc127f3"}, - {file = "lmdb-1.3.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fa6439356e591d3249ab0e1778a6f8d8408e993f66dc911914c78208f5310309"}, - {file = "lmdb-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:c6adbd6f7f9048e97f31a069e652eb51020a81e80a0ce92dbb9810d21da2409a"}, - {file = "lmdb-1.3.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:eefb392f6b5cd43aada49258c5a79be11cb2c8cd3fc3e2d9319a1e0b9f906458"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a14aca2651c3af6f0d0a6b9168200eea0c8f2d27c40b01a442f33329a6e8dff"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfa4aa9c67f8aee89b23005e98d1f3f32490b6b905fd1cb604b207cbd5755ab"}, - {file = "lmdb-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7da05d70fcc6561ac6b09e9fb1bf64b7ca294652c64c8a2889273970cee796b9"}, - {file = "lmdb-1.3.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:008243762decf8f6c90430a9bced56290ebbcdb5e877d90e42343bb97033e494"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:17215a42a4b9814c383deabecb160581e4fb75d00198eef0e3cea54f230ffbea"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65334eafa5d430b18d81ebd5362559a41483c362e1931f6e1b15bab2ecb7d75d"}, - {file = "lmdb-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:18c69fabdaf04efaf246587739cc1062b3e57c6ef0743f5c418df89e5e7e7b9b"}, - {file = "lmdb-1.3.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:41318717ab5d15ad2d6d263d34fbf614a045210f64b25e59ce734bb2105e421f"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:df2724bad7820114a205472994091097d0fa65a3e5fff5a8e688d123fb8c6326"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddd590e1c7fcb395931aa3782fb89b9db4550ab2d81d006ecd239e0d462bc41"}, - {file = "lmdb-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:4172fba19417d7b29409beca7d73c067b54e5d8ab1fb9b51d7b4c1445d20a167"}, - {file = "lmdb-1.3.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2df38115dd9428a54d59ae7c712a4c7cce0d6b1d66056de4b1a8c38718066106"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9103aa4908f0bca43c5911ca067d4e3d01f682dff0c0381a1239bd2bd757984"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:394df860c3f93cfd92b6f4caba785f38208cc9614c18b3803f83a2cc1695042f"}, - {file = "lmdb-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:62ab28e3593bdc318ea2f2fa1574e5fca3b6d1f264686d773ba54a637d4f563b"}, - {file = "lmdb-1.3.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:e6a704b3baced9182836c7f77b769f23856f3a8f62d0282b1bc1feaf81a86712"}, - {file = "lmdb-1.3.0-pp27-pypy_73-win_amd64.whl", hash = "sha256:08f4b5129f4683802569b02581142e415c8dcc0ff07605983ec1b07804cecbad"}, - {file = "lmdb-1.3.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:f291e3f561f58dddf63a92a5a6a4b8af3a0920b6705d35e2f80e52e86ee238a2"}, - {file = "lmdb-1.3.0.tar.gz", hash = "sha256:60a11efc21aaf009d06518996360eed346f6000bfc9de05114374230879f992e"}, -] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, @@ -671,6 +652,7 @@ mccabe = [ minos-microservice-aggregate = [] minos-microservice-common = [] minos-microservice-networks = [] +minos-microservice-transactions = [] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, diff --git a/packages/plugins/minos-database-aiopg/pyproject.toml b/packages/plugins/minos-database-aiopg/pyproject.toml index 0bb1ef2ae..238aec41d 100644 --- a/packages/plugins/minos-database-aiopg/pyproject.toml +++ b/packages/plugins/minos-database-aiopg/pyproject.toml @@ -34,6 +34,7 @@ python = "^3.9" minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true } minos-microservice-networks = { version ="^0.7.0*", allow-prereleases = true } minos-microservice-aggregate = { version ="^0.7.0*", allow-prereleases = true } +minos-microservice-transactions = { version ="^0.0.0*", allow-prereleases = true } aiopg = "^1.2.1" psycopg2-binary = "^2.9.3" @@ -41,6 +42,7 @@ psycopg2-binary = "^2.9.3" minos-microservice-common = { path = "../../core/minos-microservice-common", develop = true } minos-microservice-networks = { path = "../../core/minos-microservice-networks", develop = true } minos-microservice-aggregate = { path = "../../core/minos-microservice-aggregate", develop = true } +minos-microservice-transactions = { path = "../../core/minos-microservice-transactions", develop = true } black = "^22.3" isort = "^5.8.0" pytest = "^7.0.1" diff --git a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/__init__.py b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/__init__.py b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_transactions/__init__.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_transactions/test_repositories/__init__.py rename to packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_transactions/__init__.py diff --git a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/test_factory.py b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_transactions/test_factory.py similarity index 98% rename from packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/test_factory.py rename to packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_transactions/test_factory.py index 15d7e0c17..b860fce90 100644 --- a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/test_factory.py +++ b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_transactions/test_factory.py @@ -3,10 +3,6 @@ uuid4, ) -from minos.aggregate import ( - TransactionDatabaseOperationFactory, - TransactionStatus, -) from minos.common import ( ComposedDatabaseOperation, current_datetime, @@ -15,6 +11,10 @@ AiopgDatabaseOperation, AiopgTransactionDatabaseOperationFactory, ) +from minos.transactions import ( + TransactionDatabaseOperationFactory, + TransactionStatus, +) class TestAiopgTransactionDatabaseOperationFactory(unittest.TestCase): diff --git a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/test_repository.py b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_transactions/test_repository.py similarity index 95% rename from packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/test_repository.py rename to packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_transactions/test_repository.py index c86eab02a..6723dd3b1 100644 --- a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_transactions/test_repository.py +++ b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_transactions/test_repository.py @@ -1,12 +1,5 @@ import unittest -from minos.aggregate import ( - DatabaseTransactionRepository, - TransactionRepository, -) -from minos.aggregate.testing import ( - TransactionRepositoryTestCase, -) from minos.common import ( DatabaseClientPool, ) @@ -14,6 +7,13 @@ AiopgDatabaseClient, AiopgDatabaseOperation, ) +from minos.transactions import ( + DatabaseTransactionRepository, + TransactionRepository, +) +from minos.transactions.testing import ( + TransactionRepositoryTestCase, +) from tests.utils import ( AiopgTestCase, ) diff --git a/packages/plugins/minos-database-aiopg/tests/utils.py b/packages/plugins/minos-database-aiopg/tests/utils.py index f3670c839..b6d0ce527 100644 --- a/packages/plugins/minos-database-aiopg/tests/utils.py +++ b/packages/plugins/minos-database-aiopg/tests/utils.py @@ -5,7 +5,6 @@ from minos.aggregate import ( InMemoryEventRepository, InMemorySnapshotRepository, - InMemoryTransactionRepository, ) from minos.common import ( DatabaseClientPool, @@ -21,6 +20,9 @@ InMemoryBrokerPublisher, InMemoryBrokerSubscriberBuilder, ) +from minos.transactions import ( + InMemoryTransactionRepository, +) BASE_PATH = Path(__file__).parent CONFIG_FILE_PATH = BASE_PATH / "test_config.yml" diff --git a/packages/plugins/minos-database-lmdb/poetry.lock b/packages/plugins/minos-database-lmdb/poetry.lock index 0c2aef563..86e51a87f 100644 --- a/packages/plugins/minos-database-lmdb/poetry.lock +++ b/packages/plugins/minos-database-lmdb/poetry.lock @@ -205,24 +205,6 @@ category = "dev" optional = false python-versions = "*" -[[package]] -name = "minos-microservice-aggregate" -version = "0.7.0.dev1" -description = "The Aggregate pattern of the Minos Framework" -category = "main" -optional = false -python-versions = "^3.9" -develop = true - -[package.dependencies] -cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" -minos-microservice-networks = "^0.7.0*" - -[package.source] -type = "directory" -url = "../../core/minos-microservice-aggregate" - [[package]] name = "minos-microservice-common" version = "0.7.0.dev1" @@ -237,7 +219,6 @@ aiomisc = ">=14.0.3,<15.8.0" cached-property = "^1.5.2" dependency-injector = "^4.32.2" fastavro = "^1.4.0" -lmdb = "^1.2.1" orjson = "^3.5.2" PyYAML = ">=5.4.1,<7.0.0" uvloop = "^0.16.0" @@ -274,14 +255,32 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-aggregate = "^0.7.0*" minos-microservice-common = "^0.7.0*" minos-microservice-networks = "^0.7.0*" +minos-microservice-transactions = "^0.0.0*" [package.source] type = "directory" url = "../../core/minos-microservice-saga" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" +minos-microservice-networks = "^0.7.0*" + +[package.source] +type = "directory" +url = "../../core/minos-microservice-transactions" + [[package]] name = "mypy-extensions" version = "0.4.3" @@ -445,7 +444,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "13984b2345050619e558ec2b7f5d7042811ef69ab784f48b842086de883d0b6a" +content-hash = "c05e39549472bae1f528614fa2583e94e785bde2e805fa57a18d08ec88b53391" [metadata.files] aiomisc = [ @@ -648,10 +647,10 @@ mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] -minos-microservice-aggregate = [] minos-microservice-common = [] minos-microservice-networks = [] minos-microservice-saga = [] +minos-microservice-transactions = [] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, diff --git a/packages/plugins/minos-database-lmdb/pyproject.toml b/packages/plugins/minos-database-lmdb/pyproject.toml index d2e063afc..2c77c65c3 100644 --- a/packages/plugins/minos-database-lmdb/pyproject.toml +++ b/packages/plugins/minos-database-lmdb/pyproject.toml @@ -39,7 +39,7 @@ lmdb = "^1.2.1" minos-microservice-common = { path = "../../core/minos-microservice-common", develop = true } minos-microservice-saga = { path = "../../core/minos-microservice-saga", develop = true } minos-microservice-networks = { path = "../../core/minos-microservice-networks", develop = true } -minos-microservice-aggregate = { path = "../../core/minos-microservice-aggregate", develop = true } +minos-microservice-transactions = { path = "../../core/minos-microservice-transactions", develop = true } black = "^22.3" isort = "^5.8.0" pytest = "^7.0.1" diff --git a/packages/plugins/minos-database-lmdb/tests/utils.py b/packages/plugins/minos-database-lmdb/tests/utils.py index b2b080c94..111a3c47a 100644 --- a/packages/plugins/minos-database-lmdb/tests/utils.py +++ b/packages/plugins/minos-database-lmdb/tests/utils.py @@ -2,11 +2,6 @@ Path, ) -from minos.aggregate import ( - InMemoryEventRepository, - InMemorySnapshotRepository, - InMemoryTransactionRepository, -) from minos.common import ( DatabaseClientPool, Lock, @@ -21,6 +16,9 @@ InMemoryBrokerPublisher, InMemoryBrokerSubscriberBuilder, ) +from minos.transactions import ( + InMemoryTransactionRepository, +) BASE_PATH = Path(__file__).parent CONFIG_FILE_PATH = BASE_PATH / "test_config.yml" @@ -44,22 +42,11 @@ def get_injections(self): transaction_repository = InMemoryTransactionRepository( lock_pool=pool_factory.get_pool("lock"), ) - event_repository = InMemoryEventRepository( - broker_publisher=broker_publisher, - transaction_repository=transaction_repository, - lock_pool=pool_factory.get_pool("lock"), - ) - snapshot_repository = InMemorySnapshotRepository( - event_repository=event_repository, - transaction_repository=transaction_repository, - ) return [ pool_factory, broker_publisher, broker_subscriber_builder, transaction_repository, - event_repository, - snapshot_repository, ] From dd6bc583a546eee6ad41a345b1278a4bf0d7d52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 21 Apr 2022 10:36:41 +0200 Subject: [PATCH 13/75] ISSUE #65 * Integrate `minos-microservice-transactions` into deployment workflows. --- ...inos-microservice-transactions-publish.yml | 33 +++++++++++++ .../minos-microservice-transactions-tests.yml | 49 +++++++++++++++++++ .pre-commit-config.yaml | 7 +++ .../tests/test_transactions/test_entries.py | 10 ++-- .../tests/test_transactions/test_mixins.py | 3 +- .../test_repositories/test_abc.py | 2 +- .../test_repositories/test_database.py | 2 +- .../tests/test_transactions/test_services.py | 2 +- .../tests/utils.py | 17 +++++-- pyproject.toml | 1 + 10 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/minos-microservice-transactions-publish.yml create mode 100644 .github/workflows/minos-microservice-transactions-tests.yml diff --git a/.github/workflows/minos-microservice-transactions-publish.yml b/.github/workflows/minos-microservice-transactions-publish.yml new file mode 100644 index 000000000..27bd60fb0 --- /dev/null +++ b/.github/workflows/minos-microservice-transactions-publish.yml @@ -0,0 +1,33 @@ +name: "Publish: minos-microservice-transactions" + +on: + push: + branches: + - '*.*.x' + paths: + - 'packages/core/minos-microservice-transactions/**' + +jobs: + deploy: + runs-on: ubuntu-latest + container: python:3.9-buster + defaults: + run: + working-directory: packages/core/minos-microservice-transactions + + steps: + + - name: Check out repository code + uses: actions/checkout@v2 + + - name: Install Poetry + uses: snok/install-poetry@v1 + + - name: Install dependencies + run: make install + + - name: Publish package + run: make release + env: + POETRY_HTTP_BASIC_PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }} + POETRY_HTTP_BASIC_PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} diff --git a/.github/workflows/minos-microservice-transactions-tests.yml b/.github/workflows/minos-microservice-transactions-tests.yml new file mode 100644 index 000000000..8b9751bd9 --- /dev/null +++ b/.github/workflows/minos-microservice-transactions-tests.yml @@ -0,0 +1,49 @@ +name: "Test: minos-microservice-transactions" + +on: + push: + branches: + - main + - '*.*.x' + pull_request: + paths: + - 'packages/core/minos-microservice-transactions/**' + - 'packages/core/minos-microservice-networks/**' + - 'packages/core/minos-microservice-common/**' + +jobs: + build: + runs-on: ubuntu-latest + container: python:3.9-buster + defaults: + run: + working-directory: packages/core/minos-microservice-transactions + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - name: Install Poetry + uses: snok/install-poetry@v1 + + - name: Install dependencies + run: make install + + - name: Lint package + run: make lint + + - name: Test package with coverage + run: make coverage + + - name: Publish coverage + uses: codecov/codecov-action@v2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./packages/core/minos-microservice-transactions/coverage.xml + fail_ci_if_error: true + + - name: Generate documentation + run: make docs + + - name: Generate build + run: make dist diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 46f97e088..497561cf1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,6 +37,13 @@ repos: files: ^packages/core/minos-microservice-saga/ language: system + - id: minos-microservice-transactions-check + pass_filenames: false + entry: make --directory=packages/core/minos-microservice-transactions check + name: Check minos-microservice-transactions + files: ^packages/core/minos-microservice-transactions/ + language: system + - id: minos-broker-kafka-check pass_filenames: false entry: make --directory=packages/plugins/minos-broker-kafka check diff --git a/packages/core/minos-microservice-transactions/tests/test_transactions/test_entries.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_entries.py index 3fb85c318..da64dcca8 100644 --- a/packages/core/minos-microservice-transactions/tests/test_transactions/test_entries.py +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_entries.py @@ -2,7 +2,9 @@ from datetime import ( datetime, ) -from typing import Optional +from typing import ( + Optional, +) from unittest.mock import ( AsyncMock, MagicMock, @@ -15,7 +17,8 @@ ) from minos.common import ( - NULL_UUID, Lock, + NULL_UUID, + Lock, ) from minos.transactions import ( TRANSACTION_CONTEXT_VAR, @@ -25,8 +28,9 @@ TransactionStatus, ) from tests.utils import ( + FakeAsyncIterator, + FakeLock, TransactionsTestCase, - FakeAsyncIterator, FakeLock, ) diff --git a/packages/core/minos-microservice-transactions/tests/test_transactions/test_mixins.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_mixins.py index 24c8710db..ee5d646d4 100644 --- a/packages/core/minos-microservice-transactions/tests/test_transactions/test_mixins.py +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_mixins.py @@ -4,7 +4,8 @@ ) from minos.common import ( - SetupMixin, NotProvidedException, + NotProvidedException, + SetupMixin, ) from minos.transactions import ( TransactionalMixin, diff --git a/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_abc.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_abc.py index 215d65f39..236a33d92 100644 --- a/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_abc.py @@ -26,9 +26,9 @@ TransactionStatus, ) from tests.utils import ( - TransactionsTestCase, FakeAsyncIterator, FakeLock, + TransactionsTestCase, ) diff --git a/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_database.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_database.py index 35fac3d7d..e4e4a2e2e 100644 --- a/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_database.py +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_repositories/test_database.py @@ -17,8 +17,8 @@ TransactionRepositoryTestCase, ) from tests.utils import ( - TransactionsTestCase, FakeAsyncIterator, + TransactionsTestCase, ) diff --git a/packages/core/minos-microservice-transactions/tests/test_transactions/test_services.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_services.py index d86b610f1..3c1e67849 100644 --- a/packages/core/minos-microservice-transactions/tests/test_transactions/test_services.py +++ b/packages/core/minos-microservice-transactions/tests/test_transactions/test_services.py @@ -31,8 +31,8 @@ TransactionStatus, ) from tests.utils import ( - TransactionsTestCase, FakeAsyncIterator, + TransactionsTestCase, ) diff --git a/packages/core/minos-microservice-transactions/tests/utils.py b/packages/core/minos-microservice-transactions/tests/utils.py index 9054ed43b..0c0a888e6 100644 --- a/packages/core/minos-microservice-transactions/tests/utils.py +++ b/packages/core/minos-microservice-transactions/tests/utils.py @@ -8,17 +8,26 @@ from pathlib import ( Path, ) -from typing import Union +from typing import ( + Union, +) from minos.common import ( + DatabaseClientPool, + InjectableMixin, Lock, - LockPool, DatabaseClientPool, PoolFactory, InjectableMixin, + LockPool, + PoolFactory, ) from minos.common.testing import ( MinosTestCase, ) -from minos.networks import BrokerClientPool -from minos.transactions import InMemoryTransactionRepository +from minos.networks import ( + BrokerClientPool, +) +from minos.transactions import ( + InMemoryTransactionRepository, +) BASE_PATH = Path(__file__).parent CONFIG_FILE_PATH = BASE_PATH / "test_config.yml" diff --git a/pyproject.toml b/pyproject.toml index a4437c649..4eaca34f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ license = "MIT" python = "^3.9" minos-microservice-common = { path = "packages/core/minos-microservice-common", develop = true } minos-microservice-networks = { path = "packages/core/minos-microservice-networks", develop = true } +minos-microservice-transactions = { path = "packages/core/minos-microservice-transactions", develop = true } minos-microservice-aggregate = { path = "packages/core/minos-microservice-aggregate", develop = true } minos-microservice-saga = { path = "packages/core/minos-microservice-saga", develop = true } minos-microservice-cqrs = { path = "packages/core/minos-microservice-cqrs", develop = true } From 135c8042438a7ca67de49b1c3fe143b47cfc2f4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 21 Apr 2022 10:43:10 +0200 Subject: [PATCH 14/75] ISSUE #65 * Fix bug related with dependency specification. --- .../core/minos-microservice-cqrs/poetry.lock | 247 +++++------------- .../minos-microservice-cqrs/pyproject.toml | 1 + 2 files changed, 65 insertions(+), 183 deletions(-) diff --git a/packages/core/minos-microservice-cqrs/poetry.lock b/packages/core/minos-microservice-cqrs/poetry.lock index bc0c15e2b..1e199ff54 100644 --- a/packages/core/minos-microservice-cqrs/poetry.lock +++ b/packages/core/minos-microservice-cqrs/poetry.lock @@ -19,29 +19,6 @@ develop = ["aiocontextvars (==0.2.2)", "aiohttp-asgi", "aiohttp (<4)", "async-ti raven = ["raven-aiohttp"] uvloop = ["uvloop (>=0.14,<1)"] -[[package]] -name = "aiopg" -version = "1.3.3" -description = "Postgres integration with asyncio." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -async-timeout = ">=3.0,<5.0" -psycopg2-binary = ">=2.8.4" - -[package.extras] -sa = ["sqlalchemy[postgresql_psycopg2binary] (>=1.3,<1.5)"] - -[[package]] -name = "async-timeout" -version = "4.0.2" -description = "Timeout context manager for asyncio programs" -category = "main" -optional = false -python-versions = ">=3.6" - [[package]] name = "atomicwrites" version = "1.4.0" @@ -212,14 +189,6 @@ requirements_deprecated_finder = ["pipreqs", "pip-api"] colors = ["colorama (>=0.4.3,<0.5.0)"] plugins = ["setuptools"] -[[package]] -name = "lmdb" -version = "1.3.0" -description = "Universal Python binding for the LMDB 'Lightning' Database" -category = "main" -optional = false -python-versions = "*" - [[package]] name = "mccabe" version = "0.6.1" @@ -241,7 +210,7 @@ develop = true cached-property = "^1.5.2" minos-microservice-common = "^0.7.0*" minos-microservice-networks = "^0.7.0*" -psycopg2-binary = "^2.9.3" +minos-microservice-transactions = "^0.0.0*" [package.source] type = "directory" @@ -258,11 +227,9 @@ develop = true [package.dependencies] aiomisc = ">=14.0.3,<15.8.0" -aiopg = "^1.2.1" cached-property = "^1.5.2" dependency-injector = "^4.32.2" fastavro = "^1.4.0" -lmdb = "^1.2.1" orjson = "^3.5.2" PyYAML = ">=5.4.1,<7.0.0" uvloop = "^0.16.0" @@ -281,15 +248,31 @@ python-versions = "^3.9" develop = true [package.dependencies] -aiopg = "^1.2.1" crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" -psycopg2-binary = "^2.9.3" [package.source] type = "directory" url = "../minos-microservice-networks" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" +minos-microservice-networks = "^0.7.0*" + +[package.source] +type = "directory" +url = "../minos-microservice-transactions" + [[package]] name = "mypy-extensions" version = "0.4.3" @@ -300,7 +283,7 @@ python-versions = "*" [[package]] name = "orjson" -version = "3.6.7" +version = "3.6.8" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" category = "main" optional = false @@ -327,15 +310,15 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] name = "platformdirs" -version = "2.5.1" +version = "2.5.2" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] +test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] [[package]] name = "pluggy" @@ -349,14 +332,6 @@ python-versions = ">=3.6" dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "psycopg2-binary" -version = "2.9.3" -description = "psycopg2 - Python-PostgreSQL Database Adapter" -category = "main" -optional = false -python-versions = ">=3.6" - [[package]] name = "py" version = "1.11.0" @@ -439,11 +414,11 @@ python-versions = ">=3.7" [[package]] name = "typing-extensions" -version = "4.1.1" -description = "Backported and Experimental Type Hints for Python 3.6+" +version = "4.2.0" +description = "Backported and Experimental Type Hints for Python 3.7+" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "uvloop" @@ -461,21 +436,13 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "4aebc32cd00338ca4f9a425c9f75b2c796abb3b46bd8a7b895ec0b9e753866b5" +content-hash = "5ca90aaa0ec893363da7235a0badda9b2f0431ceb3a654f2219d3b7e84731a18" [metadata.files] aiomisc = [ {file = "aiomisc-15.7.3-py3-none-any.whl", hash = "sha256:0403e83268e98d0f2a125a70d13303fe1a2358e36db3daf02df032c7fa4f1525"}, {file = "aiomisc-15.7.3.tar.gz", hash = "sha256:ba250a34bd4609ced36111cb50580f57c3d52f3955f953a53ecb2986988baedc"}, ] -aiopg = [ - {file = "aiopg-1.3.3-py3-none-any.whl", hash = "sha256:2842dd8741460eeef940032dcb577bfba4d4115205dd82a73ce13b3271f5bf0a"}, - {file = "aiopg-1.3.3.tar.gz", hash = "sha256:547c6ba4ea0d73c2a11a2f44387d7133cc01d3c6f3b8ed976c0ac1eff4f595d7"}, -] -async-timeout = [ - {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, - {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, -] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, @@ -639,35 +606,6 @@ isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] -lmdb = [ - {file = "lmdb-1.3.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:63cb73fe7ce9eb93d992d632c85a0476b4332670d9e6a2802b5062f603b7809f"}, - {file = "lmdb-1.3.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:abbc439cd9fe60ffd6197009087ea885ac150017dc85384093b1d376f83f0ec4"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6260a526e4ad85b1f374a5ba9475bf369fb07e7728ea6ec57226b02c40d1976b"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e568ae0887ae196340947d9800136e90feaed6b86a261ef01f01b2ba65fc8106"}, - {file = "lmdb-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6a816954d212f40fd15007cd81ab7a6bebb77436d949a6a9ae04af57fc127f3"}, - {file = "lmdb-1.3.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fa6439356e591d3249ab0e1778a6f8d8408e993f66dc911914c78208f5310309"}, - {file = "lmdb-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:c6adbd6f7f9048e97f31a069e652eb51020a81e80a0ce92dbb9810d21da2409a"}, - {file = "lmdb-1.3.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:eefb392f6b5cd43aada49258c5a79be11cb2c8cd3fc3e2d9319a1e0b9f906458"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a14aca2651c3af6f0d0a6b9168200eea0c8f2d27c40b01a442f33329a6e8dff"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfa4aa9c67f8aee89b23005e98d1f3f32490b6b905fd1cb604b207cbd5755ab"}, - {file = "lmdb-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7da05d70fcc6561ac6b09e9fb1bf64b7ca294652c64c8a2889273970cee796b9"}, - {file = "lmdb-1.3.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:008243762decf8f6c90430a9bced56290ebbcdb5e877d90e42343bb97033e494"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:17215a42a4b9814c383deabecb160581e4fb75d00198eef0e3cea54f230ffbea"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65334eafa5d430b18d81ebd5362559a41483c362e1931f6e1b15bab2ecb7d75d"}, - {file = "lmdb-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:18c69fabdaf04efaf246587739cc1062b3e57c6ef0743f5c418df89e5e7e7b9b"}, - {file = "lmdb-1.3.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:41318717ab5d15ad2d6d263d34fbf614a045210f64b25e59ce734bb2105e421f"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:df2724bad7820114a205472994091097d0fa65a3e5fff5a8e688d123fb8c6326"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddd590e1c7fcb395931aa3782fb89b9db4550ab2d81d006ecd239e0d462bc41"}, - {file = "lmdb-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:4172fba19417d7b29409beca7d73c067b54e5d8ab1fb9b51d7b4c1445d20a167"}, - {file = "lmdb-1.3.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2df38115dd9428a54d59ae7c712a4c7cce0d6b1d66056de4b1a8c38718066106"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9103aa4908f0bca43c5911ca067d4e3d01f682dff0c0381a1239bd2bd757984"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:394df860c3f93cfd92b6f4caba785f38208cc9614c18b3803f83a2cc1695042f"}, - {file = "lmdb-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:62ab28e3593bdc318ea2f2fa1574e5fca3b6d1f264686d773ba54a637d4f563b"}, - {file = "lmdb-1.3.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:e6a704b3baced9182836c7f77b769f23856f3a8f62d0282b1bc1feaf81a86712"}, - {file = "lmdb-1.3.0-pp27-pypy_73-win_amd64.whl", hash = "sha256:08f4b5129f4683802569b02581142e415c8dcc0ff07605983ec1b07804cecbad"}, - {file = "lmdb-1.3.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:f291e3f561f58dddf63a92a5a6a4b8af3a0920b6705d35e2f80e52e86ee238a2"}, - {file = "lmdb-1.3.0.tar.gz", hash = "sha256:60a11efc21aaf009d06518996360eed346f6000bfc9de05114374230879f992e"}, -] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, @@ -675,43 +613,44 @@ mccabe = [ minos-microservice-aggregate = [] minos-microservice-common = [] minos-microservice-networks = [] +minos-microservice-transactions = [] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] orjson = [ - {file = "orjson-3.6.7-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:93188a9d6eb566419ad48befa202dfe7cd7a161756444b99c4ec77faea9352a4"}, - {file = "orjson-3.6.7-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:82515226ecb77689a029061552b5df1802b75d861780c401e96ca6bc8495f775"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3af57ffab7848aaec6ba6b9e9b41331250b57bf696f9d502bacdc71a0ebab0ba"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:a7297504d1142e7efa236ffc53f056d73934a993a08646dbcee89fc4308a8fcf"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:5a50cde0dbbde255ce751fd1bca39d00ecd878ba0903c0480961b31984f2fab7"}, - {file = "orjson-3.6.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d21f9a2d1c30e58070f93988db4cad154b9009fafbde238b52c1c760e3607fbe"}, - {file = "orjson-3.6.7-cp310-none-win_amd64.whl", hash = "sha256:e152464c4606b49398afd911777decebcf9749cc8810c5b4199039e1afb0991e"}, - {file = "orjson-3.6.7-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:0a65f3c403f38b0117c6dd8e76e85a7bd51fcd92f06c5598dfeddbc44697d3e5"}, - {file = "orjson-3.6.7-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:6c47cfca18e41f7f37b08ff3e7abf5ada2d0f27b5ade934f05be5fc5bb956e9d"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:63185af814c243fad7a72441e5f98120c9ecddf2675befa486d669fb65539e9b"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2da6fde42182b80b40df2e6ab855c55090ebfa3fcc21c182b7ad1762b61d55c"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:48c5831ec388b4e2682d4ff56d6bfa4a2ef76c963f5e75f4ff4785f9cf338a80"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:913fac5d594ccabf5e8fbac15b9b3bb9c576d537d49eeec9f664e7a64dde4c4b"}, - {file = "orjson-3.6.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:58f244775f20476e5851e7546df109f75160a5178d44257d437ba6d7e562bfe8"}, - {file = "orjson-3.6.7-cp37-none-win_amd64.whl", hash = "sha256:2d5f45c6b85e5f14646df2d32ecd7ff20fcccc71c0ea1155f4d3df8c5299bbb7"}, - {file = "orjson-3.6.7-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:612d242493afeeb2068bc72ff2544aa3b1e627578fcf92edee9daebb5893ffea"}, - {file = "orjson-3.6.7-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:539cdc5067db38db27985e257772d073cd2eb9462d0a41bde96da4e4e60bd99b"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d103b721bbc4f5703f62b3882e638c0b65fcdd48622531c7ffd45047ef8e87c"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb10a20f80e95102dd35dfbc3a22531661b44a09b55236b012a446955846b023"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:bb68d0da349cf8a68971a48ad179434f75256159fe8b0715275d9b49fa23b7a3"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:4a2c7d0a236aaeab7f69c17b7ab4c078874e817da1bfbb9827cb8c73058b3050"}, - {file = "orjson-3.6.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3be045ca3b96119f592904cf34b962969ce97bd7843cbfca084009f6c8d2f268"}, - {file = "orjson-3.6.7-cp38-none-win_amd64.whl", hash = "sha256:bd765c06c359d8a814b90f948538f957fa8a1f55ad1aaffcdc5771996aaea061"}, - {file = "orjson-3.6.7-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7dd9e1e46c0776eee9e0649e3ae9584ea368d96851bcaeba18e217fa5d755283"}, - {file = "orjson-3.6.7-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c4b4f20a1e3df7e7c83717aff0ef4ab69e42ce2fb1f5234682f618153c458406"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7107a5673fd0b05adbb58bf71c1578fc84d662d29c096eb6d998982c8635c221"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a08b6940dd9a98ccf09785890112a0f81eadb4f35b51b9a80736d1725437e22c"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:f5d1648e5a9d1070f3628a69a7c6c17634dbb0caf22f2085eca6910f7427bf1f"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:e6201494e8dff2ce7fd21da4e3f6dfca1a3fed38f9dcefc972f552f6596a7621"}, - {file = "orjson-3.6.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:70d0386abe02879ebaead2f9632dd2acb71000b4721fd8c1a2fb8c031a38d4d5"}, - {file = "orjson-3.6.7-cp39-none-win_amd64.whl", hash = "sha256:d9a3288861bfd26f3511fb4081561ca768674612bac59513cb9081bb61fcc87f"}, - {file = "orjson-3.6.7.tar.gz", hash = "sha256:a4bb62b11289b7620eead2f25695212e9ac77fcfba76f050fa8a540fb5c32401"}, + {file = "orjson-3.6.8-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:3a287a650458de2211db03681b71c3e5cb2212b62f17a39df8ad99fc54855d0f"}, + {file = "orjson-3.6.8-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5204e25c12cea58e524fc82f7c27ed0586f592f777b33075a92ab7b3eb3687c2"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77e8386393add64f959c044e0fb682364fd0e611a6f477aa13f0e6a733bd6a28"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:279f2d2af393fdf8601020744cb206b91b54ad60fb8401e0761819c7bda1f4e4"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:c31c9f389be7906f978ed4192eb58a4b74a37ad60556a0b88ddc47c576697770"}, + {file = "orjson-3.6.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0db5c5a0c5b89f092d52f6e5a3701660a9d6ffa9e2968b3ce17c2bc4f5eb0414"}, + {file = "orjson-3.6.8-cp310-none-win_amd64.whl", hash = "sha256:eb22485847b9a0c4bbedc668df860126ac931edbed1d456cf41a59f3cb961ed8"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:1a5fe569310bc819279bd4d5f2c349910b104ed3207936246dd5d5e0b085e74a"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:ccb356a47ab1067cd3549847e9db1d279a63fe0482d315b3ffd6e7abef35ef77"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab29c069c222248ce302a25855b4e1664f9436e8ae5a131fb0859daf31676d2b"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d2b5e4cba9e774ac011071d9d27760f97f4b8cd46003e971d122e712f971345"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:c311ec504414d22834d5b972a209619925b48263856a11a14d90230f9682d49c"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:a3dfec7950b90fb8d143743503ee53fa06b32e6068bdea792fc866284da3d71d"}, + {file = "orjson-3.6.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b890dbbada2cbb26eb29bd43a848426f007f094bb0758df10dfe7a438e1cb4b4"}, + {file = "orjson-3.6.8-cp37-none-win_amd64.whl", hash = "sha256:9143ae2c52771525be9ad11a7a8cc8e7fd75391b107e7e644a9e0050496f6b4f"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:33a82199fd42f6436f833e210ae5129c922a5c355629356ca7a8e82964da7285"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:90159ea8b9a5a2a98fa33dc7b421cfac4d2ae91ba5e1058f5909e7f059f6b467"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:656fbe15d9ef0733e740d9def78f4fdb4153102f4836ee774a05123499005931"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7be3be6153843e0f01351b1313a5ad4723595427680dac2dfff22a37e652ce02"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:dd24f66b6697ee7424f7da575ec6cbffc8ede441114d53470949cda4d97c6e56"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:b07c780f7345ecf5901356dc21dee0669defc489c38ce7b9ab0f5e008cc0385c"}, + {file = "orjson-3.6.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ea32015a5d8a4ce00d348a0de5dc7040e0ad58f970a8fcbb5713a1eac129e493"}, + {file = "orjson-3.6.8-cp38-none-win_amd64.whl", hash = "sha256:c5a3e382194c838988ec128a26b08aa92044e5e055491cc4056142af0c1c54d7"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:83a8424e857ae1bf53530e88b4eb2f16ca2b489073b924e655f1575cacd7f52a"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:81e1a6a2d67f15007dadacbf9ba5d3d79237e5e33786c028557fe5a2b72f1c9a"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:137b539881c77866eba86ff6a11df910daf2eb9ab8f1acae62f879e83d7c38af"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cbd358f3b3ad539a27e36900e8e7d172d0e1b72ad9dd7d69544dcbc0f067ee7"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:6ab94701542d40b90903ecfc339333f458884979a01cb9268bc662cc67a5f6d8"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:32b6f26593a9eb606b40775826beb0dac152e3d224ea393688fced036045a821"}, + {file = "orjson-3.6.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:afd9e329ebd3418cac3cd747769b1d52daa25fa672bbf414ab59f0e0881b32b9"}, + {file = "orjson-3.6.8-cp39-none-win_amd64.whl", hash = "sha256:0c89b419914d3d1f65a1b0883f377abe42a6e44f6624ba1c63e8846cbfc2fa60"}, + {file = "orjson-3.6.8.tar.gz", hash = "sha256:e19d23741c5de13689bb316abfccea15a19c264e3ec8eb332a5319a583595ace"}, ] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, @@ -722,71 +661,13 @@ pathspec = [ {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, ] platformdirs = [ - {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, - {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] -psycopg2-binary = [ - {file = "psycopg2-binary-2.9.3.tar.gz", hash = "sha256:761df5313dc15da1502b21453642d7599d26be88bff659382f8f9747c7ebea4e"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:539b28661b71da7c0e428692438efbcd048ca21ea81af618d845e06ebfd29478"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e82d38390a03da28c7985b394ec3f56873174e2c88130e6966cb1c946508e65"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57804fc02ca3ce0dbfbef35c4b3a4a774da66d66ea20f4bda601294ad2ea6092"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:083a55275f09a62b8ca4902dd11f4b33075b743cf0d360419e2051a8a5d5ff76"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:0a29729145aaaf1ad8bafe663131890e2111f13416b60e460dae0a96af5905c9"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a79d622f5206d695d7824cbf609a4f5b88ea6d6dab5f7c147fc6d333a8787e4"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:090f3348c0ab2cceb6dfbe6bf721ef61262ddf518cd6cc6ecc7d334996d64efa"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a9e1f75f96ea388fbcef36c70640c4efbe4650658f3d6a2967b4cc70e907352e"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c3ae8e75eb7160851e59adc77b3a19a976e50622e44fd4fd47b8b18208189d42"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-win32.whl", hash = "sha256:7b1e9b80afca7b7a386ef087db614faebbf8839b7f4db5eb107d0f1a53225029"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:8b344adbb9a862de0c635f4f0425b7958bf5a4b927c8594e6e8d261775796d53"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:e847774f8ffd5b398a75bc1c18fbb56564cda3d629fe68fd81971fece2d3c67e"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68641a34023d306be959101b345732360fc2ea4938982309b786f7be1b43a4a1"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3303f8807f342641851578ee7ed1f3efc9802d00a6f83c101d21c608cb864460"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:e3699852e22aa68c10de06524a3721ade969abf382da95884e6a10ff798f9281"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:526ea0378246d9b080148f2d6681229f4b5964543c170dd10bf4faaab6e0d27f"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:b1c8068513f5b158cf7e29c43a77eb34b407db29aca749d3eb9293ee0d3103ca"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:15803fa813ea05bef089fa78835118b5434204f3a17cb9f1e5dbfd0b9deea5af"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:152f09f57417b831418304c7f30d727dc83a12761627bb826951692cc6491e57"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:404224e5fef3b193f892abdbf8961ce20e0b6642886cfe1fe1923f41aaa75c9d"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-win32.whl", hash = "sha256:1f6b813106a3abdf7b03640d36e24669234120c72e91d5cbaeb87c5f7c36c65b"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:2d872e3c9d5d075a2e104540965a1cf898b52274a5923936e5bfddb58c59c7c2"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:10bb90fb4d523a2aa67773d4ff2b833ec00857f5912bafcfd5f5414e45280fb1"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:874a52ecab70af13e899f7847b3e074eeb16ebac5615665db33bce8a1009cf33"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a29b3ca4ec9defec6d42bf5feb36bb5817ba3c0230dd83b4edf4bf02684cd0ae"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:12b11322ea00ad8db8c46f18b7dfc47ae215e4df55b46c67a94b4effbaec7094"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:53293533fcbb94c202b7c800a12c873cfe24599656b341f56e71dd2b557be063"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c381bda330ddf2fccbafab789d83ebc6c53db126e4383e73794c74eedce855ef"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d29409b625a143649d03d0fd7b57e4b92e0ecad9726ba682244b73be91d2fdb"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:183a517a3a63503f70f808b58bfbf962f23d73b6dccddae5aa56152ef2bcb232"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:15c4e4cfa45f5a60599d9cec5f46cd7b1b29d86a6390ec23e8eebaae84e64554"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-win32.whl", hash = "sha256:adf20d9a67e0b6393eac162eb81fb10bc9130a80540f4df7e7355c2dd4af9fba"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:2f9ffd643bc7349eeb664eba8864d9e01f057880f510e4681ba40a6532f93c71"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:def68d7c21984b0f8218e8a15d514f714d96904265164f75f8d3a70f9c295667"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dffc08ca91c9ac09008870c9eb77b00a46b3378719584059c034b8945e26b272"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:280b0bb5cbfe8039205c7981cceb006156a675362a00fe29b16fbc264e242834"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:af9813db73395fb1fc211bac696faea4ca9ef53f32dc0cfa27e4e7cf766dcf24"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:63638d875be8c2784cfc952c9ac34e2b50e43f9f0a0660b65e2a87d656b3116c"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ffb7a888a047696e7f8240d649b43fb3644f14f0ee229077e7f6b9f9081635bd"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0c9d5450c566c80c396b7402895c4369a410cab5a82707b11aee1e624da7d004"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:d1c1b569ecafe3a69380a94e6ae09a4789bbb23666f3d3a08d06bbd2451f5ef1"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8fc53f9af09426a61db9ba357865c77f26076d48669f2e1bb24d85a22fb52307"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-win32.whl", hash = "sha256:6472a178e291b59e7f16ab49ec8b4f3bdada0a879c68d3817ff0963e722a82ce"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:35168209c9d51b145e459e05c31a9eaeffa9a6b0fd61689b48e07464ffd1a83e"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:47133f3f872faf28c1e87d4357220e809dfd3fa7c64295a4a148bcd1e6e34ec9"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91920527dea30175cc02a1099f331aa8c1ba39bf8b7762b7b56cbf54bc5cce42"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887dd9aac71765ac0d0bac1d0d4b4f2c99d5f5c1382d8b770404f0f3d0ce8a39"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:1f14c8b0942714eb3c74e1e71700cbbcb415acbc311c730370e70c578a44a25c"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:7af0dd86ddb2f8af5da57a976d27cd2cd15510518d582b478fbb2292428710b4"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93cd1967a18aa0edd4b95b1dfd554cf15af657cb606280996d393dadc88c3c35"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bda845b664bb6c91446ca9609fc69f7db6c334ec5e4adc87571c34e4f47b7ddb"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:01310cf4cf26db9aea5158c217caa92d291f0500051a6469ac52166e1a16f5b7"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:99485cab9ba0fa9b84f1f9e1fef106f44a46ef6afdeec8885e0b88d0772b49e8"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-win32.whl", hash = "sha256:46f0e0a6b5fa5851bbd9ab1bc805eef362d3a230fbdfbc209f4a236d0a7a990d"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:accfe7e982411da3178ec690baaceaad3c278652998b2c45828aaac66cd8285f"}, -] py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, @@ -851,8 +732,8 @@ tomli = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] typing-extensions = [ - {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, - {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, + {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, + {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, ] uvloop = [ {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, diff --git a/packages/core/minos-microservice-cqrs/pyproject.toml b/packages/core/minos-microservice-cqrs/pyproject.toml index 25286b446..6e1b07121 100644 --- a/packages/core/minos-microservice-cqrs/pyproject.toml +++ b/packages/core/minos-microservice-cqrs/pyproject.toml @@ -39,6 +39,7 @@ minos-microservice-networks = { version ="^0.7.0*", allow-prereleases = true } minos-microservice-common = { path = "../minos-microservice-common", develop = true } minos-microservice-networks = { path = "../minos-microservice-networks", develop = true } minos-microservice-aggregate = { path = "../minos-microservice-aggregate", develop = true } +minos-microservice-transactions = { path = "../minos-microservice-transactions", develop = true } black = "^22.3" isort = "^5.8.0" pytest = "^7.0.1" From a8867c700251e1d4759971d5071270106a29af64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 21 Apr 2022 12:02:14 +0200 Subject: [PATCH 15/75] ISSUE #65 * Move `TransactionService` logic to `SagaService`. --- .../minos/saga/services.py | 81 ++++++++- .../tests/test_saga/test_services.py | 123 +++++++++++++ .../minos-microservice-saga/tests/utils.py | 16 ++ .../minos/transactions/__init__.py | 3 - .../minos/transactions/services.py | 101 ----------- .../poetry.lock | 31 +--- .../pyproject.toml | 2 - .../tests/test_transactions/test_services.py | 161 ------------------ .../tests/utils.py | 5 +- 9 files changed, 220 insertions(+), 303 deletions(-) delete mode 100644 packages/core/minos-microservice-transactions/minos/transactions/services.py delete mode 100644 packages/core/minos-microservice-transactions/tests/test_transactions/test_services.py diff --git a/packages/core/minos-microservice-saga/minos/saga/services.py b/packages/core/minos-microservice-saga/minos/saga/services.py index 9ff6a3f3a..98fb06fcc 100644 --- a/packages/core/minos-microservice-saga/minos/saga/services.py +++ b/packages/core/minos-microservice-saga/minos/saga/services.py @@ -1,16 +1,32 @@ +import logging +from datetime import ( + timedelta, +) + from minos.common import ( Config, Inject, + current_datetime, ) from minos.networks import ( BrokerRequest, EnrouteDecorator, + Request, + ResponseException, enroute, ) from minos.saga import ( SagaManager, SagaResponse, ) +from minos.transactions import ( + TransactionNotFoundException, + TransactionRepository, + TransactionRepositoryConflictException, + TransactionStatus, +) + +logger = logging.getLogger(__name__) class SagaService: @@ -18,13 +34,74 @@ class SagaService: # noinspection PyUnusedLocal @Inject() - def __init__(self, *args, saga_manager: SagaManager, **kwargs): + def __init__(self, *args, saga_manager: SagaManager, transaction_repository: TransactionRepository, **kwargs): self.saga_manager = saga_manager + self.transaction_repository = transaction_repository @classmethod def __get_enroute__(cls, config: Config) -> dict[str, set[EnrouteDecorator]]: - return {cls.__reply__.__name__: {enroute.broker.command(f"{config.get_name()}Reply")}} + name = config.get_name() + return { + cls.__reply__.__name__: {enroute.broker.command(f"{config.get_name()}Reply")}, + cls.__reserve__.__name__: {enroute.broker.command(f"_Reserve{name.title()}Transaction")}, + cls.__reject__.__name__: {enroute.broker.command(f"_Reject{name.title()}Transaction")}, + cls.__commit__.__name__: {enroute.broker.command(f"_Commit{name.title()}Transaction")}, + cls.__reject_blocked__.__name__: {enroute.periodic.event("* * * * *")}, + } async def __reply__(self, request: BrokerRequest) -> None: response = SagaResponse.from_message(request.raw) await self.saga_manager.run(response=response, pause_on_disk=True, raise_on_error=False, return_execution=False) + + async def __reserve__(self, request: Request) -> None: + uuid = await request.content() + + try: + transaction = await self.transaction_repository.get(uuid) + except TransactionNotFoundException: + raise ResponseException(f"The transaction identified by {uuid!r} does not exist.") + + try: + await transaction.reserve() + except TransactionRepositoryConflictException: + raise ResponseException("The transaction could not be reserved.") + + async def __reject__(self, request: Request) -> None: + uuid = await request.content() + + try: + transaction = await self.transaction_repository.get(uuid) + except TransactionNotFoundException: + raise ResponseException(f"The transaction identified by {uuid!r} does not exist.") + + if transaction.status == TransactionStatus.REJECTED: + return + + try: + await transaction.reject() + except TransactionRepositoryConflictException as exc: + raise ResponseException(f"{exc!s}") + + async def __commit__(self, request: Request) -> None: + uuid = await request.content() + + try: + transaction = await self.transaction_repository.get(uuid) + except TransactionNotFoundException: + raise ResponseException(f"The transaction identified by {uuid!r} does not exist.") + + try: + await transaction.commit() + except TransactionRepositoryConflictException as exc: + raise ResponseException(f"{exc!s}") + + # noinspection PyUnusedLocal + async def __reject_blocked__(self, request: Request) -> None: + status_in = (TransactionStatus.RESERVED,) + updated_at_lt = current_datetime() - timedelta(minutes=1) + async for transaction in self.transaction_repository.select(status_in=status_in, updated_at_lt=updated_at_lt): + logger.info(f"Rejecting {transaction.uuid!r} transaction as it has been reserved for a long time...") + try: + await transaction.reject() + except TransactionRepositoryConflictException as exc: + logger.warning(f"Raised an exception while trying to reject a blocked transaction: {exc!r}") diff --git a/packages/core/minos-microservice-saga/tests/test_saga/test_services.py b/packages/core/minos-microservice-saga/tests/test_saga/test_services.py index 98c2f2196..f2c4823e3 100644 --- a/packages/core/minos-microservice-saga/tests/test_saga/test_services.py +++ b/packages/core/minos-microservice-saga/tests/test_saga/test_services.py @@ -1,4 +1,7 @@ import unittest +from datetime import ( + timedelta, +) from unittest.mock import ( call, patch, @@ -9,12 +12,16 @@ from minos.common import ( Config, + current_datetime, ) from minos.networks import ( BrokerCommandEnrouteDecorator, BrokerMessageV1, BrokerMessageV1Payload, BrokerRequest, + InMemoryRequest, + PeriodicEventEnrouteDecorator, + ResponseException, ) from minos.saga import ( SagaManager, @@ -22,8 +29,16 @@ SagaResponseStatus, SagaService, ) +from minos.transactions import ( + TransactionEntry, + TransactionNotFoundException, + TransactionRepository, + TransactionRepositoryConflictException, + TransactionStatus, +) from tests.utils import ( CONFIG_FILE_PATH, + FakeAsyncIterator, SagaTestCase, ) @@ -40,6 +55,10 @@ def setUp(self) -> None: def test_get_enroute(self): expected = { "__reply__": {BrokerCommandEnrouteDecorator("orderReply")}, + "__reserve__": {BrokerCommandEnrouteDecorator("_ReserveOrderTransaction")}, + "__reject__": {BrokerCommandEnrouteDecorator("_RejectOrderTransaction")}, + "__commit__": {BrokerCommandEnrouteDecorator("_CommitOrderTransaction")}, + "__reject_blocked__": {PeriodicEventEnrouteDecorator("* * * * *")}, } observed = SagaService.__get_enroute__(self.config) self.assertEqual(expected, observed) @@ -67,6 +86,110 @@ async def test_reply(self): run_mock.call_args_list, ) + async def test_reserve(self): + uuid = uuid4() + with patch.object(TransactionEntry, "reserve") as reserve_mock: + with patch.object(TransactionRepository, "get", return_value=TransactionEntry(uuid)) as get_mock: + response = await self.service.__reserve__(InMemoryRequest(uuid)) + self.assertEqual([call(uuid)], get_mock.call_args_list) + self.assertEqual([call()], reserve_mock.call_args_list) + self.assertEqual(None, response) + + async def test_reserve_raises(self): + with patch.object(TransactionRepository, "get", side_effect=TransactionNotFoundException("")): + with self.assertRaises(ResponseException): + await self.service.__reserve__(InMemoryRequest(None)) + + with patch.object(TransactionRepository, "get", return_value=TransactionEntry()): + with patch.object(TransactionEntry, "reserve", side_effect=TransactionRepositoryConflictException("")): + with self.assertRaises(ResponseException): + await self.service.__reserve__(InMemoryRequest(None)) + + async def test_reject(self): + uuid = uuid4() + with patch.object(TransactionEntry, "reject") as reject_mock: + with patch.object(TransactionRepository, "get", return_value=TransactionEntry(uuid)) as get_mock: + response = await self.service.__reject__(InMemoryRequest(uuid)) + self.assertEqual([call(uuid)], get_mock.call_args_list) + self.assertEqual([call()], reject_mock.call_args_list) + self.assertEqual(None, response) + + async def test_reject_already(self): + uuid = uuid4() + with patch.object(TransactionEntry, "reject") as reject_mock: + with patch.object( + TransactionRepository, + "get", + return_value=TransactionEntry(uuid, status=TransactionStatus.REJECTED), + ) as get_mock: + response = await self.service.__reject__(InMemoryRequest(uuid)) + self.assertEqual([call(uuid)], get_mock.call_args_list) + self.assertEqual([], reject_mock.call_args_list) + self.assertEqual(None, response) + + async def test_reject_raises(self): + with patch.object(TransactionRepository, "get", side_effect=TransactionNotFoundException("")): + with self.assertRaises(ResponseException): + await self.service.__reject__(InMemoryRequest(None)) + + with patch.object(TransactionRepository, "get", return_value=TransactionEntry()): + with patch.object(TransactionEntry, "reject", side_effect=TransactionRepositoryConflictException("")): + with self.assertRaises(ResponseException): + await self.service.__reject__(InMemoryRequest(None)) + + async def test_commit(self): + uuid = uuid4() + with patch.object(TransactionEntry, "commit") as commit_mock: + with patch.object(TransactionRepository, "get", return_value=TransactionEntry(uuid)) as get_mock: + response = await self.service.__commit__(InMemoryRequest(uuid)) + self.assertEqual([call(uuid)], get_mock.call_args_list) + self.assertEqual([call()], commit_mock.call_args_list) + self.assertEqual(None, response) + + async def test_commit_raises(self): + with patch.object(TransactionRepository, "get", side_effect=TransactionNotFoundException("")): + with self.assertRaises(ResponseException): + await self.service.__commit__(InMemoryRequest(None)) + + with patch.object(TransactionRepository, "get", return_value=TransactionEntry()): + with patch.object(TransactionEntry, "commit", side_effect=TransactionRepositoryConflictException("")): + with self.assertRaises(ResponseException): + await self.service.__commit__(InMemoryRequest(None)) + + async def test_reject_blocked(self): + uuid = uuid4() + with patch.object(TransactionEntry, "reject") as reject_mock: + with patch.object( + TransactionRepository, "select", return_value=FakeAsyncIterator([TransactionEntry(uuid)]) + ) as select_mock: + response = await self.service.__reject_blocked__(InMemoryRequest(uuid)) + + self.assertEqual(1, select_mock.call_count) + self.assertEqual((TransactionStatus.RESERVED,), select_mock.call_args.kwargs["status_in"]) + self.assertAlmostEqual( + current_datetime() - timedelta(minutes=1), + select_mock.call_args.kwargs["updated_at_lt"], + delta=timedelta(seconds=5), + ) + + self.assertEqual([call()], reject_mock.call_args_list) + self.assertEqual(None, response) + + async def test_reject_blocked_raises(self): + uuid = uuid4() + with patch.object( + TransactionEntry, "reject", side_effect=[None, TransactionRepositoryConflictException("")] + ) as reject_mock: + with patch.object( + TransactionRepository, + "select", + return_value=FakeAsyncIterator([TransactionEntry(uuid), TransactionEntry(uuid)]), + ): + response = await self.service.__reject_blocked__(InMemoryRequest(uuid)) + + self.assertEqual([call(), call()], reject_mock.call_args_list) + self.assertEqual(None, response) + if __name__ == "__main__": unittest.main() diff --git a/packages/core/minos-microservice-saga/tests/utils.py b/packages/core/minos-microservice-saga/tests/utils.py index 7c1870a25..5fc9df0b9 100644 --- a/packages/core/minos-microservice-saga/tests/utils.py +++ b/packages/core/minos-microservice-saga/tests/utils.py @@ -68,6 +68,22 @@ async def send(self, data: Any, **kwargs) -> None: """For testing purposes.""" +class FakeAsyncIterator: + """For testing purposes.""" + + def __init__(self, seq): + self.iter = iter(seq) + + def __aiter__(self): + return self + + async def __anext__(self): + try: + return next(self.iter) + except StopIteration: + raise StopAsyncIteration + + class FakeLock(Lock): """For testing purposes.""" diff --git a/packages/core/minos-microservice-transactions/minos/transactions/__init__.py b/packages/core/minos-microservice-transactions/minos/transactions/__init__.py index fb9f69663..8a0ff6dcc 100644 --- a/packages/core/minos-microservice-transactions/minos/transactions/__init__.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/__init__.py @@ -25,6 +25,3 @@ TransactionDatabaseOperationFactory, TransactionRepository, ) -from .services import ( - TransactionService, -) diff --git a/packages/core/minos-microservice-transactions/minos/transactions/services.py b/packages/core/minos-microservice-transactions/minos/transactions/services.py deleted file mode 100644 index ec1aae562..000000000 --- a/packages/core/minos-microservice-transactions/minos/transactions/services.py +++ /dev/null @@ -1,101 +0,0 @@ -import logging -from datetime import ( - timedelta, -) - -from minos.common import ( - Config, - Inject, - current_datetime, -) -from minos.networks import ( - EnrouteDecorator, - Request, - ResponseException, - enroute, -) - -from .entries import ( - TransactionStatus, -) -from .exceptions import ( - TransactionNotFoundException, - TransactionRepositoryConflictException, -) -from .repositories import ( - TransactionRepository, -) - -logger = logging.getLogger(__name__) - - -class TransactionService: - """Snapshot Service class.""" - - # noinspection PyUnusedLocal - @Inject() - def __init__(self, *args, transaction_repository: TransactionRepository, **kwargs): - self.transaction_repository = transaction_repository - - @classmethod - def __get_enroute__(cls, config: Config) -> dict[str, set[EnrouteDecorator]]: - name = config.get_name() - return { - cls.__reserve__.__name__: {enroute.broker.command(f"_Reserve{name.title()}Transaction")}, - cls.__reject__.__name__: {enroute.broker.command(f"_Reject{name.title()}Transaction")}, - cls.__commit__.__name__: {enroute.broker.command(f"_Commit{name.title()}Transaction")}, - cls.__reject_blocked__.__name__: {enroute.periodic.event("* * * * *")}, - } - - async def __reserve__(self, request: Request) -> None: - uuid = await request.content() - - try: - transaction = await self.transaction_repository.get(uuid) - except TransactionNotFoundException: - raise ResponseException(f"The transaction identified by {uuid!r} does not exist.") - - try: - await transaction.reserve() - except TransactionRepositoryConflictException: - raise ResponseException("The transaction could not be reserved.") - - async def __reject__(self, request: Request) -> None: - uuid = await request.content() - - try: - transaction = await self.transaction_repository.get(uuid) - except TransactionNotFoundException: - raise ResponseException(f"The transaction identified by {uuid!r} does not exist.") - - if transaction.status == TransactionStatus.REJECTED: - return - - try: - await transaction.reject() - except TransactionRepositoryConflictException as exc: - raise ResponseException(f"{exc!s}") - - async def __commit__(self, request: Request) -> None: - uuid = await request.content() - - try: - transaction = await self.transaction_repository.get(uuid) - except TransactionNotFoundException: - raise ResponseException(f"The transaction identified by {uuid!r} does not exist.") - - try: - await transaction.commit() - except TransactionRepositoryConflictException as exc: - raise ResponseException(f"{exc!s}") - - # noinspection PyUnusedLocal - async def __reject_blocked__(self, request: Request) -> None: - status_in = (TransactionStatus.RESERVED,) - updated_at_lt = current_datetime() - timedelta(minutes=1) - async for transaction in self.transaction_repository.select(status_in=status_in, updated_at_lt=updated_at_lt): - logger.info(f"Rejecting {transaction.uuid!r} transaction as it has been reserved for a long time...") - try: - await transaction.reject() - except TransactionRepositoryConflictException as exc: - logger.warning(f"Raised an exception while trying to reject a blocked transaction: {exc!r}") diff --git a/packages/core/minos-microservice-transactions/poetry.lock b/packages/core/minos-microservice-transactions/poetry.lock index ac8ec33d1..251cb1d6b 100644 --- a/packages/core/minos-microservice-transactions/poetry.lock +++ b/packages/core/minos-microservice-transactions/poetry.lock @@ -115,14 +115,6 @@ python-versions = ">=3.7" [package.extras] toml = ["tomli"] -[[package]] -name = "crontab" -version = "0.23.0" -description = "Parse and use crontab schedules in Python" -category = "main" -optional = false -python-versions = "*" - [[package]] name = "dependency-injector" version = "4.39.1" @@ -219,23 +211,6 @@ uvloop = "^0.16.0" type = "directory" url = "../minos-microservice-common" -[[package]] -name = "minos-microservice-networks" -version = "0.7.0.dev1" -description = "The networks core of the Minos Framework" -category = "main" -optional = false -python-versions = "^3.9" -develop = true - -[package.dependencies] -crontab = "^0.23.0" -minos-microservice-common = "^0.7.0*" - -[package.source] -type = "directory" -url = "../minos-microservice-networks" - [[package]] name = "mypy-extensions" version = "0.4.3" @@ -399,7 +374,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "9c9ca4862b7363ae69ed21727f7a65a29a33e373df45250938f7c75f398b8da5" +content-hash = "4c34a5eab6efb983f4ab2f609f54e5a8475bad1de65c75cce36989757379ea2d" [metadata.files] aiomisc = [ @@ -498,9 +473,6 @@ coverage = [ {file = "coverage-6.3.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf"}, {file = "coverage-6.3.2.tar.gz", hash = "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9"}, ] -crontab = [ - {file = "crontab-0.23.0.tar.gz", hash = "sha256:ca79dede9c2f572bb32f38703e8fddcf3427e86edc838f2ffe7ae4b9ee2b0733"}, -] dependency-injector = [ {file = "dependency-injector-4.39.1.tar.gz", hash = "sha256:9ab76dc5e19b2692aaca49e00f9b41a087138d139b0ec985f92ff0498f038772"}, {file = "dependency_injector-4.39.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c788a3d5482e63b5fd55e14fc258f1ff0b51b411927ab132ef0f689cb5d1183f"}, @@ -574,7 +546,6 @@ mccabe = [ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] minos-microservice-common = [] -minos-microservice-networks = [] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, diff --git a/packages/core/minos-microservice-transactions/pyproject.toml b/packages/core/minos-microservice-transactions/pyproject.toml index 4cc1b8889..8a9906365 100644 --- a/packages/core/minos-microservice-transactions/pyproject.toml +++ b/packages/core/minos-microservice-transactions/pyproject.toml @@ -32,12 +32,10 @@ include = [ [tool.poetry.dependencies] python = "^3.9" minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true } -minos-microservice-networks = { version ="^0.7.0*", allow-prereleases = true } cached-property = "^1.5.2" [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../minos-microservice-common", develop = true } -minos-microservice-networks = { path = "../minos-microservice-networks", develop = true } black = "^22.3" isort = "^5.8.0" pytest = "^7.0.1" diff --git a/packages/core/minos-microservice-transactions/tests/test_transactions/test_services.py b/packages/core/minos-microservice-transactions/tests/test_transactions/test_services.py deleted file mode 100644 index 3c1e67849..000000000 --- a/packages/core/minos-microservice-transactions/tests/test_transactions/test_services.py +++ /dev/null @@ -1,161 +0,0 @@ -import unittest -from datetime import ( - timedelta, -) -from unittest.mock import ( - call, - patch, -) -from uuid import ( - uuid4, -) - -from minos.common import ( - current_datetime, -) -from minos.common.testing import ( - DatabaseMinosTestCase, -) -from minos.networks import ( - BrokerCommandEnrouteDecorator, - InMemoryRequest, - PeriodicEventEnrouteDecorator, - ResponseException, -) -from minos.transactions import ( - TransactionEntry, - TransactionNotFoundException, - TransactionRepository, - TransactionRepositoryConflictException, - TransactionService, - TransactionStatus, -) -from tests.utils import ( - FakeAsyncIterator, - TransactionsTestCase, -) - - -class TestSnapshotService(TransactionsTestCase, DatabaseMinosTestCase): - def setUp(self) -> None: - super().setUp() - - self.service = TransactionService(config=self.config) - - def test_get_enroute(self): - expected = { - "__reserve__": {BrokerCommandEnrouteDecorator("_ReserveOrderTransaction")}, - "__reject__": {BrokerCommandEnrouteDecorator("_RejectOrderTransaction")}, - "__commit__": {BrokerCommandEnrouteDecorator("_CommitOrderTransaction")}, - "__reject_blocked__": {PeriodicEventEnrouteDecorator("* * * * *")}, - } - observed = TransactionService.__get_enroute__(self.config) - self.assertEqual(expected, observed) - - async def test_reserve(self): - uuid = uuid4() - with patch.object(TransactionEntry, "reserve") as reserve_mock: - with patch.object(TransactionRepository, "get", return_value=TransactionEntry(uuid)) as get_mock: - response = await self.service.__reserve__(InMemoryRequest(uuid)) - self.assertEqual([call(uuid)], get_mock.call_args_list) - self.assertEqual([call()], reserve_mock.call_args_list) - self.assertEqual(None, response) - - async def test_reserve_raises(self): - with patch.object(TransactionRepository, "get", side_effect=TransactionNotFoundException("")): - with self.assertRaises(ResponseException): - await self.service.__reserve__(InMemoryRequest(None)) - - with patch.object(TransactionRepository, "get", return_value=TransactionEntry()): - with patch.object(TransactionEntry, "reserve", side_effect=TransactionRepositoryConflictException("")): - with self.assertRaises(ResponseException): - await self.service.__reserve__(InMemoryRequest(None)) - - async def test_reject(self): - uuid = uuid4() - with patch.object(TransactionEntry, "reject") as reject_mock: - with patch.object(TransactionRepository, "get", return_value=TransactionEntry(uuid)) as get_mock: - response = await self.service.__reject__(InMemoryRequest(uuid)) - self.assertEqual([call(uuid)], get_mock.call_args_list) - self.assertEqual([call()], reject_mock.call_args_list) - self.assertEqual(None, response) - - async def test_reject_already(self): - uuid = uuid4() - with patch.object(TransactionEntry, "reject") as reject_mock: - with patch.object( - TransactionRepository, - "get", - return_value=TransactionEntry(uuid, status=TransactionStatus.REJECTED), - ) as get_mock: - response = await self.service.__reject__(InMemoryRequest(uuid)) - self.assertEqual([call(uuid)], get_mock.call_args_list) - self.assertEqual([], reject_mock.call_args_list) - self.assertEqual(None, response) - - async def test_reject_raises(self): - with patch.object(TransactionRepository, "get", side_effect=TransactionNotFoundException("")): - with self.assertRaises(ResponseException): - await self.service.__reject__(InMemoryRequest(None)) - - with patch.object(TransactionRepository, "get", return_value=TransactionEntry()): - with patch.object(TransactionEntry, "reject", side_effect=TransactionRepositoryConflictException("")): - with self.assertRaises(ResponseException): - await self.service.__reject__(InMemoryRequest(None)) - - async def test_commit(self): - uuid = uuid4() - with patch.object(TransactionEntry, "commit") as commit_mock: - with patch.object(TransactionRepository, "get", return_value=TransactionEntry(uuid)) as get_mock: - response = await self.service.__commit__(InMemoryRequest(uuid)) - self.assertEqual([call(uuid)], get_mock.call_args_list) - self.assertEqual([call()], commit_mock.call_args_list) - self.assertEqual(None, response) - - async def test_commit_raises(self): - with patch.object(TransactionRepository, "get", side_effect=TransactionNotFoundException("")): - with self.assertRaises(ResponseException): - await self.service.__commit__(InMemoryRequest(None)) - - with patch.object(TransactionRepository, "get", return_value=TransactionEntry()): - with patch.object(TransactionEntry, "commit", side_effect=TransactionRepositoryConflictException("")): - with self.assertRaises(ResponseException): - await self.service.__commit__(InMemoryRequest(None)) - - async def test_reject_blocked(self): - uuid = uuid4() - with patch.object(TransactionEntry, "reject") as reject_mock: - with patch.object( - TransactionRepository, "select", return_value=FakeAsyncIterator([TransactionEntry(uuid)]) - ) as select_mock: - response = await self.service.__reject_blocked__(InMemoryRequest(uuid)) - - self.assertEqual(1, select_mock.call_count) - self.assertEqual((TransactionStatus.RESERVED,), select_mock.call_args.kwargs["status_in"]) - self.assertAlmostEqual( - current_datetime() - timedelta(minutes=1), - select_mock.call_args.kwargs["updated_at_lt"], - delta=timedelta(seconds=5), - ) - - self.assertEqual([call()], reject_mock.call_args_list) - self.assertEqual(None, response) - - async def test_reject_blocked_raises(self): - uuid = uuid4() - with patch.object( - TransactionEntry, "reject", side_effect=[None, TransactionRepositoryConflictException("")] - ) as reject_mock: - with patch.object( - TransactionRepository, - "select", - return_value=FakeAsyncIterator([TransactionEntry(uuid), TransactionEntry(uuid)]), - ): - response = await self.service.__reject_blocked__(InMemoryRequest(uuid)) - - self.assertEqual([call(), call()], reject_mock.call_args_list) - self.assertEqual(None, response) - - -if __name__ == "__main__": - unittest.main() diff --git a/packages/core/minos-microservice-transactions/tests/utils.py b/packages/core/minos-microservice-transactions/tests/utils.py index 0c0a888e6..c909fe6a5 100644 --- a/packages/core/minos-microservice-transactions/tests/utils.py +++ b/packages/core/minos-microservice-transactions/tests/utils.py @@ -22,9 +22,6 @@ from minos.common.testing import ( MinosTestCase, ) -from minos.networks import ( - BrokerClientPool, -) from minos.transactions import ( InMemoryTransactionRepository, ) @@ -40,7 +37,7 @@ def get_config_file_path(self): def get_injections(self) -> list[Union[InjectableMixin, type[InjectableMixin], str]]: pool_factory = PoolFactory.from_config( self.config, - default_classes={"broker": BrokerClientPool, "lock": FakeLockPool, "database": DatabaseClientPool}, + default_classes={"lock": FakeLockPool, "database": DatabaseClientPool}, ) transaction_repository = InMemoryTransactionRepository(lock_pool=pool_factory.get_pool("lock")) From 4827c4f4c9d1592b5e73019fe414b5248c724dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 21 Apr 2022 16:14:31 +0200 Subject: [PATCH 16/75] ISSUE #65 * Minor change. --- packages/core/minos-microservice-aggregate/poetry.lock | 3 ++- packages/core/minos-microservice-aggregate/pyproject.toml | 2 +- packages/core/minos-microservice-saga/poetry.lock | 3 ++- packages/core/minos-microservice-saga/pyproject.toml | 2 +- packages/plugins/minos-database-aiopg/poetry.lock | 6 +++--- packages/plugins/minos-database-aiopg/pyproject.toml | 2 +- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/poetry.lock b/packages/core/minos-microservice-aggregate/poetry.lock index 9d85569e8..aef88a048 100644 --- a/packages/core/minos-microservice-aggregate/poetry.lock +++ b/packages/core/minos-microservice-aggregate/poetry.lock @@ -231,6 +231,7 @@ develop = true [package.dependencies] crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" @@ -416,7 +417,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "0db237d303b06dd9fc7f7bf21e39e84845e915b71fd12bc90c4c2cf7563caf93" +content-hash = "f7a11c35a966519ecda45424aadc924e0d1101a33522129d107f4b80b7644dcb" [metadata.files] aiomisc = [ diff --git a/packages/core/minos-microservice-aggregate/pyproject.toml b/packages/core/minos-microservice-aggregate/pyproject.toml index 01189fd2a..c9262d1d0 100644 --- a/packages/core/minos-microservice-aggregate/pyproject.toml +++ b/packages/core/minos-microservice-aggregate/pyproject.toml @@ -33,7 +33,7 @@ include = [ python = "^3.9" minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true } minos-microservice-networks = { version ="^0.7.0*", allow-prereleases = true } -minos-microservice-transactions = { version ="^0.0.0*", allow-prereleases = true } +minos-microservice-transactions = { version ="^0.7.0*", allow-prereleases = true } cached-property = "^1.5.2" [tool.poetry.dev-dependencies] diff --git a/packages/core/minos-microservice-saga/poetry.lock b/packages/core/minos-microservice-saga/poetry.lock index 9d85569e8..aef88a048 100644 --- a/packages/core/minos-microservice-saga/poetry.lock +++ b/packages/core/minos-microservice-saga/poetry.lock @@ -231,6 +231,7 @@ develop = true [package.dependencies] crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" @@ -416,7 +417,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "0db237d303b06dd9fc7f7bf21e39e84845e915b71fd12bc90c4c2cf7563caf93" +content-hash = "f7a11c35a966519ecda45424aadc924e0d1101a33522129d107f4b80b7644dcb" [metadata.files] aiomisc = [ diff --git a/packages/core/minos-microservice-saga/pyproject.toml b/packages/core/minos-microservice-saga/pyproject.toml index e96489254..253484d3e 100644 --- a/packages/core/minos-microservice-saga/pyproject.toml +++ b/packages/core/minos-microservice-saga/pyproject.toml @@ -31,7 +31,7 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-transactions = { version ="^0.0.0*", allow-prereleases = true } +minos-microservice-transactions = { version ="^0.7.0*", allow-prereleases = true } minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true } minos-microservice-networks = { version ="^0.7.0*", allow-prereleases = true } cached-property = "^1.5.2" diff --git a/packages/plugins/minos-database-aiopg/poetry.lock b/packages/plugins/minos-database-aiopg/poetry.lock index ce7e01062..eb6ed2e19 100644 --- a/packages/plugins/minos-database-aiopg/poetry.lock +++ b/packages/plugins/minos-database-aiopg/poetry.lock @@ -233,7 +233,7 @@ develop = true cached-property = "^1.5.2" minos-microservice-common = "^0.7.0*" minos-microservice-networks = "^0.7.0*" -minos-microservice-transactions = "^0.0.0*" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" @@ -273,6 +273,7 @@ develop = true [package.dependencies] crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" @@ -290,7 +291,6 @@ develop = true [package.dependencies] cached-property = "^1.5.2" minos-microservice-common = "^0.7.0*" -minos-microservice-networks = "^0.7.0*" [package.source] type = "directory" @@ -467,7 +467,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "f321d3408cb81d58e84018c0009cb373d9622926f2d3e611bfdf86c40a944817" +content-hash = "963fbc74ad4e913a0a32f4cf9014e8182572fac729735297f700d3237d11f44b" [metadata.files] aiomisc = [ diff --git a/packages/plugins/minos-database-aiopg/pyproject.toml b/packages/plugins/minos-database-aiopg/pyproject.toml index c800f06b0..820d402b2 100644 --- a/packages/plugins/minos-database-aiopg/pyproject.toml +++ b/packages/plugins/minos-database-aiopg/pyproject.toml @@ -34,7 +34,7 @@ python = "^3.9" minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true } minos-microservice-networks = { version ="^0.7.0*", allow-prereleases = true } minos-microservice-aggregate = { version ="^0.7.0*", allow-prereleases = true } -minos-microservice-transactions = { version ="^0.0.0*", allow-prereleases = true } +minos-microservice-transactions = { version ="^0.7.0*", allow-prereleases = true } aiopg = "^1.2.1" psycopg2-binary = "^2.9.3" From e0d6483a373d1c558a33e46287023e10abb9084e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 21 Apr 2022 16:36:57 +0200 Subject: [PATCH 17/75] ISSUE #65 * Fix bug related with `poetry.lock`. --- packages/core/minos-microservice-cqrs/poetry.lock | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/core/minos-microservice-cqrs/poetry.lock b/packages/core/minos-microservice-cqrs/poetry.lock index 3940e115b..e9d3a0870 100644 --- a/packages/core/minos-microservice-cqrs/poetry.lock +++ b/packages/core/minos-microservice-cqrs/poetry.lock @@ -210,10 +210,7 @@ develop = true cached-property = "^1.5.2" minos-microservice-common = "^0.7.0*" minos-microservice-networks = "^0.7.0*" -<<<<<<< HEAD -minos-microservice-transactions = "^0.0.0*" -======= ->>>>>>> origin/issue-63-observer-transaction +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" @@ -253,6 +250,7 @@ develop = true [package.dependencies] crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" @@ -270,7 +268,6 @@ develop = true [package.dependencies] cached-property = "^1.5.2" minos-microservice-common = "^0.7.0*" -minos-microservice-networks = "^0.7.0*" [package.source] type = "directory" From b55bf0423b3c5ec7c80fbdf0e7cd02bd161c8575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 21 Apr 2022 16:44:50 +0200 Subject: [PATCH 18/75] ISSUE #86 * Add `TransactionalBrokerPublisher`. --- .../minos/networks/__init__.py | 6 ++ .../minos/networks/brokers/__init__.py | 6 ++ .../networks/brokers/publishers/__init__.py | 8 ++ .../publishers/transactional/__init__.py | 12 +++ .../publishers/transactional/entries.py | 38 ++++++++++ .../brokers/publishers/transactional/impl.py | 74 +++++++++++++++++++ .../transactional/repositories/__init__.py | 10 +++ .../transactional/repositories/abc.py | 42 +++++++++++ .../repositories/database/__init__.py | 6 ++ .../repositories/database/factories.py | 32 ++++++++ .../repositories/database/impl.py | 54 ++++++++++++++ .../transactional/repositories/memory.py | 34 +++++++++ .../minos-microservice-networks/poetry.lock | 20 ++++- .../pyproject.toml | 2 + 14 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/__init__.py create mode 100644 packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py create mode 100644 packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py create mode 100644 packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/__init__.py create mode 100644 packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py create mode 100644 packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/__init__.py create mode 100644 packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py create mode 100644 packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py create mode 100644 packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py diff --git a/packages/core/minos-microservice-networks/minos/networks/__init__.py b/packages/core/minos-microservice-networks/minos/networks/__init__.py index d3ae24f8e..69b92de5b 100644 --- a/packages/core/minos-microservice-networks/minos/networks/__init__.py +++ b/packages/core/minos-microservice-networks/minos/networks/__init__.py @@ -22,6 +22,9 @@ BrokerPublisherBuilder, BrokerPublisherQueue, BrokerPublisherQueueDatabaseOperationFactory, + BrokerPublisherTransactionDatabaseOperationFactory, + BrokerPublisherTransactionEntry, + BrokerPublisherTransactionRepository, BrokerQueue, BrokerQueueDatabaseOperationFactory, BrokerRequest, @@ -36,6 +39,7 @@ BrokerSubscriberQueueDatabaseOperationFactory, BrokerSubscriberValidator, DatabaseBrokerPublisherQueue, + DatabaseBrokerPublisherTransactionRepository, DatabaseBrokerQueue, DatabaseBrokerQueueBuilder, DatabaseBrokerSubscriberDuplicateValidator, @@ -45,6 +49,7 @@ FilteredBrokerSubscriber, InMemoryBrokerPublisher, InMemoryBrokerPublisherQueue, + InMemoryBrokerPublisherTransactionRepository, InMemoryBrokerQueue, InMemoryBrokerSubscriber, InMemoryBrokerSubscriberBuilder, @@ -54,6 +59,7 @@ QueuedBrokerPublisher, QueuedBrokerSubscriber, QueuedBrokerSubscriberBuilder, + TransactionalBrokerPublisher, ) from .decorators import ( BrokerCommandEnrouteDecorator, diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/__init__.py b/packages/core/minos-microservice-networks/minos/networks/brokers/__init__.py index 0ec5e35de..6ed912ad1 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/__init__.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/__init__.py @@ -36,10 +36,16 @@ BrokerPublisherBuilder, BrokerPublisherQueue, BrokerPublisherQueueDatabaseOperationFactory, + BrokerPublisherTransactionDatabaseOperationFactory, + BrokerPublisherTransactionEntry, + BrokerPublisherTransactionRepository, DatabaseBrokerPublisherQueue, + DatabaseBrokerPublisherTransactionRepository, InMemoryBrokerPublisher, InMemoryBrokerPublisherQueue, + InMemoryBrokerPublisherTransactionRepository, QueuedBrokerPublisher, + TransactionalBrokerPublisher, ) from .subscribers import ( BrokerSubscriber, diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/__init__.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/__init__.py index d3195a41f..895956bd5 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/__init__.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/__init__.py @@ -12,3 +12,11 @@ InMemoryBrokerPublisherQueue, QueuedBrokerPublisher, ) +from .transactional import ( + BrokerPublisherTransactionDatabaseOperationFactory, + BrokerPublisherTransactionEntry, + BrokerPublisherTransactionRepository, + DatabaseBrokerPublisherTransactionRepository, + InMemoryBrokerPublisherTransactionRepository, + TransactionalBrokerPublisher, +) diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/__init__.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/__init__.py new file mode 100644 index 000000000..4fc6d7e72 --- /dev/null +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/__init__.py @@ -0,0 +1,12 @@ +from .entries import ( + BrokerPublisherTransactionEntry, +) +from .impl import ( + TransactionalBrokerPublisher, +) +from .repositories import ( + BrokerPublisherTransactionDatabaseOperationFactory, + BrokerPublisherTransactionRepository, + DatabaseBrokerPublisherTransactionRepository, + InMemoryBrokerPublisherTransactionRepository, +) diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py new file mode 100644 index 000000000..ddb637adb --- /dev/null +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py @@ -0,0 +1,38 @@ +from typing import ( + Any, + Union, +) +from uuid import ( + UUID, +) + +from ...messages import ( + BrokerMessage, +) + + +class BrokerPublisherTransactionEntry: + """TODO""" + + def __init__(self, message: Union[bytes, BrokerMessage], transaction_uuid: UUID): + if isinstance(message, bytes): + message = BrokerMessage.from_avro_bytes(message) + self._message = message + self._transaction_uuid = transaction_uuid + + @property + def message(self) -> BrokerMessage: + """TODO""" + return self._message + + @property + def transaction_uuid(self) -> UUID: + """TODO""" + return self._transaction_uuid + + def as_raw(self) -> dict[str, Any]: + """TODO""" + return { + "message": self._message.avro_bytes, + "transaction_uuid": self._transaction_uuid, + } diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py new file mode 100644 index 000000000..74f841384 --- /dev/null +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py @@ -0,0 +1,74 @@ +from uuid import ( + UUID, +) + +from minos.common import ( + NULL_UUID, + Inject, +) +from minos.transactions import ( + TRANSACTION_CONTEXT_VAR, + TransactionalMixin, +) + +from ...messages import ( + BrokerMessage, +) +from ..abc import ( + BrokerPublisher, +) +from . import ( + BrokerPublisherTransactionEntry, +) +from .repositories import ( + BrokerPublisherTransactionRepository, +) + + +class TransactionalBrokerPublisher(BrokerPublisher, TransactionalMixin): + """TODO""" + + impl: BrokerPublisher + repository: BrokerPublisherTransactionRepository + + @Inject() + def __init__(self, impl: BrokerPublisher, repository: BrokerPublisherTransactionRepository, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.impl = impl + self.repository = repository + + async def _send(self, message: BrokerMessage) -> None: + transaction = TRANSACTION_CONTEXT_VAR.get() + + if transaction is None: + await self.impl.send(message) + else: + entry = BrokerPublisherTransactionEntry(message, transaction.uuid) + await self.repository.submit(entry) + + async def commit_transaction(self, transaction_uuid: UUID, destination_transaction_uuid: UUID) -> None: + """Commit the transaction with given identifier. + + :param transaction_uuid: The identifier of the transaction to be committed. + :param destination_transaction_uuid: The identifier of the destination transaction. + :return: This method does not return anything. + """ + iterable = self.repository.select(transaction_uuid=transaction_uuid) + if destination_transaction_uuid == NULL_UUID: + async for entry in iterable: + await self.impl.send(entry.message) + else: + async for entry in iterable: + new_entry = BrokerPublisherTransactionEntry(entry.message, destination_transaction_uuid) + await self.repository.submit(new_entry) + + await self.repository.delete_batch(transaction_uuid=transaction_uuid) + + async def reject_transaction(self, transaction_uuid: UUID) -> None: + """Reject the transaction with given identifier + + :param transaction_uuid: The identifier of the transaction to be committed. + :return: This method does not return anything. + """ + await self.repository.delete_batch(transaction_uuid=transaction_uuid) diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/__init__.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/__init__.py new file mode 100644 index 000000000..fe6d379ac --- /dev/null +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/__init__.py @@ -0,0 +1,10 @@ +from .abc import ( + BrokerPublisherTransactionRepository, +) +from .database import ( + BrokerPublisherTransactionDatabaseOperationFactory, + DatabaseBrokerPublisherTransactionRepository, +) +from .memory import ( + InMemoryBrokerPublisherTransactionRepository, +) diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py new file mode 100644 index 000000000..fcfc7d643 --- /dev/null +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py @@ -0,0 +1,42 @@ +from abc import ( + ABC, + abstractmethod, +) +from collections.abc import ( + AsyncIterator, +) +from uuid import ( + UUID, +) + +from ..entries import ( + BrokerPublisherTransactionEntry, +) + + +class BrokerPublisherTransactionRepository(ABC): + """TODO""" + + def select(self, transaction_uuid: UUID) -> AsyncIterator[BrokerPublisherTransactionEntry]: + """TODO""" + return self._select(transaction_uuid) + + @abstractmethod + def _select(self, transaction_uuid: UUID) -> AsyncIterator[BrokerPublisherTransactionEntry]: + raise NotImplementedError + + async def submit(self, entry: BrokerPublisherTransactionEntry) -> None: + """TODO""" + await self._submit(entry) + + @abstractmethod + async def _submit(self, entry: BrokerPublisherTransactionEntry) -> None: + raise NotImplementedError + + async def delete_batch(self, transaction_uuid: UUID) -> None: + """TODO""" + await self._delete_batch(transaction_uuid) + + @abstractmethod + async def _delete_batch(self, transaction_uuid: UUID) -> None: + raise NotImplementedError diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/__init__.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/__init__.py new file mode 100644 index 000000000..f1ce716d0 --- /dev/null +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/__init__.py @@ -0,0 +1,6 @@ +from .factories import ( + BrokerPublisherTransactionDatabaseOperationFactory, +) +from .impl import ( + DatabaseBrokerPublisherTransactionRepository, +) diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py new file mode 100644 index 000000000..7d0a4c2fe --- /dev/null +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py @@ -0,0 +1,32 @@ +from abc import ( + ABC, + abstractmethod, +) +from uuid import ( + UUID, +) + +from minos.common import ( + DatabaseOperation, + DatabaseOperationFactory, +) + + +class BrokerPublisherTransactionDatabaseOperationFactory(DatabaseOperationFactory, ABC): + """TODO""" + + @abstractmethod + def build_create(self) -> DatabaseOperation: + """TODO""" + + @abstractmethod + def build_query(self, transaction_uuid: UUID) -> DatabaseOperation: + """TODO""" + + @abstractmethod + def build_submit(self, message: bytes, transaction_uuid: UUID) -> DatabaseOperation: + """TODO""" + + @abstractmethod + def build_delete_batch(self, transaction_uuid: UUID) -> DatabaseOperation: + """TODO""" diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py new file mode 100644 index 000000000..929bdccb0 --- /dev/null +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py @@ -0,0 +1,54 @@ +from typing import ( + AsyncIterator, + Optional, +) +from uuid import ( + UUID, +) + +from minos.common import ( + DatabaseMixin, +) + +from ...entries import ( + BrokerPublisherTransactionEntry, +) +from ..abc import ( + BrokerPublisherTransactionRepository, +) +from .factories import ( + BrokerPublisherTransactionDatabaseOperationFactory, +) + + +class DatabaseBrokerPublisherTransactionRepository( + BrokerPublisherTransactionRepository, + DatabaseMixin[BrokerPublisherTransactionDatabaseOperationFactory], +): + """TODO""" + + def __init__(self, *args, database_key: Optional[tuple[str]] = None, **kwargs): + if database_key is None: + database_key = ("broker",) + super().__init__(*args, database_key=database_key, **kwargs) + + async def _setup(self) -> None: + await super()._setup() + await self._create_table() + + async def _create_table(self) -> None: + operation = self.database_operation_factory.build_create() + await self.execute_on_database(operation) + + async def _select(self, transaction_uuid: UUID) -> AsyncIterator[BrokerPublisherTransactionEntry]: + operation = self.database_operation_factory.build_query(transaction_uuid) + async for raw in self.execute_on_database_and_fetch_all(operation): + yield BrokerPublisherTransactionEntry(*raw) + + async def _submit(self, entry: BrokerPublisherTransactionEntry) -> None: + operation = self.database_operation_factory.build_submit(**entry.as_raw()) + await self.execute_on_database(operation) + + async def _delete_batch(self, transaction_uuid: UUID) -> None: + operation = self.database_operation_factory.build_delete_batch(transaction_uuid) + await self.execute_on_database(operation) diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py new file mode 100644 index 000000000..90ac18a66 --- /dev/null +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py @@ -0,0 +1,34 @@ +from collections import ( + defaultdict, +) +from typing import ( + AsyncIterator, +) +from uuid import ( + UUID, +) + +from ..entries import ( + BrokerPublisherTransactionEntry, +) +from .abc import ( + BrokerPublisherTransactionRepository, +) + + +class InMemoryBrokerPublisherTransactionRepository(BrokerPublisherTransactionRepository): + """TODO""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._storage = defaultdict(list) + + async def _select(self, transaction_uuid: UUID) -> AsyncIterator[BrokerPublisherTransactionEntry]: + for entry in self._storage[transaction_uuid]: + yield entry + + async def _submit(self, entry: BrokerPublisherTransactionEntry) -> None: + self._storage[entry.transaction_uuid].append(entry) + + async def _delete_batch(self, transaction_uuid: UUID) -> None: + self._storage.pop(transaction_uuid) diff --git a/packages/core/minos-microservice-networks/poetry.lock b/packages/core/minos-microservice-networks/poetry.lock index fd5f64712..4c9f1cba7 100644 --- a/packages/core/minos-microservice-networks/poetry.lock +++ b/packages/core/minos-microservice-networks/poetry.lock @@ -219,6 +219,23 @@ uvloop = "^0.16.0" type = "directory" url = "../minos-microservice-common" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" + +[package.source] +type = "directory" +url = "../minos-microservice-transactions" + [[package]] name = "mypy-extensions" version = "0.4.3" @@ -382,7 +399,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "fb90fd955533067f90236079e7f071d3f45f6d4cf0d28398f4a1ac2654576755" +content-hash = "3ee45ec11638ae320cf4cc32ef855d4491f6d2231eaa29ca025b4eb345028cd5" [metadata.files] aiomisc = [ @@ -557,6 +574,7 @@ mccabe = [ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] minos-microservice-common = [] +minos-microservice-transactions = [] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, diff --git a/packages/core/minos-microservice-networks/pyproject.toml b/packages/core/minos-microservice-networks/pyproject.toml index 1120a73b1..a5de192a1 100644 --- a/packages/core/minos-microservice-networks/pyproject.toml +++ b/packages/core/minos-microservice-networks/pyproject.toml @@ -32,10 +32,12 @@ include = [ [tool.poetry.dependencies] python = "^3.9" minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true } +minos-microservice-transactions = { version ="^0.7.0*", allow-prereleases = true } crontab = "^0.23.0" [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../minos-microservice-common", develop = true } +minos-microservice-transactions = { path = "../minos-microservice-transactions", develop = true } black = "^22.3" isort = "^5.8.0" pytest = "^7.0.1" From de3e2153f623e18397e3851ed95cf629f815faea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 21 Apr 2022 17:29:52 +0200 Subject: [PATCH 19/75] ISSUE #86 * Add `AiopgBrokerPublisherTransactionDatabaseOperationFactory`. --- .../minos/plugins/aiopg/__init__.py | 1 + .../minos/plugins/aiopg/factories/__init__.py | 1 + .../aiopg/factories/networks/__init__.py | 1 + .../factories/networks/publishers/__init__.py | 3 + .../networks/publishers/transactional.py | 97 +++++++++++++++++++ 5 files changed, 103 insertions(+) create mode 100644 packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py index 152433c47..1a2ff659a 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py @@ -9,6 +9,7 @@ ) from .factories import ( AiopgBrokerPublisherQueueDatabaseOperationFactory, + AiopgBrokerPublisherTransactionDatabaseOperationFactory, AiopgBrokerQueueDatabaseOperationFactory, AiopgBrokerSubscriberDuplicateValidatorDatabaseOperationFactory, AiopgBrokerSubscriberQueueDatabaseOperationFactory, diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py index e75be0303..28e8086dd 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py @@ -9,6 +9,7 @@ ) from .networks import ( AiopgBrokerPublisherQueueDatabaseOperationFactory, + AiopgBrokerPublisherTransactionDatabaseOperationFactory, AiopgBrokerQueueDatabaseOperationFactory, AiopgBrokerSubscriberDuplicateValidatorDatabaseOperationFactory, AiopgBrokerSubscriberQueueDatabaseOperationFactory, diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/__init__.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/__init__.py index 04568ca64..70626cedc 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/__init__.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/__init__.py @@ -3,6 +3,7 @@ ) from .publishers import ( AiopgBrokerPublisherQueueDatabaseOperationFactory, + AiopgBrokerPublisherTransactionDatabaseOperationFactory, ) from .subscribers import ( AiopgBrokerSubscriberDuplicateValidatorDatabaseOperationFactory, diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/__init__.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/__init__.py index fd07a5ba7..8ff68d8ad 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/__init__.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/__init__.py @@ -1,3 +1,6 @@ from .queues import ( AiopgBrokerPublisherQueueDatabaseOperationFactory, ) +from .transactional import ( + AiopgBrokerPublisherTransactionDatabaseOperationFactory, +) diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py new file mode 100644 index 000000000..1c4f94f66 --- /dev/null +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py @@ -0,0 +1,97 @@ +from uuid import ( + UUID, +) + +from psycopg2.sql import ( + SQL, +) + +from minos.common import ( + ComposedDatabaseOperation, + DatabaseOperation, +) +from minos.networks import ( + BrokerPublisherTransactionDatabaseOperationFactory, +) + +from ....clients import ( + AiopgDatabaseClient, +) +from ....operations import ( + AiopgDatabaseOperation, +) + + +# noinspection SqlDialectInspection,SqlNoDataSourceInspection +class AiopgBrokerPublisherTransactionDatabaseOperationFactory(BrokerPublisherTransactionDatabaseOperationFactory): + """TODO""" + + @staticmethod + def build_table_name() -> str: + """Build the table name. + + :return: A ``str`` instance. + """ + return "broker_publisher_transactional_messages" + + def build_create(self) -> DatabaseOperation: + """TODO""" + return ComposedDatabaseOperation( + [ + AiopgDatabaseOperation( + SQL('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";'), + lock="uuid-ossp", + ), + AiopgDatabaseOperation( + SQL( + f""" + CREATE TABLE IF NOT EXISTS {self.build_table_name()} ( + message BYTEA NOT NULL, + transaction_uuid UUID NOT NULL + ) + """ + ), + lock=self.build_table_name(), + ), + ] + ) + + def build_query(self, transaction_uuid: UUID) -> DatabaseOperation: + """TODO""" + return AiopgDatabaseOperation( + SQL( + f""" + SELECT message, transaction_uuid + FROM {self.build_table_name()} + WHERE transaction_uuid = %(transaction_uuid)s + """ + ), + {"transaction_uuid": transaction_uuid}, + ) + + def build_submit(self, message: bytes, transaction_uuid: UUID) -> DatabaseOperation: + """TODO""" + return AiopgDatabaseOperation( + SQL( + f""" + INSERT INTO {self.build_table_name()}(message, transaction_uuid) + VALUES(%(message)s, %(transaction_uuid)s) + """ + ), + { + "message": message, + "transaction_uuid": transaction_uuid, + }, + ) + + def build_delete_batch(self, transaction_uuid: UUID) -> DatabaseOperation: + """TODO""" + return AiopgDatabaseOperation( + SQL(f"DELETE FROM {self.build_table_name()} WHERE transaction_uuid = %(transaction_uuid)s"), + {"transaction_uuid": transaction_uuid}, + ) + + +AiopgDatabaseClient.set_factory( + BrokerPublisherTransactionDatabaseOperationFactory, AiopgBrokerPublisherTransactionDatabaseOperationFactory +) From 01174e60f8980146d690904a01d462653779c623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 21 Apr 2022 18:46:52 +0200 Subject: [PATCH 20/75] ISSUE #86 * Working on... --- .../minos/aggregate/aggregate.py | 48 ++++++++----------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py index 7f8bf18a1..efa9adc36 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py @@ -12,7 +12,7 @@ Config, Inject, NotProvidedException, - SetupMixin, + SetupMixin, Injectable, ) from minos.transactions import ( TransactionRepository, @@ -27,63 +27,55 @@ from .snapshots import ( SnapshotRepository, ) +from minos.networks import ( + TransactionalBrokerPublisher, +) RT = TypeVar("RT", bound=RootEntity) +@Injectable("aggregate") class Aggregate(Generic[RT], SetupMixin): """Base Service class""" transaction_repository: TransactionRepository event_repository: EventRepository snapshot_repository: SnapshotRepository + broker_publisher: TransactionalBrokerPublisher + @Inject() def __init__( self, transaction_repository: TransactionRepository, event_repository: EventRepository, snapshot_repository: SnapshotRepository, + broker_publisher: TransactionalBrokerPublisher, *args, **kwargs, ): + if transaction_repository is None: + raise NotProvidedException(f"A {TransactionRepository!r} object must be provided.") + if event_repository is None: + raise NotProvidedException(f"A {EventRepository!r} object must be provided.") + if snapshot_repository is None: + raise NotProvidedException(f"A {SnapshotRepository!r} object must be provided.") + if broker_publisher is None: + raise NotProvidedException(f"A {TransactionalBrokerPublisher!r} object must be provided.") + super().__init__(*args, **kwargs) + self._check_root() self.transaction_repository = transaction_repository self.event_repository = event_repository self.snapshot_repository = snapshot_repository + self.broker_publisher = broker_publisher @classmethod def _from_config(cls, config: Config, **kwargs) -> Aggregate: - kwargs["transaction_repository"] = cls._get_transaction_repository(**kwargs) - kwargs["event_repository"] = cls._get_event_repository(**kwargs) - kwargs["snapshot_repository"] = cls._get_snapshot_repository(**kwargs) + kwargs["broker_publisher"] = TransactionalBrokerPublisher.from_config(config, **kwargs) return cls(**kwargs) - # noinspection PyUnusedLocal - @staticmethod - @Inject() - def _get_transaction_repository(transaction_repository: TransactionRepository, **kwargs) -> TransactionRepository: - if transaction_repository is None: - raise NotProvidedException(f"A {TransactionRepository!r} object must be provided.") - return transaction_repository - - # noinspection PyUnusedLocal - @staticmethod - @Inject() - def _get_event_repository(event_repository: EventRepository, **kwargs) -> EventRepository: - if event_repository is None: - raise NotProvidedException(f"A {EventRepository!r} object must be provided.") - return event_repository - - # noinspection PyUnusedLocal - @staticmethod - @Inject() - def _get_snapshot_repository(snapshot_repository: SnapshotRepository, **kwargs) -> SnapshotRepository: - if snapshot_repository is None: - raise NotProvidedException(f"A {SnapshotRepository!r} object must be provided.") - return snapshot_repository - def _check_root(self): self.root # If root is not valid it will raise an exception. From fe725eed90254aeb015ca30b4abf37a31d2641c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Fri, 22 Apr 2022 09:42:00 +0200 Subject: [PATCH 21/75] ISSUE #86 * Fix syntax --- .../minos/aggregate/aggregate.py | 11 ++++++----- .../brokers/publishers/transactional/impl.py | 14 +++++++++++++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py index efa9adc36..7db83fd8a 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py @@ -11,8 +11,12 @@ from minos.common import ( Config, Inject, + Injectable, NotProvidedException, - SetupMixin, Injectable, + SetupMixin, +) +from minos.networks import ( + TransactionalBrokerPublisher, ) from minos.transactions import ( TransactionRepository, @@ -27,9 +31,6 @@ from .snapshots import ( SnapshotRepository, ) -from minos.networks import ( - TransactionalBrokerPublisher, -) RT = TypeVar("RT", bound=RootEntity) @@ -87,7 +88,7 @@ def root(self) -> type[RootEntity]: """ # noinspection PyUnresolvedReferences bases = self.__orig_bases__ - root = get_args(bases[0])[0] + root = get_args(next((base for base in bases if len(get_args(base))), None))[0] if not isinstance(root, type) or not issubclass(root, RootEntity): raise TypeError(f"{type(self)!r} must contain a {RootEntity!r} as generic value.") return root diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py index 74f841384..e9a3d23b8 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py @@ -1,9 +1,14 @@ +from __future__ import ( + annotations, +) + from uuid import ( UUID, ) from minos.common import ( NULL_UUID, + Config, Inject, ) from minos.transactions import ( @@ -17,11 +22,12 @@ from ..abc import ( BrokerPublisher, ) -from . import ( +from .entries import ( BrokerPublisherTransactionEntry, ) from .repositories import ( BrokerPublisherTransactionRepository, + InMemoryBrokerPublisherTransactionRepository, ) @@ -38,6 +44,12 @@ def __init__(self, impl: BrokerPublisher, repository: BrokerPublisherTransaction self.impl = impl self.repository = repository + @classmethod + def _from_config(cls, config: Config, **kwargs) -> TransactionalBrokerPublisher: + if "repository" not in kwargs: + kwargs["repository"] = InMemoryBrokerPublisherTransactionRepository() + return cls(**kwargs) + async def _send(self, message: BrokerMessage) -> None: transaction = TRANSACTION_CONTEXT_VAR.get() From 2f1b09d52dd007d3dcbac6ad2cae6547ce840624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Fri, 22 Apr 2022 09:51:15 +0200 Subject: [PATCH 22/75] ISSUE #86 * Add `minos-microservice-transactions` as a dev dependency. --- .../plugins/minos-broker-kafka/poetry.lock | 21 +- .../plugins/minos-broker-kafka/pyproject.toml | 1 + .../plugins/minos-broker-rabbitmq/poetry.lock | 26 +- .../minos-broker-rabbitmq/pyproject.toml | 1 + .../plugins/minos-discovery-kong/poetry.lock | 21 +- .../minos-discovery-kong/pyproject.toml | 1 + .../plugins/minos-discovery-minos/poetry.lock | 237 +++++------------- .../minos-discovery-minos/pyproject.toml | 1 + .../plugins/minos-http-aiohttp/poetry.lock | 237 +++++------------- .../plugins/minos-http-aiohttp/pyproject.toml | 1 + .../plugins/minos-router-graphql/poetry.lock | 21 +- .../minos-router-graphql/pyproject.toml | 1 + 12 files changed, 218 insertions(+), 351 deletions(-) diff --git a/packages/plugins/minos-broker-kafka/poetry.lock b/packages/plugins/minos-broker-kafka/poetry.lock index 5bb6c4143..33cf610d9 100644 --- a/packages/plugins/minos-broker-kafka/poetry.lock +++ b/packages/plugins/minos-broker-kafka/poetry.lock @@ -256,11 +256,29 @@ develop = true [package.dependencies] crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" url = "../../core/minos-microservice-networks" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" + +[package.source] +type = "directory" +url = "../../core/minos-microservice-transactions" + [[package]] name = "mypy-extensions" version = "0.4.3" @@ -432,7 +450,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "83dc6e09d794b3da6df0d99473af5ec70635027ee12d410e98eb29f830339979" +content-hash = "bf3c479e000ab771842f391d95fea5581e832d951dfc4e27de778ac08a304433" [metadata.files] aiokafka = [ @@ -635,6 +653,7 @@ mccabe = [ ] minos-microservice-common = [] minos-microservice-networks = [] +minos-microservice-transactions = [] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, diff --git a/packages/plugins/minos-broker-kafka/pyproject.toml b/packages/plugins/minos-broker-kafka/pyproject.toml index c3efa2ee0..b62bcfee8 100644 --- a/packages/plugins/minos-broker-kafka/pyproject.toml +++ b/packages/plugins/minos-broker-kafka/pyproject.toml @@ -40,6 +40,7 @@ kafka-python = "^2.0.2" [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../../core/minos-microservice-common", develop = true } minos-microservice-networks = { path = "../../core/minos-microservice-networks", develop = true } +minos-microservice-transactions = { path = "../../core/minos-microservice-transactions", develop = true } black = "^22.1" isort = "^5.8.0" pytest = "^6.2.4" diff --git a/packages/plugins/minos-broker-rabbitmq/poetry.lock b/packages/plugins/minos-broker-rabbitmq/poetry.lock index 7be5608d0..fc6627b3b 100644 --- a/packages/plugins/minos-broker-rabbitmq/poetry.lock +++ b/packages/plugins/minos-broker-rabbitmq/poetry.lock @@ -1,6 +1,6 @@ [[package]] name = "aio-pika" -version = "7.1.2" +version = "7.2.0" description = "Wrapper for the aiormq for asyncio and humans." category = "main" optional = false @@ -269,11 +269,29 @@ develop = true [package.dependencies] crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" url = "../../core/minos-microservice-networks" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" + +[package.source] +type = "directory" +url = "../../core/minos-microservice-transactions" + [[package]] name = "multidict" version = "6.0.2" @@ -477,12 +495,11 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "2b66ade14c61be67e8928576bec9684c7798cc021994c6815a8a0e25b47f5d5b" +content-hash = "c0890d7bedb8d8ad1ff37ae41b92b0791591284bbf025aed40ff0fb3b3fb77de" [metadata.files] aio-pika = [ - {file = "aio-pika-7.1.2.tar.gz", hash = "sha256:b754ba114ce3cfbc5fb444c0d41c5f74f5cfff34c2c87fef3eab0ba796ec3e94"}, - {file = "aio_pika-7.1.2-py3-none-any.whl", hash = "sha256:47fbd996d6ff4a8b1ea0148091b9e056c3a581fd4be863801eba8fce690cd243"}, + {file = "aio_pika-7.2.0-py3-none-any.whl", hash = "sha256:9b741aa81b3dd3917ec1a4910ab0766e4e568bac498831c6a02f0c96936b2d3c"}, ] aiomisc = [ {file = "aiomisc-15.7.3-py3-none-any.whl", hash = "sha256:0403e83268e98d0f2a125a70d13303fe1a2358e36db3daf02df032c7fa4f1525"}, @@ -665,6 +682,7 @@ mccabe = [ ] minos-microservice-common = [] minos-microservice-networks = [] +minos-microservice-transactions = [] multidict = [ {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2"}, {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3"}, diff --git a/packages/plugins/minos-broker-rabbitmq/pyproject.toml b/packages/plugins/minos-broker-rabbitmq/pyproject.toml index ff2f9a597..b68233979 100644 --- a/packages/plugins/minos-broker-rabbitmq/pyproject.toml +++ b/packages/plugins/minos-broker-rabbitmq/pyproject.toml @@ -38,6 +38,7 @@ aio-pika = "^7.1.0" [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../../core/minos-microservice-common", develop = true } minos-microservice-networks = { path = "../../core/minos-microservice-networks", develop = true } +minos-microservice-transactions = { path = "../../core/minos-microservice-transactions", develop = true } black = "^22.1" isort = "^5.8.0" pytest = "^6.2.4" diff --git a/packages/plugins/minos-discovery-kong/poetry.lock b/packages/plugins/minos-discovery-kong/poetry.lock index 317c08de6..887c4f451 100644 --- a/packages/plugins/minos-discovery-kong/poetry.lock +++ b/packages/plugins/minos-discovery-kong/poetry.lock @@ -322,11 +322,29 @@ develop = true [package.dependencies] crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" url = "../../core/minos-microservice-networks" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" + +[package.source] +type = "directory" +url = "../../core/minos-microservice-transactions" + [[package]] name = "mypy-extensions" version = "0.4.3" @@ -542,7 +560,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "a4bba089f11aeccbc7cbc7f0cedb301d87d26d1c12075a2a233c5bf9901027b7" +content-hash = "d4cc192dc0247c2577d6442e699a14adb86199ad0d260c57a4efc606162aa51c" [metadata.files] aiomisc = [ @@ -746,6 +764,7 @@ mccabe = [ ] minos-microservice-common = [] minos-microservice-networks = [] +minos-microservice-transactions = [] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, diff --git a/packages/plugins/minos-discovery-kong/pyproject.toml b/packages/plugins/minos-discovery-kong/pyproject.toml index dd4a45e56..cad402170 100644 --- a/packages/plugins/minos-discovery-kong/pyproject.toml +++ b/packages/plugins/minos-discovery-kong/pyproject.toml @@ -41,6 +41,7 @@ PyJWT = "^2.3.0" [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../../core/minos-microservice-common", develop = true } minos-microservice-networks = { path = "../../core/minos-microservice-networks", develop = true } +minos-microservice-transactions = { path = "../../core/minos-microservice-transactions", develop = true } black = "^22.1" isort = "^5.8.0" pytest = "^6.2.4" diff --git a/packages/plugins/minos-discovery-minos/poetry.lock b/packages/plugins/minos-discovery-minos/poetry.lock index 4b8937fd7..888ffafdb 100644 --- a/packages/plugins/minos-discovery-minos/poetry.lock +++ b/packages/plugins/minos-discovery-minos/poetry.lock @@ -39,21 +39,6 @@ develop = ["aiocontextvars (==0.2.2)", "aiohttp-asgi", "aiohttp (<4)", "async-ti raven = ["raven-aiohttp"] uvloop = ["uvloop (>=0.14,<1)"] -[[package]] -name = "aiopg" -version = "1.3.3" -description = "Postgres integration with asyncio." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -async-timeout = ">=3.0,<5.0" -psycopg2-binary = ">=2.8.4" - -[package.extras] -sa = ["sqlalchemy[postgresql_psycopg2binary] (>=1.3,<1.5)"] - [[package]] name = "aiosignal" version = "1.2.0" @@ -270,14 +255,6 @@ requirements_deprecated_finder = ["pipreqs", "pip-api"] colors = ["colorama (>=0.4.3,<0.5.0)"] plugins = ["setuptools"] -[[package]] -name = "lmdb" -version = "1.3.0" -description = "Universal Python binding for the LMDB 'Lightning' Database" -category = "main" -optional = false -python-versions = "*" - [[package]] name = "mccabe" version = "0.6.1" @@ -288,7 +265,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0.dev1" +version = "0.7.0.dev2" description = "The common core of the Minos Framework" category = "main" optional = false @@ -297,11 +274,9 @@ develop = true [package.dependencies] aiomisc = ">=14.0.3,<15.8.0" -aiopg = "^1.2.1" cached-property = "^1.5.2" dependency-injector = "^4.32.2" fastavro = "^1.4.0" -lmdb = "^1.2.1" orjson = "^3.5.2" PyYAML = ">=5.4.1,<7.0.0" uvloop = "^0.16.0" @@ -312,7 +287,7 @@ url = "../../core/minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0.dev1" +version = "0.7.0.dev2" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -320,15 +295,31 @@ python-versions = "^3.9" develop = true [package.dependencies] -aiopg = "^1.2.1" crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" -psycopg2-binary = "^2.9.3" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" url = "../../core/minos-microservice-networks" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" + +[package.source] +type = "directory" +url = "../../core/minos-microservice-transactions" + [[package]] name = "multidict" version = "6.0.2" @@ -347,7 +338,7 @@ python-versions = "*" [[package]] name = "orjson" -version = "3.6.7" +version = "3.6.8" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" category = "main" optional = false @@ -374,15 +365,15 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] name = "platformdirs" -version = "2.5.1" +version = "2.5.2" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] +test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] [[package]] name = "pluggy" @@ -396,14 +387,6 @@ python-versions = ">=3.6" dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "psycopg2-binary" -version = "2.9.3" -description = "psycopg2 - Python-PostgreSQL Database Adapter" -category = "main" -optional = false -python-versions = ">=3.6" - [[package]] name = "py" version = "1.11.0" @@ -494,11 +477,11 @@ python-versions = ">=3.7" [[package]] name = "typing-extensions" -version = "4.1.1" -description = "Backported and Experimental Type Hints for Python 3.6+" +version = "4.2.0" +description = "Backported and Experimental Type Hints for Python 3.7+" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "uvloop" @@ -528,7 +511,7 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "8de1ddcc7e0efd18606f140ff12b1863992d8867b595de724e91b86baddc47c1" +content-hash = "34f6c50045f0350f25472903d6464ee857e6496f6a3d8a6fba3f4436ad023da2" [metadata.files] aiohttp = [ @@ -609,10 +592,6 @@ aiomisc = [ {file = "aiomisc-15.7.3-py3-none-any.whl", hash = "sha256:0403e83268e98d0f2a125a70d13303fe1a2358e36db3daf02df032c7fa4f1525"}, {file = "aiomisc-15.7.3.tar.gz", hash = "sha256:ba250a34bd4609ced36111cb50580f57c3d52f3955f953a53ecb2986988baedc"}, ] -aiopg = [ - {file = "aiopg-1.3.3-py3-none-any.whl", hash = "sha256:2842dd8741460eeef940032dcb577bfba4d4115205dd82a73ce13b3271f5bf0a"}, - {file = "aiopg-1.3.3.tar.gz", hash = "sha256:547c6ba4ea0d73c2a11a2f44387d7133cc01d3c6f3b8ed976c0ac1eff4f595d7"}, -] aiosignal = [ {file = "aiosignal-1.2.0-py3-none-any.whl", hash = "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a"}, {file = "aiosignal-1.2.0.tar.gz", hash = "sha256:78ed67db6c7b7ced4f98e495e572106d5c432a93e1ddd1bf475e1dc05f5b7df2"}, @@ -853,41 +832,13 @@ isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] -lmdb = [ - {file = "lmdb-1.3.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:63cb73fe7ce9eb93d992d632c85a0476b4332670d9e6a2802b5062f603b7809f"}, - {file = "lmdb-1.3.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:abbc439cd9fe60ffd6197009087ea885ac150017dc85384093b1d376f83f0ec4"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6260a526e4ad85b1f374a5ba9475bf369fb07e7728ea6ec57226b02c40d1976b"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e568ae0887ae196340947d9800136e90feaed6b86a261ef01f01b2ba65fc8106"}, - {file = "lmdb-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6a816954d212f40fd15007cd81ab7a6bebb77436d949a6a9ae04af57fc127f3"}, - {file = "lmdb-1.3.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fa6439356e591d3249ab0e1778a6f8d8408e993f66dc911914c78208f5310309"}, - {file = "lmdb-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:c6adbd6f7f9048e97f31a069e652eb51020a81e80a0ce92dbb9810d21da2409a"}, - {file = "lmdb-1.3.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:eefb392f6b5cd43aada49258c5a79be11cb2c8cd3fc3e2d9319a1e0b9f906458"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a14aca2651c3af6f0d0a6b9168200eea0c8f2d27c40b01a442f33329a6e8dff"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfa4aa9c67f8aee89b23005e98d1f3f32490b6b905fd1cb604b207cbd5755ab"}, - {file = "lmdb-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7da05d70fcc6561ac6b09e9fb1bf64b7ca294652c64c8a2889273970cee796b9"}, - {file = "lmdb-1.3.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:008243762decf8f6c90430a9bced56290ebbcdb5e877d90e42343bb97033e494"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:17215a42a4b9814c383deabecb160581e4fb75d00198eef0e3cea54f230ffbea"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65334eafa5d430b18d81ebd5362559a41483c362e1931f6e1b15bab2ecb7d75d"}, - {file = "lmdb-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:18c69fabdaf04efaf246587739cc1062b3e57c6ef0743f5c418df89e5e7e7b9b"}, - {file = "lmdb-1.3.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:41318717ab5d15ad2d6d263d34fbf614a045210f64b25e59ce734bb2105e421f"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:df2724bad7820114a205472994091097d0fa65a3e5fff5a8e688d123fb8c6326"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddd590e1c7fcb395931aa3782fb89b9db4550ab2d81d006ecd239e0d462bc41"}, - {file = "lmdb-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:4172fba19417d7b29409beca7d73c067b54e5d8ab1fb9b51d7b4c1445d20a167"}, - {file = "lmdb-1.3.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2df38115dd9428a54d59ae7c712a4c7cce0d6b1d66056de4b1a8c38718066106"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9103aa4908f0bca43c5911ca067d4e3d01f682dff0c0381a1239bd2bd757984"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:394df860c3f93cfd92b6f4caba785f38208cc9614c18b3803f83a2cc1695042f"}, - {file = "lmdb-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:62ab28e3593bdc318ea2f2fa1574e5fca3b6d1f264686d773ba54a637d4f563b"}, - {file = "lmdb-1.3.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:e6a704b3baced9182836c7f77b769f23856f3a8f62d0282b1bc1feaf81a86712"}, - {file = "lmdb-1.3.0-pp27-pypy_73-win_amd64.whl", hash = "sha256:08f4b5129f4683802569b02581142e415c8dcc0ff07605983ec1b07804cecbad"}, - {file = "lmdb-1.3.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:f291e3f561f58dddf63a92a5a6a4b8af3a0920b6705d35e2f80e52e86ee238a2"}, - {file = "lmdb-1.3.0.tar.gz", hash = "sha256:60a11efc21aaf009d06518996360eed346f6000bfc9de05114374230879f992e"}, -] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] minos-microservice-common = [] minos-microservice-networks = [] +minos-microservice-transactions = [] multidict = [ {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2"}, {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3"}, @@ -954,38 +905,38 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] orjson = [ - {file = "orjson-3.6.7-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:93188a9d6eb566419ad48befa202dfe7cd7a161756444b99c4ec77faea9352a4"}, - {file = "orjson-3.6.7-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:82515226ecb77689a029061552b5df1802b75d861780c401e96ca6bc8495f775"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3af57ffab7848aaec6ba6b9e9b41331250b57bf696f9d502bacdc71a0ebab0ba"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:a7297504d1142e7efa236ffc53f056d73934a993a08646dbcee89fc4308a8fcf"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:5a50cde0dbbde255ce751fd1bca39d00ecd878ba0903c0480961b31984f2fab7"}, - {file = "orjson-3.6.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d21f9a2d1c30e58070f93988db4cad154b9009fafbde238b52c1c760e3607fbe"}, - {file = "orjson-3.6.7-cp310-none-win_amd64.whl", hash = "sha256:e152464c4606b49398afd911777decebcf9749cc8810c5b4199039e1afb0991e"}, - {file = "orjson-3.6.7-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:0a65f3c403f38b0117c6dd8e76e85a7bd51fcd92f06c5598dfeddbc44697d3e5"}, - {file = "orjson-3.6.7-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:6c47cfca18e41f7f37b08ff3e7abf5ada2d0f27b5ade934f05be5fc5bb956e9d"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:63185af814c243fad7a72441e5f98120c9ecddf2675befa486d669fb65539e9b"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2da6fde42182b80b40df2e6ab855c55090ebfa3fcc21c182b7ad1762b61d55c"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:48c5831ec388b4e2682d4ff56d6bfa4a2ef76c963f5e75f4ff4785f9cf338a80"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:913fac5d594ccabf5e8fbac15b9b3bb9c576d537d49eeec9f664e7a64dde4c4b"}, - {file = "orjson-3.6.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:58f244775f20476e5851e7546df109f75160a5178d44257d437ba6d7e562bfe8"}, - {file = "orjson-3.6.7-cp37-none-win_amd64.whl", hash = "sha256:2d5f45c6b85e5f14646df2d32ecd7ff20fcccc71c0ea1155f4d3df8c5299bbb7"}, - {file = "orjson-3.6.7-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:612d242493afeeb2068bc72ff2544aa3b1e627578fcf92edee9daebb5893ffea"}, - {file = "orjson-3.6.7-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:539cdc5067db38db27985e257772d073cd2eb9462d0a41bde96da4e4e60bd99b"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d103b721bbc4f5703f62b3882e638c0b65fcdd48622531c7ffd45047ef8e87c"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb10a20f80e95102dd35dfbc3a22531661b44a09b55236b012a446955846b023"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:bb68d0da349cf8a68971a48ad179434f75256159fe8b0715275d9b49fa23b7a3"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:4a2c7d0a236aaeab7f69c17b7ab4c078874e817da1bfbb9827cb8c73058b3050"}, - {file = "orjson-3.6.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3be045ca3b96119f592904cf34b962969ce97bd7843cbfca084009f6c8d2f268"}, - {file = "orjson-3.6.7-cp38-none-win_amd64.whl", hash = "sha256:bd765c06c359d8a814b90f948538f957fa8a1f55ad1aaffcdc5771996aaea061"}, - {file = "orjson-3.6.7-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7dd9e1e46c0776eee9e0649e3ae9584ea368d96851bcaeba18e217fa5d755283"}, - {file = "orjson-3.6.7-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c4b4f20a1e3df7e7c83717aff0ef4ab69e42ce2fb1f5234682f618153c458406"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7107a5673fd0b05adbb58bf71c1578fc84d662d29c096eb6d998982c8635c221"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a08b6940dd9a98ccf09785890112a0f81eadb4f35b51b9a80736d1725437e22c"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:f5d1648e5a9d1070f3628a69a7c6c17634dbb0caf22f2085eca6910f7427bf1f"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:e6201494e8dff2ce7fd21da4e3f6dfca1a3fed38f9dcefc972f552f6596a7621"}, - {file = "orjson-3.6.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:70d0386abe02879ebaead2f9632dd2acb71000b4721fd8c1a2fb8c031a38d4d5"}, - {file = "orjson-3.6.7-cp39-none-win_amd64.whl", hash = "sha256:d9a3288861bfd26f3511fb4081561ca768674612bac59513cb9081bb61fcc87f"}, - {file = "orjson-3.6.7.tar.gz", hash = "sha256:a4bb62b11289b7620eead2f25695212e9ac77fcfba76f050fa8a540fb5c32401"}, + {file = "orjson-3.6.8-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:3a287a650458de2211db03681b71c3e5cb2212b62f17a39df8ad99fc54855d0f"}, + {file = "orjson-3.6.8-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5204e25c12cea58e524fc82f7c27ed0586f592f777b33075a92ab7b3eb3687c2"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77e8386393add64f959c044e0fb682364fd0e611a6f477aa13f0e6a733bd6a28"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:279f2d2af393fdf8601020744cb206b91b54ad60fb8401e0761819c7bda1f4e4"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:c31c9f389be7906f978ed4192eb58a4b74a37ad60556a0b88ddc47c576697770"}, + {file = "orjson-3.6.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0db5c5a0c5b89f092d52f6e5a3701660a9d6ffa9e2968b3ce17c2bc4f5eb0414"}, + {file = "orjson-3.6.8-cp310-none-win_amd64.whl", hash = "sha256:eb22485847b9a0c4bbedc668df860126ac931edbed1d456cf41a59f3cb961ed8"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:1a5fe569310bc819279bd4d5f2c349910b104ed3207936246dd5d5e0b085e74a"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:ccb356a47ab1067cd3549847e9db1d279a63fe0482d315b3ffd6e7abef35ef77"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab29c069c222248ce302a25855b4e1664f9436e8ae5a131fb0859daf31676d2b"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d2b5e4cba9e774ac011071d9d27760f97f4b8cd46003e971d122e712f971345"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:c311ec504414d22834d5b972a209619925b48263856a11a14d90230f9682d49c"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:a3dfec7950b90fb8d143743503ee53fa06b32e6068bdea792fc866284da3d71d"}, + {file = "orjson-3.6.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b890dbbada2cbb26eb29bd43a848426f007f094bb0758df10dfe7a438e1cb4b4"}, + {file = "orjson-3.6.8-cp37-none-win_amd64.whl", hash = "sha256:9143ae2c52771525be9ad11a7a8cc8e7fd75391b107e7e644a9e0050496f6b4f"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:33a82199fd42f6436f833e210ae5129c922a5c355629356ca7a8e82964da7285"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:90159ea8b9a5a2a98fa33dc7b421cfac4d2ae91ba5e1058f5909e7f059f6b467"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:656fbe15d9ef0733e740d9def78f4fdb4153102f4836ee774a05123499005931"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7be3be6153843e0f01351b1313a5ad4723595427680dac2dfff22a37e652ce02"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:dd24f66b6697ee7424f7da575ec6cbffc8ede441114d53470949cda4d97c6e56"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:b07c780f7345ecf5901356dc21dee0669defc489c38ce7b9ab0f5e008cc0385c"}, + {file = "orjson-3.6.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ea32015a5d8a4ce00d348a0de5dc7040e0ad58f970a8fcbb5713a1eac129e493"}, + {file = "orjson-3.6.8-cp38-none-win_amd64.whl", hash = "sha256:c5a3e382194c838988ec128a26b08aa92044e5e055491cc4056142af0c1c54d7"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:83a8424e857ae1bf53530e88b4eb2f16ca2b489073b924e655f1575cacd7f52a"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:81e1a6a2d67f15007dadacbf9ba5d3d79237e5e33786c028557fe5a2b72f1c9a"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:137b539881c77866eba86ff6a11df910daf2eb9ab8f1acae62f879e83d7c38af"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cbd358f3b3ad539a27e36900e8e7d172d0e1b72ad9dd7d69544dcbc0f067ee7"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:6ab94701542d40b90903ecfc339333f458884979a01cb9268bc662cc67a5f6d8"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:32b6f26593a9eb606b40775826beb0dac152e3d224ea393688fced036045a821"}, + {file = "orjson-3.6.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:afd9e329ebd3418cac3cd747769b1d52daa25fa672bbf414ab59f0e0881b32b9"}, + {file = "orjson-3.6.8-cp39-none-win_amd64.whl", hash = "sha256:0c89b419914d3d1f65a1b0883f377abe42a6e44f6624ba1c63e8846cbfc2fa60"}, + {file = "orjson-3.6.8.tar.gz", hash = "sha256:e19d23741c5de13689bb316abfccea15a19c264e3ec8eb332a5319a583595ace"}, ] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, @@ -996,71 +947,13 @@ pathspec = [ {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, ] platformdirs = [ - {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, - {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] -psycopg2-binary = [ - {file = "psycopg2-binary-2.9.3.tar.gz", hash = "sha256:761df5313dc15da1502b21453642d7599d26be88bff659382f8f9747c7ebea4e"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:539b28661b71da7c0e428692438efbcd048ca21ea81af618d845e06ebfd29478"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e82d38390a03da28c7985b394ec3f56873174e2c88130e6966cb1c946508e65"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57804fc02ca3ce0dbfbef35c4b3a4a774da66d66ea20f4bda601294ad2ea6092"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:083a55275f09a62b8ca4902dd11f4b33075b743cf0d360419e2051a8a5d5ff76"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:0a29729145aaaf1ad8bafe663131890e2111f13416b60e460dae0a96af5905c9"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a79d622f5206d695d7824cbf609a4f5b88ea6d6dab5f7c147fc6d333a8787e4"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:090f3348c0ab2cceb6dfbe6bf721ef61262ddf518cd6cc6ecc7d334996d64efa"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a9e1f75f96ea388fbcef36c70640c4efbe4650658f3d6a2967b4cc70e907352e"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c3ae8e75eb7160851e59adc77b3a19a976e50622e44fd4fd47b8b18208189d42"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-win32.whl", hash = "sha256:7b1e9b80afca7b7a386ef087db614faebbf8839b7f4db5eb107d0f1a53225029"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:8b344adbb9a862de0c635f4f0425b7958bf5a4b927c8594e6e8d261775796d53"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:e847774f8ffd5b398a75bc1c18fbb56564cda3d629fe68fd81971fece2d3c67e"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68641a34023d306be959101b345732360fc2ea4938982309b786f7be1b43a4a1"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3303f8807f342641851578ee7ed1f3efc9802d00a6f83c101d21c608cb864460"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:e3699852e22aa68c10de06524a3721ade969abf382da95884e6a10ff798f9281"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:526ea0378246d9b080148f2d6681229f4b5964543c170dd10bf4faaab6e0d27f"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:b1c8068513f5b158cf7e29c43a77eb34b407db29aca749d3eb9293ee0d3103ca"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:15803fa813ea05bef089fa78835118b5434204f3a17cb9f1e5dbfd0b9deea5af"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:152f09f57417b831418304c7f30d727dc83a12761627bb826951692cc6491e57"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:404224e5fef3b193f892abdbf8961ce20e0b6642886cfe1fe1923f41aaa75c9d"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-win32.whl", hash = "sha256:1f6b813106a3abdf7b03640d36e24669234120c72e91d5cbaeb87c5f7c36c65b"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:2d872e3c9d5d075a2e104540965a1cf898b52274a5923936e5bfddb58c59c7c2"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:10bb90fb4d523a2aa67773d4ff2b833ec00857f5912bafcfd5f5414e45280fb1"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:874a52ecab70af13e899f7847b3e074eeb16ebac5615665db33bce8a1009cf33"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a29b3ca4ec9defec6d42bf5feb36bb5817ba3c0230dd83b4edf4bf02684cd0ae"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:12b11322ea00ad8db8c46f18b7dfc47ae215e4df55b46c67a94b4effbaec7094"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:53293533fcbb94c202b7c800a12c873cfe24599656b341f56e71dd2b557be063"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c381bda330ddf2fccbafab789d83ebc6c53db126e4383e73794c74eedce855ef"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d29409b625a143649d03d0fd7b57e4b92e0ecad9726ba682244b73be91d2fdb"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:183a517a3a63503f70f808b58bfbf962f23d73b6dccddae5aa56152ef2bcb232"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:15c4e4cfa45f5a60599d9cec5f46cd7b1b29d86a6390ec23e8eebaae84e64554"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-win32.whl", hash = "sha256:adf20d9a67e0b6393eac162eb81fb10bc9130a80540f4df7e7355c2dd4af9fba"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:2f9ffd643bc7349eeb664eba8864d9e01f057880f510e4681ba40a6532f93c71"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:def68d7c21984b0f8218e8a15d514f714d96904265164f75f8d3a70f9c295667"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dffc08ca91c9ac09008870c9eb77b00a46b3378719584059c034b8945e26b272"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:280b0bb5cbfe8039205c7981cceb006156a675362a00fe29b16fbc264e242834"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:af9813db73395fb1fc211bac696faea4ca9ef53f32dc0cfa27e4e7cf766dcf24"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:63638d875be8c2784cfc952c9ac34e2b50e43f9f0a0660b65e2a87d656b3116c"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ffb7a888a047696e7f8240d649b43fb3644f14f0ee229077e7f6b9f9081635bd"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0c9d5450c566c80c396b7402895c4369a410cab5a82707b11aee1e624da7d004"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:d1c1b569ecafe3a69380a94e6ae09a4789bbb23666f3d3a08d06bbd2451f5ef1"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8fc53f9af09426a61db9ba357865c77f26076d48669f2e1bb24d85a22fb52307"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-win32.whl", hash = "sha256:6472a178e291b59e7f16ab49ec8b4f3bdada0a879c68d3817ff0963e722a82ce"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:35168209c9d51b145e459e05c31a9eaeffa9a6b0fd61689b48e07464ffd1a83e"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:47133f3f872faf28c1e87d4357220e809dfd3fa7c64295a4a148bcd1e6e34ec9"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91920527dea30175cc02a1099f331aa8c1ba39bf8b7762b7b56cbf54bc5cce42"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887dd9aac71765ac0d0bac1d0d4b4f2c99d5f5c1382d8b770404f0f3d0ce8a39"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:1f14c8b0942714eb3c74e1e71700cbbcb415acbc311c730370e70c578a44a25c"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:7af0dd86ddb2f8af5da57a976d27cd2cd15510518d582b478fbb2292428710b4"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93cd1967a18aa0edd4b95b1dfd554cf15af657cb606280996d393dadc88c3c35"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bda845b664bb6c91446ca9609fc69f7db6c334ec5e4adc87571c34e4f47b7ddb"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:01310cf4cf26db9aea5158c217caa92d291f0500051a6469ac52166e1a16f5b7"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:99485cab9ba0fa9b84f1f9e1fef106f44a46ef6afdeec8885e0b88d0772b49e8"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-win32.whl", hash = "sha256:46f0e0a6b5fa5851bbd9ab1bc805eef362d3a230fbdfbc209f4a236d0a7a990d"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:accfe7e982411da3178ec690baaceaad3c278652998b2c45828aaac66cd8285f"}, -] py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, @@ -1129,8 +1022,8 @@ tomli = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] typing-extensions = [ - {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, - {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, + {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, + {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, ] uvloop = [ {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, diff --git a/packages/plugins/minos-discovery-minos/pyproject.toml b/packages/plugins/minos-discovery-minos/pyproject.toml index 9ee7b064a..4b9c7aad8 100644 --- a/packages/plugins/minos-discovery-minos/pyproject.toml +++ b/packages/plugins/minos-discovery-minos/pyproject.toml @@ -38,6 +38,7 @@ aiohttp = "^3.8.1" [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../../core/minos-microservice-common", develop = true } minos-microservice-networks = { path = "../../core/minos-microservice-networks", develop = true } +minos-microservice-transactions = { path = "../../core/minos-microservice-transactions", develop = true } black = "^22.1" isort = "^5.8.0" pytest = "^6.2.4" diff --git a/packages/plugins/minos-http-aiohttp/poetry.lock b/packages/plugins/minos-http-aiohttp/poetry.lock index 5f54411d9..581ca36eb 100644 --- a/packages/plugins/minos-http-aiohttp/poetry.lock +++ b/packages/plugins/minos-http-aiohttp/poetry.lock @@ -39,21 +39,6 @@ develop = ["aiocontextvars (==0.2.2)", "aiohttp-asgi", "aiohttp (<4)", "async-ti raven = ["raven-aiohttp"] uvloop = ["uvloop (>=0.14,<1)"] -[[package]] -name = "aiopg" -version = "1.3.3" -description = "Postgres integration with asyncio." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -async-timeout = ">=3.0,<5.0" -psycopg2-binary = ">=2.8.4" - -[package.extras] -sa = ["sqlalchemy[postgresql_psycopg2binary] (>=1.3,<1.5)"] - [[package]] name = "aiosignal" version = "1.2.0" @@ -270,14 +255,6 @@ requirements_deprecated_finder = ["pipreqs", "pip-api"] colors = ["colorama (>=0.4.3,<0.5.0)"] plugins = ["setuptools"] -[[package]] -name = "lmdb" -version = "1.3.0" -description = "Universal Python binding for the LMDB 'Lightning' Database" -category = "main" -optional = false -python-versions = "*" - [[package]] name = "mccabe" version = "0.6.1" @@ -288,7 +265,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0.dev1" +version = "0.7.0.dev2" description = "The common core of the Minos Framework" category = "main" optional = false @@ -297,11 +274,9 @@ develop = true [package.dependencies] aiomisc = ">=14.0.3,<15.8.0" -aiopg = "^1.2.1" cached-property = "^1.5.2" dependency-injector = "^4.32.2" fastavro = "^1.4.0" -lmdb = "^1.2.1" orjson = "^3.5.2" PyYAML = ">=5.4.1,<7.0.0" uvloop = "^0.16.0" @@ -312,7 +287,7 @@ url = "../../core/minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0.dev1" +version = "0.7.0.dev2" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -320,15 +295,31 @@ python-versions = "^3.9" develop = true [package.dependencies] -aiopg = "^1.2.1" crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" -psycopg2-binary = "^2.9.3" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" url = "../../core/minos-microservice-networks" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" + +[package.source] +type = "directory" +url = "../../core/minos-microservice-transactions" + [[package]] name = "multidict" version = "6.0.2" @@ -347,7 +338,7 @@ python-versions = "*" [[package]] name = "orjson" -version = "3.6.7" +version = "3.6.8" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" category = "main" optional = false @@ -374,15 +365,15 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] name = "platformdirs" -version = "2.5.1" +version = "2.5.2" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] +test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] [[package]] name = "pluggy" @@ -396,14 +387,6 @@ python-versions = ">=3.6" dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "psycopg2-binary" -version = "2.9.3" -description = "psycopg2 - Python-PostgreSQL Database Adapter" -category = "main" -optional = false -python-versions = ">=3.6" - [[package]] name = "py" version = "1.11.0" @@ -494,11 +477,11 @@ python-versions = ">=3.7" [[package]] name = "typing-extensions" -version = "4.1.1" -description = "Backported and Experimental Type Hints for Python 3.6+" +version = "4.2.0" +description = "Backported and Experimental Type Hints for Python 3.7+" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "uvloop" @@ -528,7 +511,7 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "9ed872e521aee3a92c874dfb20d4f7c6eed8c1f252ef22657578b97ea0ad0d03" +content-hash = "b474cffe1c1adede8696b85d45653354c34f3d84531cc07027980d5f894af707" [metadata.files] aiohttp = [ @@ -609,10 +592,6 @@ aiomisc = [ {file = "aiomisc-15.7.3-py3-none-any.whl", hash = "sha256:0403e83268e98d0f2a125a70d13303fe1a2358e36db3daf02df032c7fa4f1525"}, {file = "aiomisc-15.7.3.tar.gz", hash = "sha256:ba250a34bd4609ced36111cb50580f57c3d52f3955f953a53ecb2986988baedc"}, ] -aiopg = [ - {file = "aiopg-1.3.3-py3-none-any.whl", hash = "sha256:2842dd8741460eeef940032dcb577bfba4d4115205dd82a73ce13b3271f5bf0a"}, - {file = "aiopg-1.3.3.tar.gz", hash = "sha256:547c6ba4ea0d73c2a11a2f44387d7133cc01d3c6f3b8ed976c0ac1eff4f595d7"}, -] aiosignal = [ {file = "aiosignal-1.2.0-py3-none-any.whl", hash = "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a"}, {file = "aiosignal-1.2.0.tar.gz", hash = "sha256:78ed67db6c7b7ced4f98e495e572106d5c432a93e1ddd1bf475e1dc05f5b7df2"}, @@ -853,41 +832,13 @@ isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] -lmdb = [ - {file = "lmdb-1.3.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:63cb73fe7ce9eb93d992d632c85a0476b4332670d9e6a2802b5062f603b7809f"}, - {file = "lmdb-1.3.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:abbc439cd9fe60ffd6197009087ea885ac150017dc85384093b1d376f83f0ec4"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6260a526e4ad85b1f374a5ba9475bf369fb07e7728ea6ec57226b02c40d1976b"}, - {file = "lmdb-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e568ae0887ae196340947d9800136e90feaed6b86a261ef01f01b2ba65fc8106"}, - {file = "lmdb-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6a816954d212f40fd15007cd81ab7a6bebb77436d949a6a9ae04af57fc127f3"}, - {file = "lmdb-1.3.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fa6439356e591d3249ab0e1778a6f8d8408e993f66dc911914c78208f5310309"}, - {file = "lmdb-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:c6adbd6f7f9048e97f31a069e652eb51020a81e80a0ce92dbb9810d21da2409a"}, - {file = "lmdb-1.3.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:eefb392f6b5cd43aada49258c5a79be11cb2c8cd3fc3e2d9319a1e0b9f906458"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a14aca2651c3af6f0d0a6b9168200eea0c8f2d27c40b01a442f33329a6e8dff"}, - {file = "lmdb-1.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfa4aa9c67f8aee89b23005e98d1f3f32490b6b905fd1cb604b207cbd5755ab"}, - {file = "lmdb-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7da05d70fcc6561ac6b09e9fb1bf64b7ca294652c64c8a2889273970cee796b9"}, - {file = "lmdb-1.3.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:008243762decf8f6c90430a9bced56290ebbcdb5e877d90e42343bb97033e494"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:17215a42a4b9814c383deabecb160581e4fb75d00198eef0e3cea54f230ffbea"}, - {file = "lmdb-1.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65334eafa5d430b18d81ebd5362559a41483c362e1931f6e1b15bab2ecb7d75d"}, - {file = "lmdb-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:18c69fabdaf04efaf246587739cc1062b3e57c6ef0743f5c418df89e5e7e7b9b"}, - {file = "lmdb-1.3.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:41318717ab5d15ad2d6d263d34fbf614a045210f64b25e59ce734bb2105e421f"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:df2724bad7820114a205472994091097d0fa65a3e5fff5a8e688d123fb8c6326"}, - {file = "lmdb-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddd590e1c7fcb395931aa3782fb89b9db4550ab2d81d006ecd239e0d462bc41"}, - {file = "lmdb-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:4172fba19417d7b29409beca7d73c067b54e5d8ab1fb9b51d7b4c1445d20a167"}, - {file = "lmdb-1.3.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2df38115dd9428a54d59ae7c712a4c7cce0d6b1d66056de4b1a8c38718066106"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9103aa4908f0bca43c5911ca067d4e3d01f682dff0c0381a1239bd2bd757984"}, - {file = "lmdb-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:394df860c3f93cfd92b6f4caba785f38208cc9614c18b3803f83a2cc1695042f"}, - {file = "lmdb-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:62ab28e3593bdc318ea2f2fa1574e5fca3b6d1f264686d773ba54a637d4f563b"}, - {file = "lmdb-1.3.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:e6a704b3baced9182836c7f77b769f23856f3a8f62d0282b1bc1feaf81a86712"}, - {file = "lmdb-1.3.0-pp27-pypy_73-win_amd64.whl", hash = "sha256:08f4b5129f4683802569b02581142e415c8dcc0ff07605983ec1b07804cecbad"}, - {file = "lmdb-1.3.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:f291e3f561f58dddf63a92a5a6a4b8af3a0920b6705d35e2f80e52e86ee238a2"}, - {file = "lmdb-1.3.0.tar.gz", hash = "sha256:60a11efc21aaf009d06518996360eed346f6000bfc9de05114374230879f992e"}, -] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] minos-microservice-common = [] minos-microservice-networks = [] +minos-microservice-transactions = [] multidict = [ {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2"}, {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3"}, @@ -954,38 +905,38 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] orjson = [ - {file = "orjson-3.6.7-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:93188a9d6eb566419ad48befa202dfe7cd7a161756444b99c4ec77faea9352a4"}, - {file = "orjson-3.6.7-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:82515226ecb77689a029061552b5df1802b75d861780c401e96ca6bc8495f775"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3af57ffab7848aaec6ba6b9e9b41331250b57bf696f9d502bacdc71a0ebab0ba"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:a7297504d1142e7efa236ffc53f056d73934a993a08646dbcee89fc4308a8fcf"}, - {file = "orjson-3.6.7-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:5a50cde0dbbde255ce751fd1bca39d00ecd878ba0903c0480961b31984f2fab7"}, - {file = "orjson-3.6.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d21f9a2d1c30e58070f93988db4cad154b9009fafbde238b52c1c760e3607fbe"}, - {file = "orjson-3.6.7-cp310-none-win_amd64.whl", hash = "sha256:e152464c4606b49398afd911777decebcf9749cc8810c5b4199039e1afb0991e"}, - {file = "orjson-3.6.7-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:0a65f3c403f38b0117c6dd8e76e85a7bd51fcd92f06c5598dfeddbc44697d3e5"}, - {file = "orjson-3.6.7-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:6c47cfca18e41f7f37b08ff3e7abf5ada2d0f27b5ade934f05be5fc5bb956e9d"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:63185af814c243fad7a72441e5f98120c9ecddf2675befa486d669fb65539e9b"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2da6fde42182b80b40df2e6ab855c55090ebfa3fcc21c182b7ad1762b61d55c"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:48c5831ec388b4e2682d4ff56d6bfa4a2ef76c963f5e75f4ff4785f9cf338a80"}, - {file = "orjson-3.6.7-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:913fac5d594ccabf5e8fbac15b9b3bb9c576d537d49eeec9f664e7a64dde4c4b"}, - {file = "orjson-3.6.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:58f244775f20476e5851e7546df109f75160a5178d44257d437ba6d7e562bfe8"}, - {file = "orjson-3.6.7-cp37-none-win_amd64.whl", hash = "sha256:2d5f45c6b85e5f14646df2d32ecd7ff20fcccc71c0ea1155f4d3df8c5299bbb7"}, - {file = "orjson-3.6.7-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:612d242493afeeb2068bc72ff2544aa3b1e627578fcf92edee9daebb5893ffea"}, - {file = "orjson-3.6.7-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:539cdc5067db38db27985e257772d073cd2eb9462d0a41bde96da4e4e60bd99b"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d103b721bbc4f5703f62b3882e638c0b65fcdd48622531c7ffd45047ef8e87c"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb10a20f80e95102dd35dfbc3a22531661b44a09b55236b012a446955846b023"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:bb68d0da349cf8a68971a48ad179434f75256159fe8b0715275d9b49fa23b7a3"}, - {file = "orjson-3.6.7-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:4a2c7d0a236aaeab7f69c17b7ab4c078874e817da1bfbb9827cb8c73058b3050"}, - {file = "orjson-3.6.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3be045ca3b96119f592904cf34b962969ce97bd7843cbfca084009f6c8d2f268"}, - {file = "orjson-3.6.7-cp38-none-win_amd64.whl", hash = "sha256:bd765c06c359d8a814b90f948538f957fa8a1f55ad1aaffcdc5771996aaea061"}, - {file = "orjson-3.6.7-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7dd9e1e46c0776eee9e0649e3ae9584ea368d96851bcaeba18e217fa5d755283"}, - {file = "orjson-3.6.7-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c4b4f20a1e3df7e7c83717aff0ef4ab69e42ce2fb1f5234682f618153c458406"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7107a5673fd0b05adbb58bf71c1578fc84d662d29c096eb6d998982c8635c221"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a08b6940dd9a98ccf09785890112a0f81eadb4f35b51b9a80736d1725437e22c"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:f5d1648e5a9d1070f3628a69a7c6c17634dbb0caf22f2085eca6910f7427bf1f"}, - {file = "orjson-3.6.7-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:e6201494e8dff2ce7fd21da4e3f6dfca1a3fed38f9dcefc972f552f6596a7621"}, - {file = "orjson-3.6.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:70d0386abe02879ebaead2f9632dd2acb71000b4721fd8c1a2fb8c031a38d4d5"}, - {file = "orjson-3.6.7-cp39-none-win_amd64.whl", hash = "sha256:d9a3288861bfd26f3511fb4081561ca768674612bac59513cb9081bb61fcc87f"}, - {file = "orjson-3.6.7.tar.gz", hash = "sha256:a4bb62b11289b7620eead2f25695212e9ac77fcfba76f050fa8a540fb5c32401"}, + {file = "orjson-3.6.8-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:3a287a650458de2211db03681b71c3e5cb2212b62f17a39df8ad99fc54855d0f"}, + {file = "orjson-3.6.8-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5204e25c12cea58e524fc82f7c27ed0586f592f777b33075a92ab7b3eb3687c2"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77e8386393add64f959c044e0fb682364fd0e611a6f477aa13f0e6a733bd6a28"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:279f2d2af393fdf8601020744cb206b91b54ad60fb8401e0761819c7bda1f4e4"}, + {file = "orjson-3.6.8-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:c31c9f389be7906f978ed4192eb58a4b74a37ad60556a0b88ddc47c576697770"}, + {file = "orjson-3.6.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0db5c5a0c5b89f092d52f6e5a3701660a9d6ffa9e2968b3ce17c2bc4f5eb0414"}, + {file = "orjson-3.6.8-cp310-none-win_amd64.whl", hash = "sha256:eb22485847b9a0c4bbedc668df860126ac931edbed1d456cf41a59f3cb961ed8"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:1a5fe569310bc819279bd4d5f2c349910b104ed3207936246dd5d5e0b085e74a"}, + {file = "orjson-3.6.8-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:ccb356a47ab1067cd3549847e9db1d279a63fe0482d315b3ffd6e7abef35ef77"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab29c069c222248ce302a25855b4e1664f9436e8ae5a131fb0859daf31676d2b"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d2b5e4cba9e774ac011071d9d27760f97f4b8cd46003e971d122e712f971345"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:c311ec504414d22834d5b972a209619925b48263856a11a14d90230f9682d49c"}, + {file = "orjson-3.6.8-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:a3dfec7950b90fb8d143743503ee53fa06b32e6068bdea792fc866284da3d71d"}, + {file = "orjson-3.6.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b890dbbada2cbb26eb29bd43a848426f007f094bb0758df10dfe7a438e1cb4b4"}, + {file = "orjson-3.6.8-cp37-none-win_amd64.whl", hash = "sha256:9143ae2c52771525be9ad11a7a8cc8e7fd75391b107e7e644a9e0050496f6b4f"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:33a82199fd42f6436f833e210ae5129c922a5c355629356ca7a8e82964da7285"}, + {file = "orjson-3.6.8-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:90159ea8b9a5a2a98fa33dc7b421cfac4d2ae91ba5e1058f5909e7f059f6b467"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:656fbe15d9ef0733e740d9def78f4fdb4153102f4836ee774a05123499005931"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7be3be6153843e0f01351b1313a5ad4723595427680dac2dfff22a37e652ce02"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:dd24f66b6697ee7424f7da575ec6cbffc8ede441114d53470949cda4d97c6e56"}, + {file = "orjson-3.6.8-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:b07c780f7345ecf5901356dc21dee0669defc489c38ce7b9ab0f5e008cc0385c"}, + {file = "orjson-3.6.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ea32015a5d8a4ce00d348a0de5dc7040e0ad58f970a8fcbb5713a1eac129e493"}, + {file = "orjson-3.6.8-cp38-none-win_amd64.whl", hash = "sha256:c5a3e382194c838988ec128a26b08aa92044e5e055491cc4056142af0c1c54d7"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:83a8424e857ae1bf53530e88b4eb2f16ca2b489073b924e655f1575cacd7f52a"}, + {file = "orjson-3.6.8-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:81e1a6a2d67f15007dadacbf9ba5d3d79237e5e33786c028557fe5a2b72f1c9a"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:137b539881c77866eba86ff6a11df910daf2eb9ab8f1acae62f879e83d7c38af"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cbd358f3b3ad539a27e36900e8e7d172d0e1b72ad9dd7d69544dcbc0f067ee7"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:6ab94701542d40b90903ecfc339333f458884979a01cb9268bc662cc67a5f6d8"}, + {file = "orjson-3.6.8-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:32b6f26593a9eb606b40775826beb0dac152e3d224ea393688fced036045a821"}, + {file = "orjson-3.6.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:afd9e329ebd3418cac3cd747769b1d52daa25fa672bbf414ab59f0e0881b32b9"}, + {file = "orjson-3.6.8-cp39-none-win_amd64.whl", hash = "sha256:0c89b419914d3d1f65a1b0883f377abe42a6e44f6624ba1c63e8846cbfc2fa60"}, + {file = "orjson-3.6.8.tar.gz", hash = "sha256:e19d23741c5de13689bb316abfccea15a19c264e3ec8eb332a5319a583595ace"}, ] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, @@ -996,71 +947,13 @@ pathspec = [ {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, ] platformdirs = [ - {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, - {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] -psycopg2-binary = [ - {file = "psycopg2-binary-2.9.3.tar.gz", hash = "sha256:761df5313dc15da1502b21453642d7599d26be88bff659382f8f9747c7ebea4e"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:539b28661b71da7c0e428692438efbcd048ca21ea81af618d845e06ebfd29478"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e82d38390a03da28c7985b394ec3f56873174e2c88130e6966cb1c946508e65"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57804fc02ca3ce0dbfbef35c4b3a4a774da66d66ea20f4bda601294ad2ea6092"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:083a55275f09a62b8ca4902dd11f4b33075b743cf0d360419e2051a8a5d5ff76"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:0a29729145aaaf1ad8bafe663131890e2111f13416b60e460dae0a96af5905c9"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a79d622f5206d695d7824cbf609a4f5b88ea6d6dab5f7c147fc6d333a8787e4"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:090f3348c0ab2cceb6dfbe6bf721ef61262ddf518cd6cc6ecc7d334996d64efa"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a9e1f75f96ea388fbcef36c70640c4efbe4650658f3d6a2967b4cc70e907352e"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c3ae8e75eb7160851e59adc77b3a19a976e50622e44fd4fd47b8b18208189d42"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-win32.whl", hash = "sha256:7b1e9b80afca7b7a386ef087db614faebbf8839b7f4db5eb107d0f1a53225029"}, - {file = "psycopg2_binary-2.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:8b344adbb9a862de0c635f4f0425b7958bf5a4b927c8594e6e8d261775796d53"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:e847774f8ffd5b398a75bc1c18fbb56564cda3d629fe68fd81971fece2d3c67e"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68641a34023d306be959101b345732360fc2ea4938982309b786f7be1b43a4a1"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3303f8807f342641851578ee7ed1f3efc9802d00a6f83c101d21c608cb864460"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:e3699852e22aa68c10de06524a3721ade969abf382da95884e6a10ff798f9281"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:526ea0378246d9b080148f2d6681229f4b5964543c170dd10bf4faaab6e0d27f"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:b1c8068513f5b158cf7e29c43a77eb34b407db29aca749d3eb9293ee0d3103ca"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:15803fa813ea05bef089fa78835118b5434204f3a17cb9f1e5dbfd0b9deea5af"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:152f09f57417b831418304c7f30d727dc83a12761627bb826951692cc6491e57"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:404224e5fef3b193f892abdbf8961ce20e0b6642886cfe1fe1923f41aaa75c9d"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-win32.whl", hash = "sha256:1f6b813106a3abdf7b03640d36e24669234120c72e91d5cbaeb87c5f7c36c65b"}, - {file = "psycopg2_binary-2.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:2d872e3c9d5d075a2e104540965a1cf898b52274a5923936e5bfddb58c59c7c2"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:10bb90fb4d523a2aa67773d4ff2b833ec00857f5912bafcfd5f5414e45280fb1"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:874a52ecab70af13e899f7847b3e074eeb16ebac5615665db33bce8a1009cf33"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a29b3ca4ec9defec6d42bf5feb36bb5817ba3c0230dd83b4edf4bf02684cd0ae"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:12b11322ea00ad8db8c46f18b7dfc47ae215e4df55b46c67a94b4effbaec7094"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:53293533fcbb94c202b7c800a12c873cfe24599656b341f56e71dd2b557be063"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c381bda330ddf2fccbafab789d83ebc6c53db126e4383e73794c74eedce855ef"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d29409b625a143649d03d0fd7b57e4b92e0ecad9726ba682244b73be91d2fdb"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:183a517a3a63503f70f808b58bfbf962f23d73b6dccddae5aa56152ef2bcb232"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:15c4e4cfa45f5a60599d9cec5f46cd7b1b29d86a6390ec23e8eebaae84e64554"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-win32.whl", hash = "sha256:adf20d9a67e0b6393eac162eb81fb10bc9130a80540f4df7e7355c2dd4af9fba"}, - {file = "psycopg2_binary-2.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:2f9ffd643bc7349eeb664eba8864d9e01f057880f510e4681ba40a6532f93c71"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:def68d7c21984b0f8218e8a15d514f714d96904265164f75f8d3a70f9c295667"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dffc08ca91c9ac09008870c9eb77b00a46b3378719584059c034b8945e26b272"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:280b0bb5cbfe8039205c7981cceb006156a675362a00fe29b16fbc264e242834"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:af9813db73395fb1fc211bac696faea4ca9ef53f32dc0cfa27e4e7cf766dcf24"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:63638d875be8c2784cfc952c9ac34e2b50e43f9f0a0660b65e2a87d656b3116c"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ffb7a888a047696e7f8240d649b43fb3644f14f0ee229077e7f6b9f9081635bd"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0c9d5450c566c80c396b7402895c4369a410cab5a82707b11aee1e624da7d004"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:d1c1b569ecafe3a69380a94e6ae09a4789bbb23666f3d3a08d06bbd2451f5ef1"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8fc53f9af09426a61db9ba357865c77f26076d48669f2e1bb24d85a22fb52307"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-win32.whl", hash = "sha256:6472a178e291b59e7f16ab49ec8b4f3bdada0a879c68d3817ff0963e722a82ce"}, - {file = "psycopg2_binary-2.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:35168209c9d51b145e459e05c31a9eaeffa9a6b0fd61689b48e07464ffd1a83e"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:47133f3f872faf28c1e87d4357220e809dfd3fa7c64295a4a148bcd1e6e34ec9"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91920527dea30175cc02a1099f331aa8c1ba39bf8b7762b7b56cbf54bc5cce42"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887dd9aac71765ac0d0bac1d0d4b4f2c99d5f5c1382d8b770404f0f3d0ce8a39"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:1f14c8b0942714eb3c74e1e71700cbbcb415acbc311c730370e70c578a44a25c"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:7af0dd86ddb2f8af5da57a976d27cd2cd15510518d582b478fbb2292428710b4"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93cd1967a18aa0edd4b95b1dfd554cf15af657cb606280996d393dadc88c3c35"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bda845b664bb6c91446ca9609fc69f7db6c334ec5e4adc87571c34e4f47b7ddb"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:01310cf4cf26db9aea5158c217caa92d291f0500051a6469ac52166e1a16f5b7"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:99485cab9ba0fa9b84f1f9e1fef106f44a46ef6afdeec8885e0b88d0772b49e8"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-win32.whl", hash = "sha256:46f0e0a6b5fa5851bbd9ab1bc805eef362d3a230fbdfbc209f4a236d0a7a990d"}, - {file = "psycopg2_binary-2.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:accfe7e982411da3178ec690baaceaad3c278652998b2c45828aaac66cd8285f"}, -] py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, @@ -1129,8 +1022,8 @@ tomli = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] typing-extensions = [ - {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, - {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, + {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, + {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, ] uvloop = [ {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, diff --git a/packages/plugins/minos-http-aiohttp/pyproject.toml b/packages/plugins/minos-http-aiohttp/pyproject.toml index c8e689ede..93fee942d 100644 --- a/packages/plugins/minos-http-aiohttp/pyproject.toml +++ b/packages/plugins/minos-http-aiohttp/pyproject.toml @@ -40,6 +40,7 @@ cached-property = "^1.5.2" [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../../core/minos-microservice-common", develop = true } minos-microservice-networks = { path = "../../core/minos-microservice-networks", develop = true } +minos-microservice-transactions = { path = "../../core/minos-microservice-transactions", develop = true } black = "^22.1" isort = "^5.8.0" pytest = "^6.2.4" diff --git a/packages/plugins/minos-router-graphql/poetry.lock b/packages/plugins/minos-router-graphql/poetry.lock index 4ab43836d..2768771f3 100644 --- a/packages/plugins/minos-router-graphql/poetry.lock +++ b/packages/plugins/minos-router-graphql/poetry.lock @@ -239,11 +239,29 @@ develop = true [package.dependencies] crontab = "^0.23.0" minos-microservice-common = "^0.7.0*" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" url = "../../core/minos-microservice-networks" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" + +[package.source] +type = "directory" +url = "../../core/minos-microservice-transactions" + [[package]] name = "mypy-extensions" version = "0.4.3" @@ -415,7 +433,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "4e128a7d215b0b372007e4d0eb730675ac7998a38c17ead9ce794683f29a3941" +content-hash = "c808a4854fa5f05df46b18cca262db590d0c0266e446c02129bd4b04e64df044" [metadata.files] aiomisc = [ @@ -595,6 +613,7 @@ mccabe = [ ] minos-microservice-common = [] minos-microservice-networks = [] +minos-microservice-transactions = [] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, diff --git a/packages/plugins/minos-router-graphql/pyproject.toml b/packages/plugins/minos-router-graphql/pyproject.toml index e756b6550..1911e0218 100644 --- a/packages/plugins/minos-router-graphql/pyproject.toml +++ b/packages/plugins/minos-router-graphql/pyproject.toml @@ -38,6 +38,7 @@ graphql-core = "^3.2.0" [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../../core/minos-microservice-common", develop = true } minos-microservice-networks = { path = "../../core/minos-microservice-networks", develop = true } +minos-microservice-transactions = { path = "../../core/minos-microservice-transactions", develop = true } black = "^22.1" isort = "^5.8.0" pytest = "^6.2.4" From a66265292dca5412c13ce7da6490c775736a2c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Fri, 22 Apr 2022 11:01:45 +0200 Subject: [PATCH 23/75] ISSUE #86 * Minor improvements. --- .../minos/aggregate/aggregate.py | 8 ++++++++ .../minos/common/config/v2.py | 6 +++++- .../brokers/publishers/transactional/impl.py | 12 +++++++++++- .../publishers/transactional/repositories/abc.py | 6 +++++- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py index 7db83fd8a..f6ec5f0ed 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py @@ -77,6 +77,14 @@ def _from_config(cls, config: Config, **kwargs) -> Aggregate: kwargs["broker_publisher"] = TransactionalBrokerPublisher.from_config(config, **kwargs) return cls(**kwargs) + async def _setup(self) -> None: + await super()._setup() + await self.broker_publisher.setup() + + async def _destroy(self) -> None: + await self.broker_publisher.destroy() + await super()._destroy() + def _check_root(self): self.root # If root is not valid it will raise an exception. diff --git a/packages/core/minos-microservice-common/minos/common/config/v2.py b/packages/core/minos-microservice-common/minos/common/config/v2.py index 345829d74..04a446aa6 100644 --- a/packages/core/minos-microservice-common/minos/common/config/v2.py +++ b/packages/core/minos-microservice-common/minos/common/config/v2.py @@ -65,6 +65,9 @@ def _get_injections(self) -> list[Union[InjectableMixin, type[InjectableMixin]]] with suppress(MinosConfigException): partial_ans.extend(self._get_aggregate().get("repositories", dict()).values()) + with suppress(MinosConfigException): + partial_ans.append(self._get_aggregate().get("client")) + with suppress(MinosConfigException): partial_ans.append(self._get_discovery().get("connector")) @@ -205,7 +208,8 @@ def _get_discovery(self) -> dict[str, Any]: def _get_aggregate(self) -> dict[str, Any]: data = deepcopy(self.get_by_key("aggregate")) - + if "client" in data: + data["client"] = import_module(data.get("client")) data["entities"] = [import_module(classname) for classname in data.get("entities", list())] data["repositories"] = {name: import_module(value) for name, value in data.get("repositories", dict()).items()} return data diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py index e9a3d23b8..d2b3c5b41 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py @@ -47,9 +47,19 @@ def __init__(self, impl: BrokerPublisher, repository: BrokerPublisherTransaction @classmethod def _from_config(cls, config: Config, **kwargs) -> TransactionalBrokerPublisher: if "repository" not in kwargs: - kwargs["repository"] = InMemoryBrokerPublisherTransactionRepository() + kwargs["repository"] = InMemoryBrokerPublisherTransactionRepository.from_config(config, **kwargs) + if "broker_publisher" in kwargs and "impl" not in kwargs: + kwargs["impl"] = kwargs["broker_publisher"] return cls(**kwargs) + async def _setup(self) -> None: + await super()._setup() + await self.repository.setup() + + async def _destroy(self) -> None: + await self.repository.destroy() + await super()._destroy() + async def _send(self, message: BrokerMessage) -> None: transaction = TRANSACTION_CONTEXT_VAR.get() diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py index fcfc7d643..882af3ce7 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py @@ -9,12 +9,16 @@ UUID, ) +from minos.common import ( + SetupMixin, +) + from ..entries import ( BrokerPublisherTransactionEntry, ) -class BrokerPublisherTransactionRepository(ABC): +class BrokerPublisherTransactionRepository(ABC, SetupMixin): """TODO""" def select(self, transaction_uuid: UUID) -> AsyncIterator[BrokerPublisherTransactionEntry]: From e5d65c29ae607eaeec1590ceb18f50644134c646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Fri, 22 Apr 2022 13:48:51 +0200 Subject: [PATCH 24/75] ISSUE #86 * Minor improvements. (2) --- .../networks/brokers/publishers/transactional/entries.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py index ddb637adb..cd286968e 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py @@ -14,7 +14,9 @@ class BrokerPublisherTransactionEntry: """TODO""" - def __init__(self, message: Union[bytes, BrokerMessage], transaction_uuid: UUID): + def __init__(self, message: Union[memoryview, bytes, BrokerMessage], transaction_uuid: UUID): + if isinstance(message, memoryview): + message = message.tobytes() if isinstance(message, bytes): message = BrokerMessage.from_avro_bytes(message) self._message = message From f268e46147fcde7ad69532acf8f28c291f6398e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 08:53:29 +0200 Subject: [PATCH 25/75] ISSUE #86 * Add support for aggregate's level broker publisher configuration. --- .../minos/aggregate/aggregate.py | 23 +++++++++++++++---- .../minos/common/config/v2.py | 8 +++++++ .../brokers/publishers/transactional/impl.py | 9 ++++++-- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py index f6ec5f0ed..266d27611 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py @@ -16,7 +16,7 @@ SetupMixin, ) from minos.networks import ( - TransactionalBrokerPublisher, + BrokerPublisher, ) from minos.transactions import ( TransactionRepository, @@ -42,7 +42,7 @@ class Aggregate(Generic[RT], SetupMixin): transaction_repository: TransactionRepository event_repository: EventRepository snapshot_repository: SnapshotRepository - broker_publisher: TransactionalBrokerPublisher + broker_publisher: BrokerPublisher @Inject() def __init__( @@ -50,7 +50,7 @@ def __init__( transaction_repository: TransactionRepository, event_repository: EventRepository, snapshot_repository: SnapshotRepository, - broker_publisher: TransactionalBrokerPublisher, + broker_publisher: BrokerPublisher, *args, **kwargs, ): @@ -61,7 +61,7 @@ def __init__( if snapshot_repository is None: raise NotProvidedException(f"A {SnapshotRepository!r} object must be provided.") if broker_publisher is None: - raise NotProvidedException(f"A {TransactionalBrokerPublisher!r} object must be provided.") + raise NotProvidedException(f"A {BrokerPublisher!r} object must be provided.") super().__init__(*args, **kwargs) @@ -74,9 +74,22 @@ def __init__( @classmethod def _from_config(cls, config: Config, **kwargs) -> Aggregate: - kwargs["broker_publisher"] = TransactionalBrokerPublisher.from_config(config, **kwargs) + kwargs["broker_publisher"] = cls._get_broker_publisher_from_config(config, **kwargs) return cls(**kwargs) + @staticmethod + @Inject() + def _get_broker_publisher_from_config( + config: Config, broker_publisher: BrokerPublisher, **kwargs + ) -> BrokerPublisher: + aggregate_config = config.get_aggregate() + + if "broker_publisher" in aggregate_config: + client_cls = aggregate_config["broker_publisher"]["client"] + broker_publisher = client_cls.from_config(config, **(aggregate_config["broker_publisher"] | kwargs)) + + return broker_publisher + async def _setup(self) -> None: await super()._setup() await self.broker_publisher.setup() diff --git a/packages/core/minos-microservice-common/minos/common/config/v2.py b/packages/core/minos-microservice-common/minos/common/config/v2.py index 04a446aa6..9222fc294 100644 --- a/packages/core/minos-microservice-common/minos/common/config/v2.py +++ b/packages/core/minos-microservice-common/minos/common/config/v2.py @@ -210,6 +210,14 @@ def _get_aggregate(self) -> dict[str, Any]: data = deepcopy(self.get_by_key("aggregate")) if "client" in data: data["client"] = import_module(data.get("client")) + if "broker_publisher" in data: + if isinstance(data["broker_publisher"], str): + data["broker_publisher"] = import_module(data.get("broker_publisher")) + if isinstance(data["broker_publisher"], dict): + data["broker_publisher"]["client"] = import_module(data["broker_publisher"]["client"]) + if "repository" in data["broker_publisher"]: + data["broker_publisher"]["repository"] = import_module(data["broker_publisher"]["repository"]) + data["entities"] = [import_module(classname) for classname in data.get("entities", list())] data["repositories"] = {name: import_module(value) for name, value in data.get("repositories", dict()).items()} return data diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py index d2b3c5b41..97ca48c38 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py @@ -27,7 +27,6 @@ ) from .repositories import ( BrokerPublisherTransactionRepository, - InMemoryBrokerPublisherTransactionRepository, ) @@ -47,11 +46,17 @@ def __init__(self, impl: BrokerPublisher, repository: BrokerPublisherTransaction @classmethod def _from_config(cls, config: Config, **kwargs) -> TransactionalBrokerPublisher: if "repository" not in kwargs: - kwargs["repository"] = InMemoryBrokerPublisherTransactionRepository.from_config(config, **kwargs) + kwargs["repository"] = cls._get_repository_from_config(config, **kwargs) if "broker_publisher" in kwargs and "impl" not in kwargs: kwargs["impl"] = kwargs["broker_publisher"] return cls(**kwargs) + @staticmethod + def _get_repository_from_config( + config: Config, repository: type[BrokerPublisherTransactionRepository], **kwargs + ) -> BrokerPublisherTransactionRepository: + return repository.from_config(config, **kwargs) + async def _setup(self) -> None: await super()._setup() await self.repository.setup() From adbc70ed0c619650712cdd3fb3cff5e7e656583e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 09:35:48 +0200 Subject: [PATCH 26/75] ISSUE #86 * Increase coverage. --- .../minos/aggregate/aggregate.py | 6 +++--- .../minos/common/config/v2.py | 12 +++++------- .../minos-microservice-common/tests/config/v2.yml | 4 ++++ .../test_common/test_config/test_v2/test_base.py | 4 ++++ .../test_config/test_v2/test_parameterized.py | 7 +++++++ .../core/minos-microservice-common/tests/utils.py | 5 +++++ .../brokers/publishers/transactional/impl.py | 8 +++++++- 7 files changed, 35 insertions(+), 11 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py index 266d27611..0362911d6 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py @@ -84,9 +84,9 @@ def _get_broker_publisher_from_config( ) -> BrokerPublisher: aggregate_config = config.get_aggregate() - if "broker_publisher" in aggregate_config: - client_cls = aggregate_config["broker_publisher"]["client"] - broker_publisher = client_cls.from_config(config, **(aggregate_config["broker_publisher"] | kwargs)) + if "publisher" in aggregate_config: + client_cls = aggregate_config["publisher"]["client"] + broker_publisher = client_cls.from_config(config, **(aggregate_config["publisher"] | kwargs)) return broker_publisher diff --git a/packages/core/minos-microservice-common/minos/common/config/v2.py b/packages/core/minos-microservice-common/minos/common/config/v2.py index 9222fc294..55e8c3292 100644 --- a/packages/core/minos-microservice-common/minos/common/config/v2.py +++ b/packages/core/minos-microservice-common/minos/common/config/v2.py @@ -210,13 +210,11 @@ def _get_aggregate(self) -> dict[str, Any]: data = deepcopy(self.get_by_key("aggregate")) if "client" in data: data["client"] = import_module(data.get("client")) - if "broker_publisher" in data: - if isinstance(data["broker_publisher"], str): - data["broker_publisher"] = import_module(data.get("broker_publisher")) - if isinstance(data["broker_publisher"], dict): - data["broker_publisher"]["client"] = import_module(data["broker_publisher"]["client"]) - if "repository" in data["broker_publisher"]: - data["broker_publisher"]["repository"] = import_module(data["broker_publisher"]["repository"]) + if "publisher" in data: + if isinstance(data["publisher"], str): + data["publisher"] = import_module(data.get("publisher")) + if isinstance(data["publisher"], dict): + data["publisher"]["client"] = import_module(data["publisher"]["client"]) data["entities"] = [import_module(classname) for classname in data.get("entities", list())] data["repositories"] = {name: import_module(value) for name, value in data.get("repositories", dict()).items()} diff --git a/packages/core/minos-microservice-common/tests/config/v2.yml b/packages/core/minos-microservice-common/tests/config/v2.yml index 5222904d1..0a8e5f1fb 100644 --- a/packages/core/minos-microservice-common/tests/config/v2.yml +++ b/packages/core/minos-microservice-common/tests/config/v2.yml @@ -57,6 +57,10 @@ discovery: saga: manager: tests.utils.FakeSagaManager aggregate: + client: tests.utils.FakeAggregate + publisher: + client: builtins.bytes + foo: bar entities: - builtins.int repositories: diff --git a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py index 163d8b6d5..51e4e398a 100644 --- a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py +++ b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py @@ -11,6 +11,7 @@ ) from tests.utils import ( BASE_PATH, + FakeAggregate, FakeBrokerClientPool, FakeBrokerPort, FakeBrokerPublisher, @@ -40,6 +41,8 @@ def test_is_subclass(self): def test_aggregate(self): expected = { + "client": FakeAggregate, + "publisher": {"client": bytes, "foo": "bar"}, "entities": [int], "repositories": { "event": FakeEventRepository, @@ -64,6 +67,7 @@ def test_injections(self): FakeEventRepository, FakeSnapshotRepository, FakeTransactionRepository, + FakeAggregate, FakeDiscoveryConnector, FakeSagaManager, FakeCustomInjection, diff --git a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py index 742773958..5b3f8968a 100644 --- a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py +++ b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py @@ -7,9 +7,11 @@ from minos.common import ( ConfigV2, PoolFactory, + classname, ) from tests.utils import ( BASE_PATH, + FakeAggregate, FakeBrokerPublisher, FakeBrokerSubscriber, FakeBrokerSubscriberBuilder, @@ -41,12 +43,17 @@ def test_injections_nones(self): FakeEventRepository, FakeSnapshotRepository, FakeTransactionRepository, + FakeAggregate, FakeDiscoveryConnector, FakeSagaManager, FakeCustomInjection, ] self.assertEqual(expected, config.get_injections()) + def test_aggregate_broker_publisher_str(self): + config = ConfigV2(self.file_path, aggregate_publisher=classname(str)) + self.assertEqual(str, config.get_aggregate()["publisher"]) + @mock.patch.dict(os.environ, {"MINOS_DATABASES_DEFAULT_DATABASE": "foo"}) def test_overwrite_with_parameter_priority(self): config = ConfigV2(self.file_path, databases_default_database="bar") diff --git a/packages/core/minos-microservice-common/tests/utils.py b/packages/core/minos-microservice-common/tests/utils.py index 5180a96c9..2208c598a 100644 --- a/packages/core/minos-microservice-common/tests/utils.py +++ b/packages/core/minos-microservice-common/tests/utils.py @@ -195,3 +195,8 @@ class FakeSnapshotRepository: @Injectable("transaction_repository") class FakeTransactionRepository: """For testing purposes.""" + + +@Injectable("aggregate") +class FakeAggregate: + """For testing purposes.""" diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py index 97ca48c38..12cd4f0c6 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py @@ -2,6 +2,9 @@ annotations, ) +from typing import ( + Union, +) from uuid import ( UUID, ) @@ -10,6 +13,7 @@ NULL_UUID, Config, Inject, + import_module, ) from minos.transactions import ( TRANSACTION_CONTEXT_VAR, @@ -53,8 +57,10 @@ def _from_config(cls, config: Config, **kwargs) -> TransactionalBrokerPublisher: @staticmethod def _get_repository_from_config( - config: Config, repository: type[BrokerPublisherTransactionRepository], **kwargs + config: Config, repository: Union[str, type[BrokerPublisherTransactionRepository]], **kwargs ) -> BrokerPublisherTransactionRepository: + if isinstance(repository, str): + repository = import_module(repository) return repository.from_config(config, **kwargs) async def _setup(self) -> None: From 2c7de342c29c08e6e54fbf03d89e387f4217d068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 11:10:22 +0200 Subject: [PATCH 27/75] ISSUE #86 * Add tests for `TransactionalBrokerPublisher`. --- .../publishers/transactional/entries.py | 15 ++ .../brokers/publishers/transactional/impl.py | 6 +- .../test_transactional/__init__.py | 0 .../test_transactional/test_impl.py | 163 ++++++++++++++++++ .../tests/utils.py | 39 +++++ 5 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/__init__.py create mode 100644 packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_impl.py diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py index cd286968e..d1b616008 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py @@ -1,3 +1,6 @@ +from collections.abc import ( + Iterable, +) from typing import ( Any, Union, @@ -38,3 +41,15 @@ def as_raw(self) -> dict[str, Any]: "message": self._message.avro_bytes, "transaction_uuid": self._transaction_uuid, } + + def __eq__(self, other: Any) -> bool: + return isinstance(other, type(self)) and tuple(self) == tuple(other) + + def __hash__(self) -> int: + return hash(tuple(self)) + + def __iter__(self) -> Iterable: + yield from ( + self._message, + self._transaction_uuid, + ) diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py index 12cd4f0c6..5027ad502 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py @@ -49,7 +49,7 @@ def __init__(self, impl: BrokerPublisher, repository: BrokerPublisherTransaction @classmethod def _from_config(cls, config: Config, **kwargs) -> TransactionalBrokerPublisher: - if "repository" not in kwargs: + if "repository" in kwargs: kwargs["repository"] = cls._get_repository_from_config(config, **kwargs) if "broker_publisher" in kwargs and "impl" not in kwargs: kwargs["impl"] = kwargs["broker_publisher"] @@ -61,7 +61,9 @@ def _get_repository_from_config( ) -> BrokerPublisherTransactionRepository: if isinstance(repository, str): repository = import_module(repository) - return repository.from_config(config, **kwargs) + if isinstance(repository, type): + repository = repository.from_config(config, **kwargs) + return repository async def _setup(self) -> None: await super()._setup() diff --git a/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/__init__.py b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_impl.py b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_impl.py new file mode 100644 index 000000000..d2402417c --- /dev/null +++ b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_impl.py @@ -0,0 +1,163 @@ +import unittest +from unittest.mock import ( + AsyncMock, + MagicMock, + call, +) +from uuid import ( + uuid4, +) + +from minos.common import ( + NULL_UUID, + classname, +) +from minos.networks import ( + BrokerMessageV1, + BrokerMessageV1Payload, + BrokerPublisher, + BrokerPublisherTransactionEntry, + InMemoryBrokerPublisher, + InMemoryBrokerPublisherTransactionRepository, + TransactionalBrokerPublisher, +) +from minos.transactions import ( + TRANSACTION_CONTEXT_VAR, + TransactionalMixin, + TransactionEntry, +) +from tests.utils import ( + FakeAsyncIterator, + NetworksTestCase, +) + + +class TestTransactionalBrokerPublisher(NetworksTestCase): + def setUp(self): + super().setUp() + self.impl = InMemoryBrokerPublisher() + self.repository = InMemoryBrokerPublisherTransactionRepository() + + def test_is_subclass(self): + self.assertTrue(issubclass(TransactionalBrokerPublisher, (BrokerPublisher, TransactionalMixin))) + + def test_constructor(self): + publisher = TransactionalBrokerPublisher(self.impl, self.repository) + self.assertEqual(self.impl, publisher.impl) + self.assertEqual(self.repository, publisher.repository) + + def test_from_config(self): + publisher = TransactionalBrokerPublisher.from_config( + self.config, + repository=classname(InMemoryBrokerPublisherTransactionRepository), + broker_publisher=self.impl, + ) + self.assertEqual(self.impl, publisher.impl) + self.assertIsInstance(publisher.repository, InMemoryBrokerPublisherTransactionRepository) + + async def test_send_outside_transaction(self): + send_mock = AsyncMock() + submit_mock = AsyncMock() + self.impl.send = send_mock + self.repository.submit = submit_mock + + message = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + + async with TransactionalBrokerPublisher(self.impl, self.repository) as publisher: + await publisher.send(message) + + self.assertEqual([call(message)], send_mock.call_args_list) + self.assertEqual([], submit_mock.call_args_list) + + async def test_send_inside_transaction(self): + send_mock = AsyncMock() + submit_mock = AsyncMock() + self.impl.send = send_mock + self.repository.submit = submit_mock + + message = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + transaction = TransactionEntry() + + async with TransactionalBrokerPublisher(self.impl, self.repository) as publisher: + token = TRANSACTION_CONTEXT_VAR.set(transaction) + try: + await publisher.send(message) + finally: + TRANSACTION_CONTEXT_VAR.reset(token) + + self.assertEqual([], send_mock.call_args_list) + self.assertEqual([call(BrokerPublisherTransactionEntry(message, transaction.uuid))], submit_mock.call_args_list) + + async def test_commit_transaction_without_destination(self): + m1 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + m2 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + + transaction_uuid = uuid4() + + entries = [ + BrokerPublisherTransactionEntry(m1, transaction_uuid), + BrokerPublisherTransactionEntry(m2, transaction_uuid), + ] + + send_mock = AsyncMock() + select_mock = MagicMock(return_value=FakeAsyncIterator(entries)) + delete_mock = AsyncMock() + self.impl.send = send_mock + self.repository.select = select_mock + self.repository.delete_batch = delete_mock + + async with TransactionalBrokerPublisher(self.impl, self.repository) as publisher: + await publisher.commit_transaction(transaction_uuid, NULL_UUID) + + self.assertEqual([call(m1), call(m2)], send_mock.call_args_list) + self.assertEqual([call(transaction_uuid=transaction_uuid)], select_mock.call_args_list) + self.assertEqual([call(transaction_uuid=transaction_uuid)], delete_mock.call_args_list) + + async def test_commit_transaction_with_destination(self): + m1 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + m2 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + + transaction_uuid = uuid4() + destination_transaction_uuid = uuid4() + entries = [ + BrokerPublisherTransactionEntry(m1, transaction_uuid), + BrokerPublisherTransactionEntry(m2, transaction_uuid), + ] + + send_mock = AsyncMock() + submit_mock = AsyncMock() + select_mock = MagicMock(return_value=FakeAsyncIterator(entries)) + delete_mock = AsyncMock() + self.impl.send = send_mock + self.repository.submit = submit_mock + self.repository.select = select_mock + self.repository.delete_batch = delete_mock + + async with TransactionalBrokerPublisher(self.impl, self.repository) as publisher: + await publisher.commit_transaction(transaction_uuid, destination_transaction_uuid) + + self.assertEqual([], send_mock.call_args_list) + self.assertEqual( + [ + call(BrokerPublisherTransactionEntry(m1, destination_transaction_uuid)), + call(BrokerPublisherTransactionEntry(m2, destination_transaction_uuid)), + ], + submit_mock.call_args_list, + ) + self.assertEqual([call(transaction_uuid=transaction_uuid)], select_mock.call_args_list) + self.assertEqual([call(transaction_uuid=transaction_uuid)], delete_mock.call_args_list) + + async def test_reject_transaction(self): + transaction_uuid = uuid4() + + delete_mock = AsyncMock() + self.repository.delete_batch = delete_mock + + async with TransactionalBrokerPublisher(self.impl, self.repository) as publisher: + await publisher.reject_transaction(transaction_uuid) + + self.assertEqual([call(transaction_uuid=transaction_uuid)], delete_mock.call_args_list) + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/core/minos-microservice-networks/tests/utils.py b/packages/core/minos-microservice-networks/tests/utils.py index d357189ee..d22e08ee5 100644 --- a/packages/core/minos-microservice-networks/tests/utils.py +++ b/packages/core/minos-microservice-networks/tests/utils.py @@ -18,10 +18,14 @@ Any, Callable, Optional, + Union, ) from minos.common import ( DeclarativeModel, + InjectableMixin, + Lock, + LockPool, ) from minos.common.testing import ( MinosTestCase, @@ -35,6 +39,9 @@ enroute, testing, ) +from minos.transactions import ( + InMemoryTransactionRepository, +) BASE_PATH = Path(__file__).parent CONFIG_FILE_PATH = BASE_PATH / "test_config.yml" @@ -46,6 +53,38 @@ class NetworksTestCase(MinosTestCase, ABC): def get_config_file_path(self): return CONFIG_FILE_PATH + def get_injections(self) -> list[Union[InjectableMixin, type[InjectableMixin], str]]: + injections = [ + InMemoryTransactionRepository(lock_pool=FakeLockPool()), + ] + # noinspection PyTypeChecker + return super().get_injections() + injections + + +class FakeLock(Lock): + """For testing purposes.""" + + def __init__(self, key=None, *args, **kwargs): + if key is None: + key = "fake" + super().__init__(key, *args, **kwargs) + + async def acquire(self) -> None: + """For testing purposes.""" + + async def release(self): + """For testing purposes.""" + + +class FakeLockPool(LockPool): + """For testing purposes.""" + + async def _create_instance(self): + return FakeLock() + + async def _destroy_instance(self, instance) -> None: + """For testing purposes.""" + @total_ordering class FakeModel(DeclarativeModel): From d9331d8bb6d7bd50178b2ce4dcb138b77ce283b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 11:35:21 +0200 Subject: [PATCH 28/75] ISSUE #86 * Add tests for `BrokerPublisherTransactionEntry`. --- .../publishers/transactional/entries.py | 3 - .../test_transactional/test_entries.py | 69 +++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_entries.py diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py index d1b616008..9be5d5109 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py @@ -45,9 +45,6 @@ def as_raw(self) -> dict[str, Any]: def __eq__(self, other: Any) -> bool: return isinstance(other, type(self)) and tuple(self) == tuple(other) - def __hash__(self) -> int: - return hash(tuple(self)) - def __iter__(self) -> Iterable: yield from ( self._message, diff --git a/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_entries.py b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_entries.py new file mode 100644 index 000000000..3a1f19c90 --- /dev/null +++ b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_entries.py @@ -0,0 +1,69 @@ +import unittest +from uuid import ( + uuid4, +) + +from minos.networks import ( + BrokerMessageV1, + BrokerMessageV1Payload, + BrokerPublisherTransactionEntry, +) +from tests.utils import ( + NetworksTestCase, +) + + +class TestBrokerPublisherTransactionEntry(NetworksTestCase): + def setUp(self): + super().setUp() + self.transaction_uuid = uuid4() + self.message = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + + def test_is_subclass(self): + self.assertTrue(issubclass(BrokerPublisherTransactionEntry, object)) + + def test_constructor(self): + entry = BrokerPublisherTransactionEntry(self.message, self.transaction_uuid) + self.assertEqual(self.message, entry.message) + self.assertEqual(self.transaction_uuid, entry.transaction_uuid) + + def test_constructor_message_bytes(self): + entry = BrokerPublisherTransactionEntry(self.message.avro_bytes, self.transaction_uuid) + self.assertEqual(self.message, entry.message) + self.assertEqual(self.transaction_uuid, entry.transaction_uuid) + + # noinspection SpellCheckingInspection + def test_constructor_message_memoryview(self): + entry = BrokerPublisherTransactionEntry(memoryview(self.message.avro_bytes), self.transaction_uuid) + self.assertEqual(self.message, entry.message) + self.assertEqual(self.transaction_uuid, entry.transaction_uuid) + + def test_as_raw(self): + entry = BrokerPublisherTransactionEntry(self.message, self.transaction_uuid) + + observed = entry.as_raw() + self.assertEqual({"message", "transaction_uuid"}, observed.keys()) + self.assertEqual(self.message, BrokerMessageV1.from_avro_bytes(observed["message"])) + self.assertEqual(self.transaction_uuid, observed["transaction_uuid"]) + + def test_iter(self): + entry = BrokerPublisherTransactionEntry(self.message, self.transaction_uuid) + self.assertEqual((self.message, self.transaction_uuid), tuple(entry)) + + def test_equal(self): + base = BrokerPublisherTransactionEntry(self.message, self.transaction_uuid) + + one = BrokerPublisherTransactionEntry(self.message, self.transaction_uuid) + self.assertEqual(one, base) + + two = BrokerPublisherTransactionEntry( + BrokerMessageV1("AddFoo", BrokerMessageV1Payload(42)), self.transaction_uuid + ) + self.assertNotEqual(two, base) + + three = BrokerPublisherTransactionEntry(self.message, uuid4()) + self.assertNotEqual(three, base) + + +if __name__ == "__main__": + unittest.main() From 777d73cb038decd317c0699157c696039a738a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 12:07:02 +0200 Subject: [PATCH 29/75] ISSUE #86 * Add tests for `BrokerPublisherTransactionRepository`. --- .../transactional/repositories/abc.py | 15 ++- .../repositories/database/factories.py | 5 +- .../repositories/database/impl.py | 4 +- .../transactional/repositories/memory.py | 14 ++- .../test_repositories/__init__.py | 0 .../test_repositories/test_abc.py | 107 ++++++++++++++++++ .../networks/publishers/transactional.py | 8 +- 7 files changed, 143 insertions(+), 10 deletions(-) create mode 100644 packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/__init__.py create mode 100644 packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_abc.py diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py index 882af3ce7..d286f3ade 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py @@ -5,6 +5,9 @@ from collections.abc import ( AsyncIterator, ) +from typing import ( + Optional, +) from uuid import ( UUID, ) @@ -21,17 +24,19 @@ class BrokerPublisherTransactionRepository(ABC, SetupMixin): """TODO""" - def select(self, transaction_uuid: UUID) -> AsyncIterator[BrokerPublisherTransactionEntry]: + def select( + self, transaction_uuid: Optional[UUID] = None, **kwargs + ) -> AsyncIterator[BrokerPublisherTransactionEntry]: """TODO""" - return self._select(transaction_uuid) + return self._select(transaction_uuid=transaction_uuid, **kwargs) @abstractmethod - def _select(self, transaction_uuid: UUID) -> AsyncIterator[BrokerPublisherTransactionEntry]: + def _select(self, transaction_uuid: Optional[UUID], **kwargs) -> AsyncIterator[BrokerPublisherTransactionEntry]: raise NotImplementedError async def submit(self, entry: BrokerPublisherTransactionEntry) -> None: """TODO""" - await self._submit(entry) + await self._submit(entry=entry) @abstractmethod async def _submit(self, entry: BrokerPublisherTransactionEntry) -> None: @@ -39,7 +44,7 @@ async def _submit(self, entry: BrokerPublisherTransactionEntry) -> None: async def delete_batch(self, transaction_uuid: UUID) -> None: """TODO""" - await self._delete_batch(transaction_uuid) + await self._delete_batch(transaction_uuid=transaction_uuid) @abstractmethod async def _delete_batch(self, transaction_uuid: UUID) -> None: diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py index 7d0a4c2fe..a795c06d7 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py @@ -2,6 +2,9 @@ ABC, abstractmethod, ) +from typing import ( + Optional, +) from uuid import ( UUID, ) @@ -20,7 +23,7 @@ def build_create(self) -> DatabaseOperation: """TODO""" @abstractmethod - def build_query(self, transaction_uuid: UUID) -> DatabaseOperation: + def build_query(self, transaction_uuid: Optional[UUID]) -> DatabaseOperation: """TODO""" @abstractmethod diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py index 929bdccb0..3cc0e7c77 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py @@ -40,7 +40,9 @@ async def _create_table(self) -> None: operation = self.database_operation_factory.build_create() await self.execute_on_database(operation) - async def _select(self, transaction_uuid: UUID) -> AsyncIterator[BrokerPublisherTransactionEntry]: + async def _select( + self, transaction_uuid: Optional[UUID], **kwargs + ) -> AsyncIterator[BrokerPublisherTransactionEntry]: operation = self.database_operation_factory.build_query(transaction_uuid) async for raw in self.execute_on_database_and_fetch_all(operation): yield BrokerPublisherTransactionEntry(*raw) diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py index 90ac18a66..b98af3017 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py @@ -1,8 +1,12 @@ from collections import ( defaultdict, ) +from itertools import ( + chain, +) from typing import ( AsyncIterator, + Optional, ) from uuid import ( UUID, @@ -23,8 +27,14 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._storage = defaultdict(list) - async def _select(self, transaction_uuid: UUID) -> AsyncIterator[BrokerPublisherTransactionEntry]: - for entry in self._storage[transaction_uuid]: + async def _select( + self, transaction_uuid: Optional[UUID], **kwargs + ) -> AsyncIterator[BrokerPublisherTransactionEntry]: + if transaction_uuid is None: + iterable = chain.from_iterable(self._storage.values()) + else: + iterable = self._storage[transaction_uuid] + for entry in iterable: yield entry async def _submit(self, entry: BrokerPublisherTransactionEntry) -> None: diff --git a/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/__init__.py b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_abc.py b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_abc.py new file mode 100644 index 000000000..146dcbd73 --- /dev/null +++ b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_abc.py @@ -0,0 +1,107 @@ +import unittest +from abc import ( + ABC, +) +from typing import ( + AsyncIterator, + Optional, +) +from unittest.mock import ( + AsyncMock, + MagicMock, + call, +) +from uuid import ( + UUID, + uuid4, +) + +from minos.common import ( + SetupMixin, +) +from minos.networks import ( + BrokerMessageV1, + BrokerMessageV1Payload, + BrokerPublisherTransactionEntry, + BrokerPublisherTransactionRepository, +) +from tests.utils import ( + FakeAsyncIterator, + NetworksTestCase, +) + + +class _BrokerPublisherTransactionRepository(BrokerPublisherTransactionRepository): + """For testing purposes.""" + + def _select(self, transaction_uuid: Optional[UUID], **kwargs) -> AsyncIterator[BrokerPublisherTransactionEntry]: + """For testing purposes.""" + + async def _submit(self, entry: BrokerPublisherTransactionEntry) -> None: + """For testing purposes.""" + + async def _delete_batch(self, transaction_uuid: UUID) -> None: + """For testing purposes.""" + + +class TestBrokerPublisherTransactionRepository(NetworksTestCase): + def test_abstract(self): + self.assertTrue(issubclass(BrokerPublisherTransactionRepository, (ABC, SetupMixin))) + + async def test_select(self): + repository = _BrokerPublisherTransactionRepository() + + m1 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + m2 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + + transaction_uuid = uuid4() + entries = [ + BrokerPublisherTransactionEntry(m1, transaction_uuid), + BrokerPublisherTransactionEntry(m2, transaction_uuid), + ] + + mock = MagicMock(return_value=FakeAsyncIterator(entries)) + repository._select = mock + + observed = [entry async for entry in repository.select()] + self.assertEqual(entries, observed) + + self.assertEqual([call(transaction_uuid=None)], mock.call_args_list) + + async def test_select_transaction(self): + repository = _BrokerPublisherTransactionRepository() + transaction_uuid = uuid4() + mock = MagicMock(return_value=FakeAsyncIterator([])) + repository._select = mock + + repository.select(transaction_uuid=transaction_uuid) + + self.assertEqual([call(transaction_uuid=transaction_uuid)], mock.call_args_list) + + async def test_submit(self): + repository = _BrokerPublisherTransactionRepository() + transaction_uuid = uuid4() + + mock = AsyncMock() + repository._submit = mock + + m1 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + entry = BrokerPublisherTransactionEntry(m1, transaction_uuid) + await repository.submit(entry) + + self.assertEqual([call(entry=entry)], mock.call_args_list) + + async def test_delete_batch(self): + repository = _BrokerPublisherTransactionRepository() + transaction_uuid = uuid4() + + mock = AsyncMock() + repository._delete_batch = mock + + await repository.delete_batch(transaction_uuid) + + self.assertEqual([call(transaction_uuid=transaction_uuid)], mock.call_args_list) + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py index 1c4f94f66..7700567c7 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py @@ -1,3 +1,6 @@ +from typing import ( + Optional, +) from uuid import ( UUID, ) @@ -56,8 +59,11 @@ def build_create(self) -> DatabaseOperation: ] ) - def build_query(self, transaction_uuid: UUID) -> DatabaseOperation: + def build_query(self, transaction_uuid: Optional[UUID]) -> DatabaseOperation: """TODO""" + if transaction_uuid is None: + return AiopgDatabaseOperation(SQL(f"SELECT message, transaction_uuid FROM {self.build_table_name()}")) + return AiopgDatabaseOperation( SQL( f""" From 7c6408a08f8d383ef083cbb878a95034a316c6ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 12:33:21 +0200 Subject: [PATCH 30/75] ISSUE #86 * Add tests for `InMemoryBrokerPublisherTransactionRepository`. --- .../minos/networks/testing/__init__.py | 1 + .../networks/testing/brokers/__init__.py | 1 + .../testing/brokers/publishers/__init__.py | 3 + .../brokers/publishers/transactions.py | 87 +++++++++++++++++++ .../test_repositories/test_memory.py | 23 +++++ 5 files changed, 115 insertions(+) create mode 100644 packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/transactions.py create mode 100644 packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_memory.py diff --git a/packages/core/minos-microservice-networks/minos/networks/testing/__init__.py b/packages/core/minos-microservice-networks/minos/networks/testing/__init__.py index 451f42047..74c8e7b3a 100644 --- a/packages/core/minos-microservice-networks/minos/networks/testing/__init__.py +++ b/packages/core/minos-microservice-networks/minos/networks/testing/__init__.py @@ -1,4 +1,5 @@ from .brokers import ( + BrokerPublisherTransactionRepositoryTestCase, MockedBrokerPublisherQueueDatabaseOperationFactory, MockedBrokerQueueDatabaseOperationFactory, MockedBrokerSubscriberDuplicateValidatorDatabaseOperationFactory, diff --git a/packages/core/minos-microservice-networks/minos/networks/testing/brokers/__init__.py b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/__init__.py index 8d6486131..c9a450c9e 100644 --- a/packages/core/minos-microservice-networks/minos/networks/testing/brokers/__init__.py +++ b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/__init__.py @@ -2,6 +2,7 @@ MockedBrokerQueueDatabaseOperationFactory, ) from .publishers import ( + BrokerPublisherTransactionRepositoryTestCase, MockedBrokerPublisherQueueDatabaseOperationFactory, ) from .subscribers import ( diff --git a/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/__init__.py b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/__init__.py index 3100d864b..8b042b17f 100644 --- a/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/__init__.py +++ b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/__init__.py @@ -1,3 +1,6 @@ from .queues import ( MockedBrokerPublisherQueueDatabaseOperationFactory, ) +from .transactions import ( + BrokerPublisherTransactionRepositoryTestCase, +) diff --git a/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/transactions.py b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/transactions.py new file mode 100644 index 000000000..b2a040a28 --- /dev/null +++ b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/transactions.py @@ -0,0 +1,87 @@ +from abc import ( + abstractmethod, +) +from uuid import ( + uuid4, +) + +from minos.common.testing import ( + MinosTestCase, +) +from minos.networks import ( + BrokerMessageV1, + BrokerMessageV1Payload, + BrokerPublisherTransactionEntry, + BrokerPublisherTransactionRepository, +) + + +class BrokerPublisherTransactionRepositoryTestCase(MinosTestCase): + __test__ = False + + def setUp(self): + super().setUp() + self.repository = self.build_repository() + + async def asyncSetUp(self): + await super().asyncSetUp() + await self.repository.setup() + + async def asyncTearDown(self): + await self.repository.destroy() + await super().asyncTearDown() + + def test_is_subclass(self): + self.assertIsInstance(self.repository, BrokerPublisherTransactionRepository) + + @abstractmethod + def build_repository(self) -> BrokerPublisherTransactionRepository: + raise NotImplementedError + + async def populate(self) -> None: + m1 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + m2 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + m3 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + + self.transaction_uuid_1 = uuid4() + self.transaction_uuid_2 = uuid4() + self.entries = [ + BrokerPublisherTransactionEntry(m1, self.transaction_uuid_1), + BrokerPublisherTransactionEntry(m2, self.transaction_uuid_1), + BrokerPublisherTransactionEntry(m3, self.transaction_uuid_2), + ] + + for entry in self.entries: + await self.repository.submit(entry) + + async def test_submit(self): + message = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) + transaction_uuid = uuid4() + entry = BrokerPublisherTransactionEntry(message, transaction_uuid) + await self.repository.submit(entry) + + observed = [entry async for entry in self.repository.select(transaction_uuid)] + + self.assertEqual([entry], observed) + + async def test_select_all(self): + await self.populate() + + observed = [entry async for entry in self.repository.select()] + + self.assertEqual(self.entries, observed) + + async def test_select_transaction(self): + await self.populate() + + observed = [entry async for entry in self.repository.select(self.transaction_uuid_1)] + + self.assertEqual([self.entries[0], self.entries[1]], observed) + + async def test_delete(self): + await self.populate() + + await self.repository.delete_batch(self.transaction_uuid_2) + observed = [entry async for entry in self.repository.select()] + + self.assertEqual([self.entries[0], self.entries[1]], observed) diff --git a/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_memory.py b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_memory.py new file mode 100644 index 000000000..ff2bba8eb --- /dev/null +++ b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_memory.py @@ -0,0 +1,23 @@ +import unittest + +from minos.networks import ( + BrokerPublisherTransactionRepository, + InMemoryBrokerPublisherTransactionRepository, +) +from minos.networks.testing import ( + BrokerPublisherTransactionRepositoryTestCase, +) +from tests.utils import ( + NetworksTestCase, +) + + +class TestInMemoryBrokerPublisherTransactionRepository(NetworksTestCase, BrokerPublisherTransactionRepositoryTestCase): + __test__ = True + + def build_repository(self) -> BrokerPublisherTransactionRepository: + return InMemoryBrokerPublisherTransactionRepository.from_config(self.config) + + +if __name__ == "__main__": + unittest.main() From e6e44209c92925e2a9f64511f4ee8b30b4cebd28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 12:59:10 +0200 Subject: [PATCH 31/75] ISSUE #86 * Add tests for `DatabaseBrokerPublisherTransactionRepository`. * Add tests for `BrokerPublisherTransactionDatabaseOperationFactory`. --- .../minos/networks/testing/__init__.py | 1 + .../networks/testing/brokers/__init__.py | 1 + .../testing/brokers/publishers/__init__.py | 1 + .../brokers/publishers/transactions.py | 69 +++++++++++++---- .../test_database/__init__.py | 0 .../test_database/test_factories.py | 26 +++++++ .../test_database/test_impl.py | 74 +++++++++++++++++++ 7 files changed, 156 insertions(+), 16 deletions(-) create mode 100644 packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_database/__init__.py create mode 100644 packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_database/test_factories.py create mode 100644 packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_database/test_impl.py diff --git a/packages/core/minos-microservice-networks/minos/networks/testing/__init__.py b/packages/core/minos-microservice-networks/minos/networks/testing/__init__.py index 74c8e7b3a..a158e6f11 100644 --- a/packages/core/minos-microservice-networks/minos/networks/testing/__init__.py +++ b/packages/core/minos-microservice-networks/minos/networks/testing/__init__.py @@ -1,6 +1,7 @@ from .brokers import ( BrokerPublisherTransactionRepositoryTestCase, MockedBrokerPublisherQueueDatabaseOperationFactory, + MockedBrokerPublisherTransactionDatabaseOperationFactory, MockedBrokerQueueDatabaseOperationFactory, MockedBrokerSubscriberDuplicateValidatorDatabaseOperationFactory, MockedBrokerSubscriberQueueDatabaseOperationFactory, diff --git a/packages/core/minos-microservice-networks/minos/networks/testing/brokers/__init__.py b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/__init__.py index c9a450c9e..7001cdf8e 100644 --- a/packages/core/minos-microservice-networks/minos/networks/testing/brokers/__init__.py +++ b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/__init__.py @@ -4,6 +4,7 @@ from .publishers import ( BrokerPublisherTransactionRepositoryTestCase, MockedBrokerPublisherQueueDatabaseOperationFactory, + MockedBrokerPublisherTransactionDatabaseOperationFactory, ) from .subscribers import ( MockedBrokerSubscriberDuplicateValidatorDatabaseOperationFactory, diff --git a/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/__init__.py b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/__init__.py index 8b042b17f..f3c18e750 100644 --- a/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/__init__.py +++ b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/__init__.py @@ -3,4 +3,5 @@ ) from .transactions import ( BrokerPublisherTransactionRepositoryTestCase, + MockedBrokerPublisherTransactionDatabaseOperationFactory, ) diff --git a/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/transactions.py b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/transactions.py index b2a040a28..c9e594527 100644 --- a/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/transactions.py +++ b/packages/core/minos-microservice-networks/minos/networks/testing/brokers/publishers/transactions.py @@ -1,21 +1,57 @@ from abc import ( abstractmethod, ) +from typing import ( + Optional, +) from uuid import ( + UUID, uuid4, ) +from minos.common import ( + DatabaseOperation, +) from minos.common.testing import ( MinosTestCase, + MockedDatabaseClient, + MockedDatabaseOperation, ) -from minos.networks import ( + +from ....brokers import ( BrokerMessageV1, BrokerMessageV1Payload, + BrokerPublisherTransactionDatabaseOperationFactory, BrokerPublisherTransactionEntry, BrokerPublisherTransactionRepository, ) +class MockedBrokerPublisherTransactionDatabaseOperationFactory(BrokerPublisherTransactionDatabaseOperationFactory): + """For testing purposes""" + + def build_create(self) -> DatabaseOperation: + """For testing purposes""" + return MockedDatabaseOperation("create") + + def build_query(self, transaction_uuid: Optional[UUID]) -> DatabaseOperation: + """For testing purposes""" + return MockedDatabaseOperation("query") + + def build_submit(self, message: bytes, transaction_uuid: UUID) -> DatabaseOperation: + """For testing purposes""" + return MockedDatabaseOperation("submit") + + def build_delete_batch(self, transaction_uuid: UUID) -> DatabaseOperation: + """For testing purposes""" + return MockedDatabaseOperation("delete_batch") + + +MockedDatabaseClient.set_factory( + BrokerPublisherTransactionDatabaseOperationFactory, MockedBrokerPublisherTransactionDatabaseOperationFactory +) + + class BrokerPublisherTransactionRepositoryTestCase(MinosTestCase): __test__ = False @@ -23,6 +59,20 @@ def setUp(self): super().setUp() self.repository = self.build_repository() + self.transaction_uuid_1 = uuid4() + self.transaction_uuid_2 = uuid4() + self.entries = [ + BrokerPublisherTransactionEntry( + BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)), self.transaction_uuid_1 + ), + BrokerPublisherTransactionEntry( + BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)), self.transaction_uuid_1 + ), + BrokerPublisherTransactionEntry( + BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)), self.transaction_uuid_2 + ), + ] + async def asyncSetUp(self): await super().asyncSetUp() await self.repository.setup() @@ -39,28 +89,15 @@ def build_repository(self) -> BrokerPublisherTransactionRepository: raise NotImplementedError async def populate(self) -> None: - m1 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) - m2 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) - m3 = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) - - self.transaction_uuid_1 = uuid4() - self.transaction_uuid_2 = uuid4() - self.entries = [ - BrokerPublisherTransactionEntry(m1, self.transaction_uuid_1), - BrokerPublisherTransactionEntry(m2, self.transaction_uuid_1), - BrokerPublisherTransactionEntry(m3, self.transaction_uuid_2), - ] for entry in self.entries: await self.repository.submit(entry) async def test_submit(self): - message = BrokerMessageV1("AddFoo", BrokerMessageV1Payload(56)) - transaction_uuid = uuid4() - entry = BrokerPublisherTransactionEntry(message, transaction_uuid) + entry = self.entries[0] await self.repository.submit(entry) - observed = [entry async for entry in self.repository.select(transaction_uuid)] + observed = [entry async for entry in self.repository.select(entry.transaction_uuid)] self.assertEqual([entry], observed) diff --git a/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_database/__init__.py b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_database/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_database/test_factories.py b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_database/test_factories.py new file mode 100644 index 000000000..2dba5668a --- /dev/null +++ b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_database/test_factories.py @@ -0,0 +1,26 @@ +import unittest +from abc import ( + ABC, +) + +from minos.common import ( + DatabaseOperationFactory, +) +from minos.networks import ( + BrokerPublisherTransactionDatabaseOperationFactory, +) + + +class TestBrokerPublisherTransactionDatabaseOperationFactory(unittest.IsolatedAsyncioTestCase): + def test_abstract(self): + self.assertTrue(issubclass(BrokerPublisherTransactionDatabaseOperationFactory, (DatabaseOperationFactory, ABC))) + + # noinspection PyUnresolvedReferences + self.assertEqual( + {"build_submit", "build_delete_batch", "build_create", "build_query"}, + BrokerPublisherTransactionDatabaseOperationFactory.__abstractmethods__, + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_database/test_impl.py b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_database/test_impl.py new file mode 100644 index 000000000..0728779fe --- /dev/null +++ b/packages/core/minos-microservice-networks/tests/test_networks/test_brokers/test_publishers/test_transactional/test_repositories/test_database/test_impl.py @@ -0,0 +1,74 @@ +import unittest +from unittest.mock import ( + patch, +) + +from minos.common import ( + DatabaseClient, +) +from minos.common.testing import ( + DatabaseMinosTestCase, +) +from minos.networks import ( + BrokerPublisherTransactionRepository, + DatabaseBrokerPublisherTransactionRepository, +) +from minos.networks.testing import ( + BrokerPublisherTransactionRepositoryTestCase, +) +from tests.utils import ( + FakeAsyncIterator, + NetworksTestCase, +) + + +class TestDatabaseBrokerPublisherTransactionRepository( + NetworksTestCase, DatabaseMinosTestCase, BrokerPublisherTransactionRepositoryTestCase +): + __test__ = True + + def build_repository(self) -> BrokerPublisherTransactionRepository: + return DatabaseBrokerPublisherTransactionRepository.from_config(self.config) + + async def populate(self) -> None: + await super().populate() + + async def test_submit(self): + iterator = FakeAsyncIterator([(self.entries[0].message, self.entries[0].transaction_uuid)]) + with patch.object(DatabaseClient, "fetch_all", return_value=iterator): + await super().test_submit() + + async def test_select_all(self): + iterator = FakeAsyncIterator( + [ + (self.entries[0].message, self.entries[0].transaction_uuid), + (self.entries[1].message, self.entries[1].transaction_uuid), + (self.entries[2].message, self.entries[2].transaction_uuid), + ] + ) + with patch.object(DatabaseClient, "fetch_all", return_value=iterator): + await super().test_select_all() + + async def test_select_transaction(self): + iterator = FakeAsyncIterator( + [ + (self.entries[0].message, self.entries[0].transaction_uuid), + (self.entries[1].message, self.entries[1].transaction_uuid), + ] + ) + with patch.object(DatabaseClient, "fetch_all", return_value=iterator): + await super().test_select_transaction() + + async def test_delete(self): + iterator = FakeAsyncIterator( + [ + (self.entries[0].message, self.entries[0].transaction_uuid), + (self.entries[1].message, self.entries[1].transaction_uuid), + ] + ) + with patch.object(DatabaseClient, "fetch_all", return_value=iterator): + await super().test_delete() + + +if __name__ == "__main__": + unittest.main() From 223f6366c64c2c33f45fe14b69cda1e52a0c1d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 13:02:10 +0200 Subject: [PATCH 32/75] ISSUE #86 * Rename file. --- .../minos-microservice-aggregate/minos/aggregate/__init__.py | 2 +- .../minos/aggregate/{aggregate.py => impl.py} | 0 .../tests/test_aggregate/{test_aggregate.py => test_impl.py} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename packages/core/minos-microservice-aggregate/minos/aggregate/{aggregate.py => impl.py} (100%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/{test_aggregate.py => test_impl.py} (100%) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py index 28f9a0688..612425c69 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py @@ -7,7 +7,7 @@ from .actions import ( Action, ) -from .aggregate import ( +from .impl import ( Aggregate, ) from .collections import ( diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py similarity index 100% rename from packages/core/minos-microservice-aggregate/minos/aggregate/aggregate.py rename to packages/core/minos-microservice-aggregate/minos/aggregate/impl.py diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_aggregate.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_aggregate.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py From ffdd6835131259cdfd202324678e6b5d89bc8dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 13:13:31 +0200 Subject: [PATCH 33/75] ISSUE #86 * Increase coverage of the `Aggregate` class. --- .../minos/aggregate/__init__.py | 6 ++--- .../minos/aggregate/impl.py | 5 ++-- .../tests/test_aggregate/test_impl.py | 25 ++++++++++++++++--- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py index 612425c69..208e00597 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py @@ -7,9 +7,6 @@ from .actions import ( Action, ) -from .impl import ( - Aggregate, -) from .collections import ( IncrementalSet, IncrementalSetDiff, @@ -50,6 +47,9 @@ SnapshotRepositoryException, ValueObjectException, ) +from .impl import ( + Aggregate, +) from .queries import ( Condition, Ordering, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py index 0362911d6..89b42393a 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py @@ -85,8 +85,9 @@ def _get_broker_publisher_from_config( aggregate_config = config.get_aggregate() if "publisher" in aggregate_config: - client_cls = aggregate_config["publisher"]["client"] - broker_publisher = client_cls.from_config(config, **(aggregate_config["publisher"] | kwargs)) + publisher_config = aggregate_config["publisher"] + client_cls = publisher_config.pop("client") + broker_publisher = client_cls.from_config(config, **(publisher_config | kwargs)) return broker_publisher diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py index b40b46a90..406cd23f4 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py @@ -1,4 +1,7 @@ import unittest +from unittest.mock import ( + patch, +) from uuid import ( UUID, ) @@ -7,8 +10,12 @@ Aggregate, ) from minos.common import ( + Config, NotProvidedException, ) +from minos.networks import ( + InMemoryBrokerPublisher, +) from tests.utils import ( CONFIG_FILE_PATH, AggregateTestCase, @@ -28,9 +35,19 @@ def test_root_raises(self): async def test_from_config(self): async with OrderAggregate.from_config(CONFIG_FILE_PATH) as aggregate: - self.assertTrue(self.transaction_repository, aggregate.transaction_repository) - self.assertTrue(self.event_repository, aggregate.event_repository) - self.assertTrue(self.snapshot_repository, aggregate.snapshot_repository) + self.assertEqual(self.transaction_repository, aggregate.transaction_repository) + self.assertEqual(self.event_repository, aggregate.event_repository) + self.assertEqual(self.snapshot_repository, aggregate.snapshot_repository) + self.assertEqual(self.broker_publisher, aggregate.broker_publisher) + + async def test_from_config_with_custom_publisher(self): + with patch.object(Config, "get_aggregate", return_value={"publisher": {"client": InMemoryBrokerPublisher}}): + async with OrderAggregate.from_config(CONFIG_FILE_PATH) as aggregate: + self.assertEqual(self.transaction_repository, aggregate.transaction_repository) + self.assertEqual(self.event_repository, aggregate.event_repository) + self.assertEqual(self.snapshot_repository, aggregate.snapshot_repository) + self.assertIsInstance(aggregate.broker_publisher, InMemoryBrokerPublisher) + self.assertNotEqual(self.broker_publisher, aggregate.broker_publisher) def test_from_config_raises(self): with self.assertRaises(NotProvidedException): @@ -39,6 +56,8 @@ def test_from_config_raises(self): OrderAggregate.from_config(CONFIG_FILE_PATH, event_repository=None) with self.assertRaises(NotProvidedException): OrderAggregate.from_config(CONFIG_FILE_PATH, snapshot_repository=None) + with self.assertRaises(NotProvidedException): + OrderAggregate.from_config(CONFIG_FILE_PATH, broker_publisher=None) async def test_call(self): async with OrderAggregate.from_config(CONFIG_FILE_PATH) as aggregate: From e6af9f0f9e8b8178f93dcda2b0b3c1693d936427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 13:27:43 +0200 Subject: [PATCH 34/75] ISSUE #86 * Add tests for `AiopgBrokerPublisherTransactionDatabaseOperationFactory`. --- .../test_transactions/__init__.py | 0 .../test_transactions/test_factory.py | 60 +++++++++++++++++++ .../test_transactions/test_repository.py | 24 ++++++++ 3 files changed, 84 insertions(+) create mode 100644 packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_networks/test_publishers/test_transactions/__init__.py create mode 100644 packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_networks/test_publishers/test_transactions/test_factory.py create mode 100644 packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_networks/test_publishers/test_transactions/test_repository.py diff --git a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_networks/test_publishers/test_transactions/__init__.py b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_networks/test_publishers/test_transactions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_networks/test_publishers/test_transactions/test_factory.py b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_networks/test_publishers/test_transactions/test_factory.py new file mode 100644 index 000000000..d6eba73b3 --- /dev/null +++ b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_networks/test_publishers/test_transactions/test_factory.py @@ -0,0 +1,60 @@ +import unittest +from uuid import ( + uuid4, +) + +from minos.common import ( + ComposedDatabaseOperation, +) +from minos.networks import ( + BrokerPublisherTransactionDatabaseOperationFactory, +) +from minos.plugins.aiopg import ( + AiopgBrokerPublisherTransactionDatabaseOperationFactory, + AiopgDatabaseOperation, +) + + +# noinspection SqlNoDataSourceInspection +class TestBrokerPublisherTransactionRepositoryTestCase(unittest.IsolatedAsyncioTestCase): + def setUp(self) -> None: + self.factory = AiopgBrokerPublisherTransactionDatabaseOperationFactory() + + def test_is_subclass(self): + self.assertTrue( + issubclass( + AiopgBrokerPublisherTransactionDatabaseOperationFactory, + BrokerPublisherTransactionDatabaseOperationFactory, + ) + ) + + def test_table_name(self): + observed = self.factory.build_table_name() + self.assertEqual("broker_publisher_transactional_messages", observed) + + def test_create(self): + observed = self.factory.build_create() + self.assertIsInstance(observed, ComposedDatabaseOperation) + self.assertEqual(2, len(observed.operations)) + for operation in observed.operations: + self.assertIsInstance(operation, AiopgDatabaseOperation) + + def test_build_query(self): + observed = self.factory.build_query(uuid4()) + self.assertIsInstance(observed, AiopgDatabaseOperation) + + def test_build_query_all(self): + observed = self.factory.build_query(None) + self.assertIsInstance(observed, AiopgDatabaseOperation) + + def test_submit(self): + observed = self.factory.build_submit(bytes(), uuid4()) + self.assertIsInstance(observed, AiopgDatabaseOperation) + + def test_delete_batch(self): + observed = self.factory.build_delete_batch(uuid4()) + self.assertIsInstance(observed, AiopgDatabaseOperation) + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_networks/test_publishers/test_transactions/test_repository.py b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_networks/test_publishers/test_transactions/test_repository.py new file mode 100644 index 000000000..80cbadaea --- /dev/null +++ b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_networks/test_publishers/test_transactions/test_repository.py @@ -0,0 +1,24 @@ +import unittest + +from minos.networks import ( + BrokerPublisherTransactionRepository, + DatabaseBrokerPublisherTransactionRepository, +) +from minos.networks.testing import ( + BrokerPublisherTransactionRepositoryTestCase, +) +from tests.utils import ( + AiopgTestCase, +) + + +# noinspection SqlNoDataSourceInspection +class TestBrokerPublisherTransactionRepositoryTestCase(AiopgTestCase, BrokerPublisherTransactionRepositoryTestCase): + __test__ = True + + def build_repository(self) -> BrokerPublisherTransactionRepository: + return DatabaseBrokerPublisherTransactionRepository.from_config(self.config) + + +if __name__ == "__main__": + unittest.main() From cd05587b6dd31539303ffb1a7a41e50772d45b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 13:38:59 +0200 Subject: [PATCH 35/75] ISSUE #86 * Add docstring. --- .../publishers/transactional/entries.py | 17 +++++++++--- .../brokers/publishers/transactional/impl.py | 2 +- .../transactional/repositories/abc.py | 22 ++++++++++++--- .../repositories/database/factories.py | 27 +++++++++++++++---- .../repositories/database/impl.py | 2 +- .../transactional/repositories/memory.py | 2 +- .../networks/publishers/transactional.py | 27 +++++++++++++++---- 7 files changed, 78 insertions(+), 21 deletions(-) diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py index 9be5d5109..e3e9d0056 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/entries.py @@ -15,7 +15,7 @@ class BrokerPublisherTransactionEntry: - """TODO""" + """Broker Publisher Transaction Entry class.""" def __init__(self, message: Union[memoryview, bytes, BrokerMessage], transaction_uuid: UUID): if isinstance(message, memoryview): @@ -27,16 +27,25 @@ def __init__(self, message: Union[memoryview, bytes, BrokerMessage], transaction @property def message(self) -> BrokerMessage: - """TODO""" + """Get the message. + + :return: A ``BrokerMessage`` instance. + """ return self._message @property def transaction_uuid(self) -> UUID: - """TODO""" + """Get the transaction identifier. + + :return: An ``UUID`` instance. + """ return self._transaction_uuid def as_raw(self) -> dict[str, Any]: - """TODO""" + """Get a raw representation of the instance. + + :return: A dictionary in which the keys are attribute names and values the attribute contents. + """ return { "message": self._message.avro_bytes, "transaction_uuid": self._transaction_uuid, diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py index 5027ad502..69431cd81 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/impl.py @@ -35,7 +35,7 @@ class TransactionalBrokerPublisher(BrokerPublisher, TransactionalMixin): - """TODO""" + """Transactional Broker Publisher class.""" impl: BrokerPublisher repository: BrokerPublisherTransactionRepository diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py index d286f3ade..ed4e4bf94 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/abc.py @@ -22,12 +22,18 @@ class BrokerPublisherTransactionRepository(ABC, SetupMixin): - """TODO""" + """Broker Publisher Transaction Repository class.""" def select( self, transaction_uuid: Optional[UUID] = None, **kwargs ) -> AsyncIterator[BrokerPublisherTransactionEntry]: - """TODO""" + """Perform a query on the repository. + + :param transaction_uuid: The identifier of the transaction. If ``None`` is provided then the entries are not + filtered by transaction. + :param kwargs: Additional named arguments. + :return: An ``AsyncIterator`` of ``BrokerPublisherTransactionEntry``. + """ return self._select(transaction_uuid=transaction_uuid, **kwargs) @abstractmethod @@ -35,7 +41,11 @@ def _select(self, transaction_uuid: Optional[UUID], **kwargs) -> AsyncIterator[B raise NotImplementedError async def submit(self, entry: BrokerPublisherTransactionEntry) -> None: - """TODO""" + """Submit a new entry to the repository. + + :param entry: The entry to be submitted. + :return: This method does not return anything. + """ await self._submit(entry=entry) @abstractmethod @@ -43,7 +53,11 @@ async def _submit(self, entry: BrokerPublisherTransactionEntry) -> None: raise NotImplementedError async def delete_batch(self, transaction_uuid: UUID) -> None: - """TODO""" + """Delete a batch of entries by transaction. + + :param transaction_uuid: The identifier of the transaction. + :return: This method does not return anything. + """ await self._delete_batch(transaction_uuid=transaction_uuid) @abstractmethod diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py index a795c06d7..bacf47310 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/factories.py @@ -16,20 +16,37 @@ class BrokerPublisherTransactionDatabaseOperationFactory(DatabaseOperationFactory, ABC): - """TODO""" + """Broker Publisher Transaction Database Operation Factory class.""" @abstractmethod def build_create(self) -> DatabaseOperation: - """TODO""" + """Build the operation to initialize the database storage. + + :return: A ``DatabaseOperation`` instance. + """ @abstractmethod def build_query(self, transaction_uuid: Optional[UUID]) -> DatabaseOperation: - """TODO""" + """Build the operation to query stored messages. + + :param transaction_uuid: The identifier of the transaction, if ``None`` is provided then the messages aren't + filtered by transaction. + :return: A ``DatabaseOperation`` instance. + """ @abstractmethod def build_submit(self, message: bytes, transaction_uuid: UUID) -> DatabaseOperation: - """TODO""" + """Build the operation to submit a new message. + + :param message: The message to be submitted. + :param transaction_uuid: The identifier of the transaction. + :return: A ``DatabaseOperation`` instance. + """ @abstractmethod def build_delete_batch(self, transaction_uuid: UUID) -> DatabaseOperation: - """TODO""" + """Build the operation to delete a batch of messages by transaction. + + :param transaction_uuid: The identifier of the transaction. + :return: A ``DatabaseOperation`` instance. + """ diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py index 3cc0e7c77..fca3d775b 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/database/impl.py @@ -25,7 +25,7 @@ class DatabaseBrokerPublisherTransactionRepository( BrokerPublisherTransactionRepository, DatabaseMixin[BrokerPublisherTransactionDatabaseOperationFactory], ): - """TODO""" + """Database Broker Publisher Transaction Repository class.""" def __init__(self, *args, database_key: Optional[tuple[str]] = None, **kwargs): if database_key is None: diff --git a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py index b98af3017..1a6fe6147 100644 --- a/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py +++ b/packages/core/minos-microservice-networks/minos/networks/brokers/publishers/transactional/repositories/memory.py @@ -21,7 +21,7 @@ class InMemoryBrokerPublisherTransactionRepository(BrokerPublisherTransactionRepository): - """TODO""" + """In Memory Broker Publisher Transaction Repository class.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py index 7700567c7..4b862680c 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/networks/publishers/transactional.py @@ -27,7 +27,7 @@ # noinspection SqlDialectInspection,SqlNoDataSourceInspection class AiopgBrokerPublisherTransactionDatabaseOperationFactory(BrokerPublisherTransactionDatabaseOperationFactory): - """TODO""" + """Aiopg Broker Publisher Transaction Database Operation Factory class.""" @staticmethod def build_table_name() -> str: @@ -38,7 +38,10 @@ def build_table_name() -> str: return "broker_publisher_transactional_messages" def build_create(self) -> DatabaseOperation: - """TODO""" + """Build the operation to initialize the database storage. + + :return: A ``DatabaseOperation`` instance. + """ return ComposedDatabaseOperation( [ AiopgDatabaseOperation( @@ -60,7 +63,12 @@ def build_create(self) -> DatabaseOperation: ) def build_query(self, transaction_uuid: Optional[UUID]) -> DatabaseOperation: - """TODO""" + """Build the operation to query stored messages. + + :param transaction_uuid: The identifier of the transaction, if ``None`` is provided then the messages aren't + filtered by transaction. + :return: A ``DatabaseOperation`` instance. + """ if transaction_uuid is None: return AiopgDatabaseOperation(SQL(f"SELECT message, transaction_uuid FROM {self.build_table_name()}")) @@ -76,7 +84,12 @@ def build_query(self, transaction_uuid: Optional[UUID]) -> DatabaseOperation: ) def build_submit(self, message: bytes, transaction_uuid: UUID) -> DatabaseOperation: - """TODO""" + """Build the operation to submit a new message. + + :param message: The message to be submitted. + :param transaction_uuid: The identifier of the transaction. + :return: A ``DatabaseOperation`` instance. + """ return AiopgDatabaseOperation( SQL( f""" @@ -91,7 +104,11 @@ def build_submit(self, message: bytes, transaction_uuid: UUID) -> DatabaseOperat ) def build_delete_batch(self, transaction_uuid: UUID) -> DatabaseOperation: - """TODO""" + """Build the operation to delete a batch of messages by transaction. + + :param transaction_uuid: The identifier of the transaction. + :return: A ``DatabaseOperation`` instance. + """ return AiopgDatabaseOperation( SQL(f"DELETE FROM {self.build_table_name()} WHERE transaction_uuid = %(transaction_uuid)s"), {"transaction_uuid": transaction_uuid}, From 7b67f9f93c3cd2144099dee1f6862c3e44bd9454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 13:44:06 +0200 Subject: [PATCH 36/75] ISSUE #86 * Fix bug related with kwargs propagation. --- .../core/minos-microservice-aggregate/minos/aggregate/impl.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py index 89b42393a..e92acaee0 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py @@ -87,7 +87,8 @@ def _get_broker_publisher_from_config( if "publisher" in aggregate_config: publisher_config = aggregate_config["publisher"] client_cls = publisher_config.pop("client") - broker_publisher = client_cls.from_config(config, **(publisher_config | kwargs)) + publisher_kwargs = publisher_config | {"broker_publisher": broker_publisher} | kwargs + broker_publisher = client_cls.from_config(config, **publisher_kwargs) return broker_publisher From 8f9189c3535391de2b5b9f1f0b64ab819428e47d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 25 Apr 2022 17:18:16 +0200 Subject: [PATCH 37/75] ISSUE #86 * Reorder injections. --- .../minos-microservice-common/minos/common/config/v2.py | 8 ++++---- .../tests/test_common/test_config/test_v2/test_base.py | 4 ++-- .../test_common/test_config/test_v2/test_parameterized.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/core/minos-microservice-common/minos/common/config/v2.py b/packages/core/minos-microservice-common/minos/common/config/v2.py index 55e8c3292..9fb910d47 100644 --- a/packages/core/minos-microservice-common/minos/common/config/v2.py +++ b/packages/core/minos-microservice-common/minos/common/config/v2.py @@ -63,16 +63,16 @@ def _get_injections(self) -> list[Union[InjectableMixin, type[InjectableMixin]]] partial_ans.append(self._get_interfaces().get("broker").get("subscriber")) with suppress(MinosConfigException): - partial_ans.extend(self._get_aggregate().get("repositories", dict()).values()) + partial_ans.append(self._get_discovery().get("connector")) with suppress(MinosConfigException): - partial_ans.append(self._get_aggregate().get("client")) + partial_ans.append(self._get_saga().get("manager")) with suppress(MinosConfigException): - partial_ans.append(self._get_discovery().get("connector")) + partial_ans.extend(self._get_aggregate().get("repositories", dict()).values()) with suppress(MinosConfigException): - partial_ans.append(self._get_saga().get("manager")) + partial_ans.append(self._get_aggregate().get("client")) with suppress(MinosConfigException): injections = self.get_by_key("injections") diff --git a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py index 51e4e398a..c1716d88a 100644 --- a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py +++ b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py @@ -64,12 +64,12 @@ def test_injections(self): FakeHttpConnector, FakeBrokerPublisher, FakeBrokerSubscriberBuilder(FakeBrokerSubscriber), + FakeDiscoveryConnector, + FakeSagaManager, FakeEventRepository, FakeSnapshotRepository, FakeTransactionRepository, FakeAggregate, - FakeDiscoveryConnector, - FakeSagaManager, FakeCustomInjection, ] self.assertEqual(expected, self.config.get_injections()) diff --git a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py index 5b3f8968a..dd9b2d946 100644 --- a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py +++ b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py @@ -40,12 +40,12 @@ def test_injections_nones(self): PoolFactory, FakeBrokerPublisher, FakeBrokerSubscriberBuilder(FakeBrokerSubscriber), + FakeDiscoveryConnector, + FakeSagaManager, FakeEventRepository, FakeSnapshotRepository, FakeTransactionRepository, FakeAggregate, - FakeDiscoveryConnector, - FakeSagaManager, FakeCustomInjection, ] self.assertEqual(expected, config.get_injections()) From e87a39e2e2cf7aadef40daa29379ed3a9d9c9c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Tue, 26 Apr 2022 11:58:44 +0200 Subject: [PATCH 38/75] ISSUE #159 * Add `EntityRepository`. --- .../minos/aggregate/entities/__init__.py | 3 + .../minos/aggregate/entities/repositories.py | 248 ++++++++++++++++++ .../minos/aggregate/impl.py | 4 + 3 files changed, 255 insertions(+) create mode 100644 packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py index 7be22cdf7..f565aabe7 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py @@ -12,3 +12,6 @@ RefInjector, RefResolver, ) +from .repositories import ( + EntityRepository, +) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py new file mode 100644 index 000000000..b1d2f4551 --- /dev/null +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py @@ -0,0 +1,248 @@ +import logging +from collections.abc import ( + AsyncIterator, +) +from typing import ( + Optional, + TypeVar, +) +from uuid import ( + UUID, +) + +from minos.common import ( + NULL_UUID, + Inject, + NotProvidedException, +) + +from ..events import ( + Event, + EventEntry, + EventRepository, +) +from ..exceptions import ( + EventRepositoryException, +) +from ..queries import ( + _Condition, + _Ordering, +) +from ..snapshots import ( + SnapshotRepository, +) +from .models import ( + RootEntity, +) + +logger = logging.getLogger(__name__) + +T = TypeVar("T", bound=RootEntity) + + +class EntityRepository: + """TODO""" + + _event_repository: EventRepository + _snapshot_repository: SnapshotRepository + + # noinspection PyUnusedLocal + @Inject() + def __init__( + self, + _event_repository: EventRepository, + _snapshot_repository: SnapshotRepository, + *args, + **kwargs, + ): + + if _event_repository is None: + raise NotProvidedException(f"A {EventRepository!r} instance is required.") + if _snapshot_repository is None: + raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") + + self._event_repository = _event_repository + self._snapshot_repository = _snapshot_repository + + async def get(self, cls: type[T], uuid: UUID, **kwargs) -> T: + """Get one instance from the database based on its identifier. + + :param cls: TODO + :param uuid: The identifier of the instance. + :return: A ``RootEntity`` instance. + """ + if self._snapshot_repository is None: + raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") + + # noinspection PyTypeChecker + return await self._snapshot_repository.get(cls.classname, uuid, **kwargs) + + def get_all( + self, + cls: type[T], + ordering: Optional[_Ordering] = None, + limit: Optional[int] = None, + **kwargs, + ) -> AsyncIterator[T]: + """Get all instance from the database. + + :param cls: TODO + :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour + is to retrieve them without any order pattern. + :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the + instances that meet the given condition. + :return: A ``RootEntity`` instance. + """ + if self._snapshot_repository is None: + raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") + + # noinspection PyTypeChecker + return self._snapshot_repository.get_all(cls.classname, ordering, limit, **kwargs) + + def find( + self, + cls: type[T], + condition: _Condition, + ordering: Optional[_Ordering] = None, + limit: Optional[int] = None, + **kwargs, + ) -> AsyncIterator[T]: + """Find a collection of instances based on a given ``Condition``. + + :param cls: TODO + :param condition: The ``Condition`` that must be satisfied by all the instances. + :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour + is to retrieve them without any order pattern. + :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the + instances that meet the given condition. + :return: An asynchronous iterator of ``RootEntity`` instances. + """ + if self._snapshot_repository is None: + raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") + # noinspection PyTypeChecker + return self._snapshot_repository.find(cls.classname, condition, ordering, limit, **kwargs) + + async def create(self, cls: type[T], *args, **kwargs) -> tuple[T, Event]: + """Create a new ``RootEntity`` instance. + + :param cls: TODO + :param args: Additional positional arguments. + :param kwargs: Additional named arguments. + :return: A new ``RootEntity`` instance. + """ + if "uuid" in kwargs: + raise EventRepositoryException( + f"The identifier must be computed internally on the repository. Obtained: {kwargs['uuid']}" + ) + if "version" in kwargs: + raise EventRepositoryException( + f"The version must be computed internally on the repository. Obtained: {kwargs['version']}" + ) + if "created_at" in kwargs: + raise EventRepositoryException( + f"The version must be computed internally on the repository. Obtained: {kwargs['created_at']}" + ) + if "updated_at" in kwargs: + raise EventRepositoryException( + f"The version must be computed internally on the repository. Obtained: {kwargs['updated_at']}" + ) + + instance: T = cls(*args, **kwargs) + + event = Event.from_root_entity(instance) + entry = await self._event_repository.submit(event) + + self._update_from_repository_entry(instance, entry) + + return instance, entry.event + + # noinspection PyMethodParameters,PyShadowingBuiltins + async def update(self, instance: T, **kwargs) -> tuple[T, Optional[Event]]: + """Update an existing ``RootEntity`` instance. + + :param instance: TODO + :param kwargs: Additional named arguments. + :return: An updated ``RootEntity`` instance. + """ + + if "version" in kwargs: + raise EventRepositoryException( + f"The version must be computed internally on the repository. Obtained: {kwargs['version']}" + ) + if "created_at" in kwargs: + raise EventRepositoryException( + f"The version must be computed internally on the repository. Obtained: {kwargs['created_at']}" + ) + if "updated_at" in kwargs: + raise EventRepositoryException( + f"The version must be computed internally on the repository. Obtained: {kwargs['updated_at']}" + ) + + for key, value in kwargs.items(): + setattr(self, key, value) + + previous = await self.get(type(instance), instance.uuid) + event = instance.diff(previous) + if not len(event.fields_diff): + return instance + + entry = await self._event_repository.submit(event) + + self._update_from_repository_entry(instance, entry) + + return instance, entry.event + + async def save(self, instance: T) -> Optional[Event]: + """Store the current instance on the repository. + + If didn't exist previously creates a new one, otherwise updates the existing one. + """ + is_creation = instance.uuid == NULL_UUID + if is_creation != (instance.version == 0): + if is_creation: + raise EventRepositoryException( + f"The version must be computed internally on the repository. Obtained: {instance.version}" + ) + else: + raise EventRepositoryException( + f"The uuid must be computed internally on the repository. Obtained: {instance.uuid}" + ) + + values = { + k: field.value + for k, field in instance.fields.items() + if k not in {"uuid", "version", "created_at", "updated_at"} + } + if is_creation: + new, event = await self.create(type(instance), **values) + instance._fields |= new.fields + else: + _, event = await self.update(instance, **values) + return event + + async def refresh(self, instance: T) -> None: + """Refresh the state of the given instance. + + :return: This method does not return anything. + """ + new = await self.get(type(instance), instance.uuid) + instance._fields |= new.fields + + async def delete(self, instance: T) -> Event: + """Delete the given root entity instance. + + :return: This method does not return anything. + """ + event = Event.from_deleted_root_entity(instance) + entry = await self._event_repository.submit(event) + + self._update_from_repository_entry(instance, entry) + return entry.event + + @staticmethod + def _update_from_repository_entry(instance: T, entry: EventEntry) -> None: + instance.uuid = entry.uuid + instance.version = entry.version + if entry.action.is_create: + instance.created_at = entry.created_at + instance.updated_at = entry.created_at diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py index e92acaee0..8e09076d2 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py @@ -23,6 +23,7 @@ ) from .entities import ( + EntityRepository, RootEntity, ) from .events import ( @@ -42,6 +43,7 @@ class Aggregate(Generic[RT], SetupMixin): transaction_repository: TransactionRepository event_repository: EventRepository snapshot_repository: SnapshotRepository + repository: EntityRepository broker_publisher: BrokerPublisher @Inject() @@ -67,6 +69,8 @@ def __init__( self._check_root() + self.repository = EntityRepository(event_repository, snapshot_repository) + self.transaction_repository = transaction_repository self.event_repository = event_repository self.snapshot_repository = snapshot_repository From b2553177c721fe1dbdf3021e67b078d0c5035ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Tue, 26 Apr 2022 16:19:21 +0200 Subject: [PATCH 39/75] ISSUE #159 * Add `EntityRepository` (2). --- .../minos/aggregate/__init__.py | 1 + .../minos/aggregate/entities/models.py | 228 ------------------ .../minos/aggregate/entities/repositories.py | 22 +- .../minos/aggregate/snapshots/services.py | 3 +- .../test_models/test_repositories/__init__.py | 0 .../test_base.py | 113 +++++---- .../test_repositories/test_integration.py | 93 +++++++ .../test_models/test_root/test_broker.py | 1 + .../test_root/test_not_provided.py | 42 ---- .../test_root/test_with_postgresql.py | 104 -------- .../test_entities/test_refs/test_injectors.py | 6 +- .../test_snapshots/test_services.py | 6 +- .../tests/utils.py | 5 +- 13 files changed, 179 insertions(+), 445 deletions(-) create mode 100644 packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/__init__.py rename packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/{test_root => test_repositories}/test_base.py (53%) create mode 100644 packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_integration.py delete mode 100644 packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_not_provided.py delete mode 100644 packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_with_postgresql.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py index 208e00597..3aeefe81f 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py @@ -17,6 +17,7 @@ ) from .entities import ( Entity, + EntityRepository, EntitySet, ExternalEntity, Ref, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py index 94be69d3d..290d85456 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py @@ -7,7 +7,6 @@ datetime, ) from typing import ( - AsyncIterator, Optional, Type, TypeVar, @@ -21,26 +20,12 @@ NULL_DATETIME, NULL_UUID, DeclarativeModel, - Inject, - NotProvidedException, ) from ..events import ( Event, - EventEntry, - EventRepository, IncrementalFieldDiff, ) -from ..exceptions import ( - EventRepositoryException, -) -from ..queries import ( - _Condition, - _Ordering, -) -from ..snapshots import ( - SnapshotRepository, -) logger = logging.getLogger(__name__) @@ -75,10 +60,6 @@ class RootEntity(Entity): created_at: datetime updated_at: datetime - _event_repository: EventRepository - _snapshot_repository: SnapshotRepository - - @Inject() def __init__( self, *args, @@ -86,220 +67,11 @@ def __init__( version: int = 0, created_at: datetime = NULL_DATETIME, updated_at: datetime = NULL_DATETIME, - _event_repository: EventRepository, - _snapshot_repository: SnapshotRepository, **kwargs, ): super().__init__(version, created_at, updated_at, *args, uuid=uuid, **kwargs) - if _event_repository is None: - raise NotProvidedException(f"A {EventRepository!r} instance is required.") - if _snapshot_repository is None: - raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") - - self._event_repository = _event_repository - self._snapshot_repository = _snapshot_repository - - @classmethod - @Inject() - async def get(cls: Type[T], uuid: UUID, *, _snapshot_repository: SnapshotRepository, **kwargs) -> T: - """Get one instance from the database based on its identifier. - - :param uuid: The identifier of the instance. - :param _snapshot_repository: Snapshot to be set to the root entity. - :return: A ``RootEntity`` instance. - """ - if _snapshot_repository is None: - raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") - - # noinspection PyTypeChecker - return await _snapshot_repository.get(cls.classname, uuid, _snapshot_repository=_snapshot_repository, **kwargs) - - @classmethod - @Inject() - def get_all( - cls: Type[T], - ordering: Optional[_Ordering] = None, - limit: Optional[int] = None, - *, - _snapshot_repository: SnapshotRepository, - **kwargs, - ) -> AsyncIterator[T]: - """Get all instance from the database. - - :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour - is to retrieve them without any order pattern. - :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the - instances that meet the given condition. - :param _snapshot_repository: Snapshot to be set to the root entity. - :return: A ``RootEntity`` instance. - """ - if _snapshot_repository is None: - raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") - - # noinspection PyTypeChecker - return _snapshot_repository.get_all( - cls.classname, ordering, limit, _snapshot_repository=_snapshot_repository, **kwargs - ) - - @classmethod - @Inject() - def find( - cls: Type[T], - condition: _Condition, - ordering: Optional[_Ordering] = None, - limit: Optional[int] = None, - *, - _snapshot_repository: SnapshotRepository, - **kwargs, - ) -> AsyncIterator[T]: - """Find a collection of instances based on a given ``Condition``. - - :param condition: The ``Condition`` that must be satisfied by all the instances. - :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour - is to retrieve them without any order pattern. - :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the - instances that meet the given condition. - :param _snapshot_repository: Snapshot to be set to the instances. - :return: An asynchronous iterator of ``RootEntity`` instances. - """ - if _snapshot_repository is None: - raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") - # noinspection PyTypeChecker - return _snapshot_repository.find( - cls.classname, condition, ordering, limit, _snapshot_repository=_snapshot_repository, **kwargs - ) - - @classmethod - async def create(cls: Type[T], *args, **kwargs) -> T: - """Create a new ``RootEntity`` instance. - - :param args: Additional positional arguments. - :param kwargs: Additional named arguments. - :return: A new ``RootEntity`` instance. - """ - if "uuid" in kwargs: - raise EventRepositoryException( - f"The identifier must be computed internally on the repository. Obtained: {kwargs['uuid']}" - ) - if "version" in kwargs: - raise EventRepositoryException( - f"The version must be computed internally on the repository. Obtained: {kwargs['version']}" - ) - if "created_at" in kwargs: - raise EventRepositoryException( - f"The version must be computed internally on the repository. Obtained: {kwargs['created_at']}" - ) - if "updated_at" in kwargs: - raise EventRepositoryException( - f"The version must be computed internally on the repository. Obtained: {kwargs['updated_at']}" - ) - - instance: T = cls(*args, **kwargs) - - event = Event.from_root_entity(instance) - entry = await instance._event_repository.submit(event) - - instance._update_from_repository_entry(entry) - - return instance - - # noinspection PyMethodParameters,PyShadowingBuiltins - async def update(self: T, **kwargs) -> T: - """Update an existing ``RootEntity`` instance. - - :param kwargs: Additional named arguments. - :return: An updated ``RootEntity`` instance. - """ - - if "version" in kwargs: - raise EventRepositoryException( - f"The version must be computed internally on the repository. Obtained: {kwargs['version']}" - ) - if "created_at" in kwargs: - raise EventRepositoryException( - f"The version must be computed internally on the repository. Obtained: {kwargs['created_at']}" - ) - if "updated_at" in kwargs: - raise EventRepositoryException( - f"The version must be computed internally on the repository. Obtained: {kwargs['updated_at']}" - ) - - for key, value in kwargs.items(): - setattr(self, key, value) - - previous = await self.get( - self.uuid, _event_repository=self._event_repository, _snapshot_repository=self._snapshot_repository - ) - event = self.diff(previous) - if not len(event.fields_diff): - return self - - entry = await self._event_repository.submit(event) - - self._update_from_repository_entry(entry) - - return self - - async def save(self) -> None: - """Store the current instance on the repository. - - If didn't exist previously creates a new one, otherwise updates the existing one. - """ - is_creation = self.uuid == NULL_UUID - if is_creation != (self.version == 0): - if is_creation: - raise EventRepositoryException( - f"The version must be computed internally on the repository. Obtained: {self.version}" - ) - else: - raise EventRepositoryException( - f"The uuid must be computed internally on the repository. Obtained: {self.uuid}" - ) - - values = { - k: field.value - for k, field in self.fields.items() - if k not in {"uuid", "version", "created_at", "updated_at"} - } - if is_creation: - new = await self.create( - **values, _event_repository=self._event_repository, _snapshot_repository=self._snapshot_repository - ) - self._fields |= new.fields - else: - await self.update( - **values, _event_repository=self._event_repository, _snapshot_repository=self._snapshot_repository - ) - - async def refresh(self) -> None: - """Refresh the state of the given instance. - - :return: This method does not return anything. - """ - new = await self.get( - self.uuid, _event_repository=self._event_repository, _snapshot_repository=self._snapshot_repository - ) - self._fields |= new.fields - - async def delete(self) -> None: - """Delete the given root entity instance. - - :return: This method does not return anything. - """ - event = Event.from_deleted_root_entity(self) - entry = await self._event_repository.submit(event) - - self._update_from_repository_entry(entry) - - def _update_from_repository_entry(self, entry: EventEntry) -> None: - self.uuid = entry.uuid - self.version = entry.version - if entry.action.is_create: - self.created_at = entry.created_at - self.updated_at = entry.created_at - def diff(self, another: RootEntity) -> Event: """Compute the difference with another instance. diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py index b1d2f4551..ee1cb98fc 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py @@ -50,19 +50,19 @@ class EntityRepository: @Inject() def __init__( self, - _event_repository: EventRepository, - _snapshot_repository: SnapshotRepository, + event_repository: EventRepository, + snapshot_repository: SnapshotRepository, *args, **kwargs, ): - if _event_repository is None: + if event_repository is None: raise NotProvidedException(f"A {EventRepository!r} instance is required.") - if _snapshot_repository is None: + if snapshot_repository is None: raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") - self._event_repository = _event_repository - self._snapshot_repository = _snapshot_repository + self._event_repository = event_repository + self._snapshot_repository = snapshot_repository async def get(self, cls: type[T], uuid: UUID, **kwargs) -> T: """Get one instance from the database based on its identifier. @@ -71,9 +71,6 @@ async def get(self, cls: type[T], uuid: UUID, **kwargs) -> T: :param uuid: The identifier of the instance. :return: A ``RootEntity`` instance. """ - if self._snapshot_repository is None: - raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") - # noinspection PyTypeChecker return await self._snapshot_repository.get(cls.classname, uuid, **kwargs) @@ -93,9 +90,6 @@ def get_all( instances that meet the given condition. :return: A ``RootEntity`` instance. """ - if self._snapshot_repository is None: - raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") - # noinspection PyTypeChecker return self._snapshot_repository.get_all(cls.classname, ordering, limit, **kwargs) @@ -117,8 +111,6 @@ def find( instances that meet the given condition. :return: An asynchronous iterator of ``RootEntity`` instances. """ - if self._snapshot_repository is None: - raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") # noinspection PyTypeChecker return self._snapshot_repository.find(cls.classname, condition, ordering, limit, **kwargs) @@ -179,7 +171,7 @@ async def update(self, instance: T, **kwargs) -> tuple[T, Optional[Event]]: ) for key, value in kwargs.items(): - setattr(self, key, value) + setattr(instance, key, value) previous = await self.get(type(instance), instance.uuid) event = instance.diff(previous) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/services.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/services.py index b77ab3f4c..f8069ae5f 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/services.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/services.py @@ -84,7 +84,8 @@ async def __get_many__(self, request: Request) -> Response: raise ResponseException(f"There was a problem while parsing the given request: {exc!r}") try: - instances = await gather(*(self.type_.get(uuid) for uuid in content["uuids"])) + futures = (self.snapshot_repository.get(self.type_, uuid) for uuid in content["uuids"]) + instances = await gather(*futures) except Exception as exc: raise ResponseException(f"There was a problem while getting the instances: {exc!r}") diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/__init__.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_base.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_base.py similarity index 53% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_base.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_base.py index 455b410d5..1638b6e6d 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_base.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_base.py @@ -2,6 +2,9 @@ from asyncio import ( gather, ) +from operator import ( + itemgetter, +) from uuid import ( uuid4, ) @@ -9,12 +12,14 @@ from minos.aggregate import ( AlreadyDeletedException, Condition, + EntityRepository, EventRepositoryException, NotFoundException, Ordering, ) from minos.common import ( NULL_UUID, + NotProvidedException, current_datetime, ) from tests.utils import ( @@ -23,9 +28,19 @@ ) -class TestRootEntity(AggregateTestCase): +class TestEntityRepository(AggregateTestCase): + def setUp(self) -> None: + super().setUp() + self.repository = EntityRepository() + + def test_constructor_raises(self): + with self.assertRaises(NotProvidedException): + EntityRepository(event_repository=None) + with self.assertRaises(NotProvidedException): + EntityRepository(snapshot_repository=None) + async def test_create(self): - observed = await Car.create(doors=3, color="blue") + observed, _ = await self.repository.create(Car, doors=3, color="blue") expected = Car( 3, "blue", @@ -38,27 +53,30 @@ async def test_create(self): async def test_create_raises(self): with self.assertRaises(EventRepositoryException): - await Car.create(uuid=uuid4(), doors=3, color="blue") + await self.repository.create(Car, uuid=uuid4(), doors=3, color="blue") with self.assertRaises(EventRepositoryException): - await Car.create(version=1, doors=3, color="blue") + await self.repository.create(Car, version=1, doors=3, color="blue") with self.assertRaises(EventRepositoryException): - await Car.create(created_at=current_datetime(), doors=3, color="blue") + await self.repository.create(Car, created_at=current_datetime(), doors=3, color="blue") with self.assertRaises(EventRepositoryException): - await Car.create(updated_at=current_datetime(), doors=3, color="blue") + await self.repository.create(Car, updated_at=current_datetime(), doors=3, color="blue") async def test_classname(self): self.assertEqual("tests.utils.Car", Car.classname) async def test_get_all(self): instances = list( - await gather( - Car.create(doors=5, color="blue"), - Car.create(doors=3, color="red"), - Car.create(doors=1, color="blue"), + map( + itemgetter(0), + await gather( + self.repository.create(Car, doors=5, color="blue"), + self.repository.create(Car, doors=3, color="red"), + self.repository.create(Car, doors=1, color="blue"), + ), ) ) ordering = Ordering.ASC("doors") - iterable = Car.get_all(ordering) + iterable = self.repository.get_all(Car, ordering) observed = [v async for v in iterable] expected = sorted(instances, key=lambda car: car.doors) @@ -66,72 +84,75 @@ async def test_get_all(self): async def test_find(self): originals = set( - await gather( - Car.create(doors=3, color="blue"), - Car.create(doors=3, color="red"), - Car.create(doors=5, color="blue"), + map( + itemgetter(0), + await gather( + self.repository.create(Car, doors=3, color="blue"), + self.repository.create(Car, doors=3, color="red"), + self.repository.create(Car, doors=5, color="blue"), + ), ) ) condition = Condition.IN("uuid", {o.uuid for o in originals}) ordering = Ordering.ASC("doors") limit = 10 - iterable = Car.find(condition, ordering, limit) + iterable = self.repository.find(Car, condition, ordering, limit) recovered = {v async for v in iterable} self.assertEqual(originals, recovered) async def test_get(self): - original = await Car.create(doors=3, color="blue") - recovered = await Car.get(original.uuid) + original, _ = await self.repository.create(Car, doors=3, color="blue") + recovered = await self.repository.get(Car, original.uuid) self.assertEqual(original, recovered) async def test_get_raises(self): with self.assertRaises(NotFoundException): - await Car.get(NULL_UUID) + await self.repository.get(Car, NULL_UUID) async def test_update(self): - car = await Car.create(doors=3, color="blue") + car, _ = await self.repository.create(Car, doors=3, color="blue") - await car.update(color="red") + await self.repository.update(car, color="red") expected = Car(3, "red", uuid=car.uuid, version=2, created_at=car.created_at, updated_at=car.updated_at) self.assertEqual(expected, car) - self.assertEqual(car, await Car.get(car.uuid)) + self.assertEqual(car, await self.repository.get(Car, car.uuid)) - await car.update(doors=5) + await self.repository.update(car, doors=5) expected = Car(5, "red", uuid=car.uuid, version=3, created_at=car.created_at, updated_at=car.updated_at) self.assertEqual(expected, car) - self.assertEqual(car, await Car.get(car.uuid)) + self.assertEqual(car, await self.repository.get(Car, car.uuid)) async def test_update_no_changes(self): - car = await Car.create(doors=3, color="blue") + car, _ = await self.repository.create(Car, doors=3, color="blue") - await car.update(color="blue") + await self.repository.update(car, color="blue") expected = Car(3, "blue", uuid=car.uuid, version=1, created_at=car.created_at, updated_at=car.updated_at) self.assertEqual(expected, car) - self.assertEqual(car, await Car.get(car.uuid)) + self.assertEqual(car, await self.repository.get(Car, car.uuid)) async def test_update_raises(self): with self.assertRaises(EventRepositoryException): - await Car(3, "blue").update(version=1) + await self.repository.update(Car(3, "blue"), version=1) with self.assertRaises(EventRepositoryException): - await Car(3, "blue").update(created_at=current_datetime()) + await self.repository.update(Car(3, "blue"), created_at=current_datetime()) with self.assertRaises(EventRepositoryException): - await Car(3, "blue").update(updated_at=current_datetime()) + await self.repository.update(Car(3, "blue"), updated_at=current_datetime()) async def test_refresh(self): - car = await Car.create(doors=3, color="blue") + car, _ = await self.repository.create(Car, doors=3, color="blue") uuid = car.uuid - car2 = await Car.get(uuid) - await car2.update(color="red") - await car2.update(doors=5) + car2 = await self.repository.get(Car, uuid) + await self.repository.update(car2, color="red") + await self.repository.update(car2, doors=5) self.assertEqual( Car(3, "blue", uuid=uuid, version=1, created_at=car.created_at, updated_at=car.updated_at), car, ) - await car.refresh() + await self.repository.refresh(car) self.assertEqual( Car(5, "red", uuid=uuid, version=3, created_at=car.created_at, updated_at=car.updated_at), car, @@ -143,16 +164,16 @@ async def test_save_create(self): car.doors = 5 with self.assertRaises(NotFoundException): - await car.refresh() + await self.repository.refresh(car) - await car.save() + await self.repository.save(car) self.assertEqual( Car(5, "red", uuid=car.uuid, version=1, created_at=car.created_at, updated_at=car.updated_at), car, ) async def test_save_update(self): - car = await Car.create(doors=3, color="blue") + car, _ = await self.repository.create(Car, doors=3, color="blue") uuid = car.uuid @@ -160,26 +181,26 @@ async def test_save_update(self): car.doors = 5 expected = Car(3, "blue", uuid=uuid, version=1, created_at=car.created_at, updated_at=car.updated_at) - self.assertEqual(expected, await Car.get(uuid)) + self.assertEqual(expected, await self.repository.get(Car, uuid)) - await car.save() + await self.repository.save(car) expected = Car(5, "red", uuid=uuid, version=2, created_at=car.created_at, updated_at=car.updated_at) self.assertEqual(expected, car) expected = Car(5, "red", uuid=uuid, version=2, created_at=car.created_at, updated_at=car.updated_at) - self.assertEqual(expected, await Car.get(uuid)) + self.assertEqual(expected, await self.repository.get(Car, uuid)) async def test_save_raises(self): with self.assertRaises(EventRepositoryException): - await Car(3, "blue", uuid=uuid4()).save() + await self.repository.save(Car(3, "blue", uuid=uuid4())) with self.assertRaises(EventRepositoryException): - await Car(3, "blue", version=1).save() + await self.repository.save(Car(3, "blue", version=1)) async def test_delete(self): - car = await Car.create(doors=3, color="blue") - await car.delete() + car, _ = await self.repository.create(Car, doors=3, color="blue") + await self.repository.delete(car) with self.assertRaises(AlreadyDeletedException): - await Car.get(car.uuid) + await self.repository.get(Car, car.uuid) if __name__ == "__main__": diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_integration.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_integration.py new file mode 100644 index 000000000..c47506f6f --- /dev/null +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_integration.py @@ -0,0 +1,93 @@ +import unittest + +from minos.aggregate import ( + AlreadyDeletedException, + EntityRepository, + EntitySet, + ValueObjectSet, +) +from minos.common.testing import ( + DatabaseMinosTestCase, +) +from tests.utils import ( + AggregateTestCase, + Car, + Order, + OrderItem, + Review, +) + + +class IntegrationTestEntityRepository(AggregateTestCase, DatabaseMinosTestCase): + def setUp(self): + super().setUp() + + self.repository = EntityRepository() + + async def test_create_update_delete(self): + car, _ = await self.repository.create(Car, doors=3, color="blue") + uuid = car.uuid + + await self.repository.update(car, color="red") + expected = Car(3, "red", uuid=uuid, version=2, created_at=car.created_at, updated_at=car.updated_at) + self.assertEqual(expected, car) + self.assertEqual(car, await self.repository.get(Car, car.uuid)) + + await self.repository.update(car, doors=5) + expected = Car(5, "red", uuid=uuid, version=3, created_at=car.created_at, updated_at=car.updated_at) + self.assertEqual(expected, car) + self.assertEqual(car, await self.repository.get(Car, car.uuid)) + + await self.repository.delete(car) + with self.assertRaises(AlreadyDeletedException): + await self.repository.get(Car, car.uuid) + + car, _ = await self.repository.create(Car, doors=3, color="blue") + uuid = car.uuid + + await self.repository.update(car, color="red") + expected = Car(3, "red", uuid=uuid, version=2, created_at=car.created_at, updated_at=car.updated_at) + self.assertEqual(expected, await self.repository.get(Car, car.uuid)) + + await self.repository.delete(car) + with self.assertRaises(AlreadyDeletedException): + await self.repository.get(Car, car.uuid) + + async def test_entity_set_value_object_set(self): + order, _ = await self.repository.create(Order, products=EntitySet(), reviews=ValueObjectSet()) + item = OrderItem("foo") + order.products.add(item) + + await self.repository.save(order) + + recovered = await self.repository.get(Order, order.uuid) + self.assertEqual(order, recovered) + + item.name = "bar" + order.products.add(item) + await self.repository.save(order) + + recovered = await self.repository.get(Order, order.uuid) + self.assertEqual(order, recovered) + + order.products.remove(item) + await self.repository.save(order) + + recovered = await self.repository.get(Order, order.uuid) + self.assertEqual(order, recovered) + + order.reviews.add(Review("GoodReview")) + await self.repository.save(order) + + recovered = await self.repository.get(Order, order.uuid) + self.assertEqual(order, recovered) + + order.reviews.discard(Review("GoodReview")) + await self.repository.save(order) + + recovered = await self.repository.get(Order, order.uuid) + self.assertEqual(order, recovered) + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_broker.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_broker.py index c9143461a..7faa0e6fe 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_broker.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_broker.py @@ -20,6 +20,7 @@ ) +@unittest.skip class TestRootEntityBroker(AggregateTestCase): async def test_create(self): car = await Car.create(doors=3, color="blue") diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_not_provided.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_not_provided.py deleted file mode 100644 index bad23aa57..000000000 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_not_provided.py +++ /dev/null @@ -1,42 +0,0 @@ -import unittest -from uuid import ( - uuid4, -) - -from minos.aggregate import ( - Condition, -) -from minos.common import ( - NotProvidedException, -) -from tests.utils import ( - AggregateTestCase, - Car, -) - - -class TestRootEntityNotProvided(AggregateTestCase): - async def test_create_raises(self): - with self.assertRaises(NotProvidedException): - await Car.create(doors=3, color="blue", _event_repository=None) - with self.assertRaises(NotProvidedException): - await Car.create(doors=3, color="blue", _snapshot_repository=None) - - async def test_get_raises(self): - with self.assertRaises(NotProvidedException): - # noinspection PyTypeChecker - await Car.get(uuid4(), _snapshot_repository=None) - - async def test_get_all_raises(self): - with self.assertRaises(NotProvidedException): - # noinspection PyTypeChecker - [c async for c in Car.get_all(_snapshot_repository=None)] - - async def test_find_raises(self): - with self.assertRaises(NotProvidedException): - # noinspection PyTypeChecker - [c async for c in Car.find(Condition.TRUE, _snapshot_repository=None)] - - -if __name__ == "__main__": - unittest.main() diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_with_postgresql.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_with_postgresql.py deleted file mode 100644 index 530651395..000000000 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_with_postgresql.py +++ /dev/null @@ -1,104 +0,0 @@ -import unittest - -from minos.aggregate import ( - AlreadyDeletedException, - DatabaseEventRepository, - DatabaseSnapshotRepository, - EntitySet, - ValueObjectSet, -) -from minos.common.testing import ( - DatabaseMinosTestCase, -) -from minos.transactions import ( - DatabaseTransactionRepository, -) -from tests.utils import ( - AggregateTestCase, - Car, - Order, - OrderItem, - Review, -) - - -class TestExternalEntityWithDatabase(AggregateTestCase, DatabaseMinosTestCase): - def setUp(self): - super().setUp() - - self.transaction_repository = DatabaseTransactionRepository.from_config(self.config) - - self.event_repository = DatabaseEventRepository.from_config( - self.config, transaction_repository=self.transaction_repository - ) - self.snapshot_repository = DatabaseSnapshotRepository.from_config( - self.config, event_repository=self.event_repository, transaction_repository=self.transaction_repository - ) - - async def test_create_update_delete(self): - car = await Car.create(doors=3, color="blue") - uuid = car.uuid - - await car.update(color="red") - expected = Car(3, "red", uuid=uuid, version=2, created_at=car.created_at, updated_at=car.updated_at) - self.assertEqual(expected, car) - self.assertEqual(car, await Car.get(car.uuid)) - - await car.update(doors=5) - expected = Car(5, "red", uuid=uuid, version=3, created_at=car.created_at, updated_at=car.updated_at) - self.assertEqual(expected, car) - self.assertEqual(car, await Car.get(car.uuid)) - - await car.delete() - with self.assertRaises(AlreadyDeletedException): - await Car.get(car.uuid) - - car = await Car.create(doors=3, color="blue") - uuid = car.uuid - - await car.update(color="red") - expected = Car(3, "red", uuid=uuid, version=2, created_at=car.created_at, updated_at=car.updated_at) - self.assertEqual(expected, await Car.get(car.uuid)) - - await car.delete() - with self.assertRaises(AlreadyDeletedException): - await Car.get(car.uuid) - - async def test_entity_set_value_object_set(self): - order = await Order.create(products=EntitySet(), reviews=ValueObjectSet()) - item = OrderItem("foo") - order.products.add(item) - - await order.save() - - recovered = await Order.get(order.uuid) - self.assertEqual(order, recovered) - - item.name = "bar" - order.products.add(item) - await order.save() - - recovered = await Order.get(order.uuid) - self.assertEqual(order, recovered) - - order.products.remove(item) - await order.save() - - recovered = await Order.get(order.uuid) - self.assertEqual(order, recovered) - - order.reviews.add(Review("GoodReview")) - await order.save() - - recovered = await Order.get(order.uuid) - self.assertEqual(order, recovered) - - order.reviews.discard(Review("GoodReview")) - await order.save() - - recovered = await Order.get(order.uuid) - self.assertEqual(order, recovered) - - -if __name__ == "__main__": - unittest.main() diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_injectors.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_injectors.py index c1572f1c2..b9b037bd4 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_injectors.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_injectors.py @@ -19,7 +19,7 @@ class TestRefInjector(AggregateTestCase): async def test_simple(self): - model = await Car.create(3, "test") + model = Car(3, "test") mapper = {model.uuid: model} expected = model @@ -28,7 +28,7 @@ async def test_simple(self): self.assertEqual(expected, observed) async def test_list(self): - model = await Car.create(3, "test") + model = Car(3, "test") mapper = {model.uuid: model} expected = [model, model, model] @@ -37,7 +37,7 @@ async def test_list(self): self.assertEqual(expected, observed) async def test_dict(self): - model = await Car.create(3, "test") + model = Car(3, "test") mapper = {model.uuid: model} expected = {model: model} diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_services.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_services.py index e552e9104..aeebaaca9 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_services.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_services.py @@ -10,7 +10,7 @@ from minos.aggregate import ( RefResolver, - RootEntity, + SnapshotRepository, SnapshotService, ) from minos.common import ( @@ -51,14 +51,14 @@ async def test_get_many(self): uuids = [uuid4(), uuid4()] expected = [Agg(u) for u in uuids] - with patch.object(RootEntity, "get", side_effect=expected): + with patch.object(SnapshotRepository, "get", side_effect=expected): response = await self.service.__get_many__(InMemoryRequest({"uuids": uuids})) self.assertEqual(expected, await response.content()) async def test_get_many_raises(self): with self.assertRaises(ResponseException): await self.service.__get_many__(InMemoryRequest()) - with patch.object(RootEntity, "get", side_effect=ValueError): + with patch.object(SnapshotRepository, "get", side_effect=ValueError): with self.assertRaises(ResponseException): await self.service.__get_many__(InMemoryRequest({"uuids": [uuid4()]})) diff --git a/packages/core/minos-microservice-aggregate/tests/utils.py b/packages/core/minos-microservice-aggregate/tests/utils.py index 4d1495332..5d1bb900f 100644 --- a/packages/core/minos-microservice-aggregate/tests/utils.py +++ b/packages/core/minos-microservice-aggregate/tests/utils.py @@ -172,9 +172,8 @@ class Product(ExternalEntity): class OrderAggregate(Aggregate[Order]): """For testing purposes.""" - @staticmethod - async def create_order() -> UUID: + async def create_order(self) -> UUID: """For testing purposes.""" - order = await Order.create(products=EntitySet(), reviews=ValueObjectSet()) + order, _ = await self.repository.create(Order, products=EntitySet(), reviews=ValueObjectSet()) return order.uuid From 0ed72aad5e42bdb19ce23b94a7456ea4daabccfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 27 Apr 2022 09:10:51 +0200 Subject: [PATCH 40/75] ISSUE #159 * Remove event sending logic from `EventRepository`. --- .../aggregate/events/repositories/abc.py | 51 -------- .../test_repositories/test_deltas.py | 83 +++++++++++++ .../test_models/test_root/test_broker.py | 112 ------------------ .../test_events/test_repositories/test_abc.py | 111 ----------------- 4 files changed, 83 insertions(+), 274 deletions(-) create mode 100644 packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_deltas.py delete mode 100644 packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_broker.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py index fc552bdaa..77f7a7afe 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py @@ -6,9 +6,6 @@ ABC, abstractmethod, ) -from asyncio import ( - gather, -) from contextlib import ( suppress, ) @@ -24,7 +21,6 @@ ) from minos.common import ( - NULL_UUID, Inject, Injectable, Lock, @@ -33,12 +29,6 @@ PoolFactory, classname, ) -from minos.networks import ( - BrokerMessageV1, - BrokerMessageV1Payload, - BrokerMessageV1Strategy, - BrokerPublisher, -) from minos.transactions import ( TRANSACTION_CONTEXT_VAR, TransactionalMixin, @@ -59,9 +49,6 @@ from ..entries import ( EventEntry, ) -from ..fields import ( - IncrementalFieldDiff, -) from ..models import ( Event, ) @@ -81,7 +68,6 @@ class EventRepository(ABC, TransactionalMixin): @Inject() def __init__( self, - broker_publisher: BrokerPublisher, lock_pool: Optional[LockPool] = None, pool_factory: Optional[PoolFactory] = None, *args, @@ -92,13 +78,9 @@ def __init__( if lock_pool is None and pool_factory is not None: lock_pool = pool_factory.get_pool("lock") - if broker_publisher is None: - raise NotProvidedException("A broker instance is required.") - if lock_pool is None: raise NotProvidedException("A lock pool instance is required.") - self._broker_publisher = broker_publisher self._lock_pool = lock_pool def transaction(self, **kwargs) -> TransactionEntry: @@ -163,9 +145,6 @@ async def submit(self, entry: Union[Event, EventEntry], **kwargs) -> EventEntry: entry = await self._submit(entry, **kwargs) - if entry.transaction_uuid == NULL_UUID: - await self._send_events(entry.event) - finally: IS_REPOSITORY_SERIALIZATION_CONTEXT_VAR.reset(token) @@ -202,36 +181,6 @@ async def validate(self, entry: EventEntry, transaction_uuid_ne: Optional[UUID] async def _submit(self, entry: EventEntry, **kwargs) -> EventEntry: raise NotImplementedError - async def _send_events(self, event: Event): - suffix_mapper = { - Action.CREATE: "Created", - Action.UPDATE: "Updated", - Action.DELETE: "Deleted", - } - topic = f"{event.simplified_name}{suffix_mapper[event.action]}" - message = BrokerMessageV1( - topic=topic, - payload=BrokerMessageV1Payload(content=event), - strategy=BrokerMessageV1Strategy.MULTICAST, - ) - futures = [self._broker_publisher.send(message)] - - if event.action == Action.UPDATE: - for decomposed_event in event.decompose(): - diff = next(iter(decomposed_event.fields_diff.flatten_values())) - composed_topic = f"{topic}.{diff.name}" - if isinstance(diff, IncrementalFieldDiff): - composed_topic += f".{diff.action.value}" - - message = BrokerMessageV1( - topic=composed_topic, - payload=BrokerMessageV1Payload(content=decomposed_event), - strategy=BrokerMessageV1Strategy.MULTICAST, - ) - futures.append(self._broker_publisher.send(message)) - - await gather(*futures) - # noinspection PyShadowingBuiltins async def select( self, diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_deltas.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_deltas.py new file mode 100644 index 000000000..21cb0ee22 --- /dev/null +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_deltas.py @@ -0,0 +1,83 @@ +import unittest +from typing import ( + Optional, +) + +from minos.aggregate import ( + Action, + EntityRepository, + Event, + FieldDiff, + FieldDiffContainer, + Ref, +) +from tests.utils import ( + AggregateTestCase, + Car, + Owner, +) + + +class TestEntityRepositoryDelta(AggregateTestCase): + def setUp(self) -> None: + super().setUp() + self.repository = EntityRepository() + + async def test_create(self): + car, delta = await self.repository.create(Car, doors=3, color="blue") + + self.assertEqual( + Event( + uuid=car.uuid, + name=Car.classname, + version=1, + action=Action.CREATE, + created_at=car.created_at, + fields_diff=FieldDiffContainer( + [ + FieldDiff("doors", int, 3), + FieldDiff("color", str, "blue"), + FieldDiff("owner", Optional[Ref[Owner]], None), + ] + ), + ), + delta, + ) + + async def test_update(self): + car, _ = await self.repository.create(Car, doors=3, color="blue") + + _, delta = await self.repository.update(car, color="red") + + self.assertEqual( + Event( + uuid=car.uuid, + name=Car.classname, + version=2, + action=Action.UPDATE, + created_at=car.updated_at, + fields_diff=FieldDiffContainer([FieldDiff("color", str, "red")]), + ), + delta, + ) + + async def test_delete(self): + car, _ = await self.repository.create(Car, doors=3, color="blue") + + delta = await self.repository.delete(car) + + self.assertEqual( + Event( + uuid=car.uuid, + name=Car.classname, + version=2, + action=Action.DELETE, + created_at=car.updated_at, + fields_diff=FieldDiffContainer.empty(), + ), + delta, + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_broker.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_broker.py deleted file mode 100644 index 7faa0e6fe..000000000 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_broker.py +++ /dev/null @@ -1,112 +0,0 @@ -import unittest -from typing import ( - Optional, -) - -from minos.aggregate import ( - Action, - Event, - FieldDiff, - FieldDiffContainer, - Ref, -) -from minos.networks import ( - BrokerMessageV1, -) -from tests.utils import ( - AggregateTestCase, - Car, - Owner, -) - - -@unittest.skip -class TestRootEntityBroker(AggregateTestCase): - async def test_create(self): - car = await Car.create(doors=3, color="blue") - - observed = self.broker_publisher.messages - - self.assertEqual(1, len(observed)) - self.assertIsInstance(observed[0], BrokerMessageV1) - self.assertEqual("CarCreated", observed[0].topic) - self.assertEqual( - Event( - uuid=car.uuid, - name=Car.classname, - version=1, - action=Action.CREATE, - created_at=car.created_at, - fields_diff=FieldDiffContainer( - [ - FieldDiff("doors", int, 3), - FieldDiff("color", str, "blue"), - FieldDiff("owner", Optional[Ref[Owner]], None), - ] - ), - ), - observed[0].content, - ) - - async def test_update(self): - car = await Car.create(doors=3, color="blue") - self.broker_publisher.messages.clear() - - await car.update(color="red") - - observed = self.broker_publisher.messages - - self.assertEqual(2, len(observed)) - self.assertIsInstance(observed[0], BrokerMessageV1) - self.assertEqual("CarUpdated", observed[0].topic) - self.assertEqual( - Event( - uuid=car.uuid, - name=Car.classname, - version=2, - action=Action.UPDATE, - created_at=car.updated_at, - fields_diff=FieldDiffContainer([FieldDiff("color", str, "red")]), - ), - observed[0].content, - ) - self.assertIsInstance(observed[1], BrokerMessageV1) - self.assertEqual("CarUpdated.color", observed[1].topic) - self.assertEqual( - Event( - uuid=car.uuid, - name=Car.classname, - version=2, - action=Action.UPDATE, - created_at=car.updated_at, - fields_diff=FieldDiffContainer([FieldDiff("color", str, "red")]), - ), - observed[1].content, - ) - - async def test_delete(self): - car = await Car.create(doors=3, color="blue") - self.broker_publisher.messages.clear() - - await car.delete() - - observed = self.broker_publisher.messages - - self.assertEqual(1, len(observed)) - self.assertIsInstance(observed[0], BrokerMessageV1) - self.assertEqual("CarDeleted", observed[0].topic) - self.assertEqual( - Event( - uuid=car.uuid, - name=Car.classname, - version=2, - action=Action.DELETE, - created_at=car.updated_at, - fields_diff=FieldDiffContainer.empty(), - ), - observed[0].content, - ) - - -if __name__ == "__main__": - unittest.main() diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py index 5331b4834..663409b89 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py @@ -26,7 +26,6 @@ EventRepositoryException, FieldDiff, FieldDiffContainer, - IncrementalFieldDiff, ) from minos.common import ( NULL_UUID, @@ -35,9 +34,6 @@ classname, current_datetime, ) -from minos.networks import ( - BrokerMessageV1, -) from minos.transactions import ( TRANSACTION_CONTEXT_VAR, TransactionEntry, @@ -80,14 +76,10 @@ def test_abstract(self): def test_constructor(self): repository = _EventRepository() - self.assertEqual(self.broker_publisher, repository._broker_publisher) self.assertEqual(self.transaction_repository, repository.transaction_repository) self.assertEqual(self.pool_factory.get_pool("lock"), repository._lock_pool) async def test_constructor_raises(self): - with self.assertRaises(NotProvidedException): - # noinspection PyTypeChecker - _EventRepository(broker_publisher=None) with self.assertRaises(NotProvidedException): # noinspection PyTypeChecker _EventRepository(transaction_repository=None) @@ -149,9 +141,7 @@ async def _fn(e: EventEntry) -> EventEntry: return e submit_mock = AsyncMock(side_effect=_fn) - send_events_mock = AsyncMock() self.event_repository._submit = submit_mock - self.event_repository._send_events = send_events_mock uuid = uuid4() event = Event( @@ -168,8 +158,6 @@ async def _fn(e: EventEntry) -> EventEntry: observed = await self.event_repository.submit(event) - self.assertEqual(1, send_events_mock.call_count) - self.assertIsInstance(observed, EventEntry) self.assertEqual(uuid, observed.uuid) self.assertEqual("example.Car", observed.name) @@ -195,9 +183,7 @@ async def _fn(e: EventEntry) -> EventEntry: return e submit_mock = AsyncMock(side_effect=_fn) - send_events_mock = AsyncMock() self.event_repository._submit = submit_mock - self.event_repository._send_events = send_events_mock uuid = uuid4() event = Event( @@ -214,8 +200,6 @@ async def _fn(e: EventEntry) -> EventEntry: observed = await self.event_repository.submit(event) - self.assertEqual(0, send_events_mock.call_count) - self.assertIsInstance(observed, EventEntry) self.assertEqual(uuid, observed.uuid) self.assertEqual("example.Car", observed.name) @@ -226,101 +210,6 @@ async def _fn(e: EventEntry) -> EventEntry: self.assertEqual(created_at, observed.created_at) self.assertEqual(transaction.uuid, observed.transaction_uuid) - async def test_submit_send_events(self): - created_at = current_datetime() - id_ = 12 - field_diff_container = FieldDiffContainer([IncrementalFieldDiff("colors", str, "red", Action.CREATE)]) - - async def _fn(e: EventEntry) -> EventEntry: - e.id = id_ - e.version = 56 - e.created_at = created_at - return e - - submit_mock = AsyncMock(side_effect=_fn) - self.event_repository._submit = submit_mock - - uuid = uuid4() - event = Event( - uuid=uuid, - name="example.Car", - version=2, - action=Action.UPDATE, - created_at=current_datetime(), - fields_diff=field_diff_container, - ) - - validate_mock = AsyncMock(return_value=True) - self.event_repository.validate = validate_mock - - await self.event_repository.submit(event) - - observed = self.broker_publisher.messages - - self.assertEqual(2, len(observed)) - self.assertIsInstance(observed[0], BrokerMessageV1) - self.assertEqual("CarUpdated", observed[0].topic) - self.assertEqual( - Event( - uuid=uuid, - name="example.Car", - version=56, - action=Action.UPDATE, - created_at=created_at, - fields_diff=field_diff_container, - ), - observed[0].content, - ) - self.assertEqual("CarUpdated.colors.create", observed[1].topic) - self.assertIsInstance(observed[1], BrokerMessageV1) - self.assertEqual( - Event( - uuid=uuid, - name="example.Car", - version=56, - action=Action.UPDATE, - created_at=created_at, - fields_diff=field_diff_container, - ), - observed[1].content, - ) - - async def test_submit_not_send_events(self): - created_at = current_datetime() - id_ = 12 - field_diff_container = FieldDiffContainer([IncrementalFieldDiff("colors", str, "red", Action.CREATE)]) - - async def _fn(e: EventEntry) -> EventEntry: - e.id = id_ - e.version = 56 - e.created_at = created_at - return e - - submit_mock = AsyncMock(side_effect=_fn) - self.event_repository._submit = submit_mock - - uuid = uuid4() - event = EventEntry.from_event( - Event( - uuid=uuid, - name="example.Car", - version=2, - action=Action.UPDATE, - created_at=current_datetime(), - fields_diff=field_diff_container, - ), - transaction_uuid=uuid4(), - ) - - validate_mock = AsyncMock(return_value=True) - self.event_repository.validate = validate_mock - - await self.event_repository.submit(event) - - observed = self.broker_publisher.messages - - self.assertEqual(0, len(observed)) - async def test_submit_raises_missing_action(self): entry = EventEntry(uuid4(), "example.Car", 0, bytes()) with self.assertRaises(EventRepositoryException): From a5a3c074022888152063df133a8e793cd01066a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 27 Apr 2022 09:23:50 +0200 Subject: [PATCH 41/75] ISSUE #159 * Move tests. --- .../test_entities/{test_models => }/test_repositories/__init__.py | 0 .../{test_models => }/test_repositories/test_base.py | 0 .../{test_models => }/test_repositories/test_deltas.py | 0 .../{test_models => }/test_repositories/test_integration.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/{test_models => }/test_repositories/__init__.py (100%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/{test_models => }/test_repositories/test_base.py (100%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/{test_models => }/test_repositories/test_deltas.py (100%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/{test_models => }/test_repositories/test_integration.py (100%) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/__init__.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/__init__.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/__init__.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/__init__.py diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_base.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_base.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_deltas.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_deltas.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_deltas.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_deltas.py diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_integration.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_integration.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_repositories/test_integration.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_integration.py From c0d82d526f47627c0cdfc96a39d35cb5233e19f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 27 Apr 2022 09:31:43 +0200 Subject: [PATCH 42/75] ISSUE #159 * Add support for instances on `EntityRepository.create`. * Minor improvements. --- .../minos/aggregate/entities/repositories.py | 57 +++++++++++-------- .../test_repositories/test_base.py | 11 +++- 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py index ee1cb98fc..38b74285c 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py @@ -5,6 +5,7 @@ from typing import ( Optional, TypeVar, + Union, ) from uuid import ( UUID, @@ -32,16 +33,16 @@ SnapshotRepository, ) from .models import ( - RootEntity, + Entity, ) logger = logging.getLogger(__name__) -T = TypeVar("T", bound=RootEntity) +T = TypeVar("T", bound=Entity) class EntityRepository: - """TODO""" + """Entity Repository class.""" _event_repository: EventRepository _snapshot_repository: SnapshotRepository @@ -64,38 +65,38 @@ def __init__( self._event_repository = event_repository self._snapshot_repository = snapshot_repository - async def get(self, cls: type[T], uuid: UUID, **kwargs) -> T: + async def get(self, type_: type[T], uuid: UUID, **kwargs) -> T: """Get one instance from the database based on its identifier. - :param cls: TODO + :param type_: The of the entity to be looked for. :param uuid: The identifier of the instance. - :return: A ``RootEntity`` instance. + :return: A ``Entity`` instance. """ # noinspection PyTypeChecker - return await self._snapshot_repository.get(cls.classname, uuid, **kwargs) + return await self._snapshot_repository.get(type_, uuid, **kwargs) def get_all( self, - cls: type[T], + type_: type[T], ordering: Optional[_Ordering] = None, limit: Optional[int] = None, **kwargs, ) -> AsyncIterator[T]: """Get all instance from the database. - :param cls: TODO + :param type_: The of the entity to be looked for. :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour is to retrieve them without any order pattern. :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the instances that meet the given condition. - :return: A ``RootEntity`` instance. + :return: A ``Entity`` instance. """ # noinspection PyTypeChecker - return self._snapshot_repository.get_all(cls.classname, ordering, limit, **kwargs) + return self._snapshot_repository.get_all(type_, ordering, limit, **kwargs) def find( self, - cls: type[T], + type_: type[T], condition: _Condition, ordering: Optional[_Ordering] = None, limit: Optional[int] = None, @@ -103,24 +104,25 @@ def find( ) -> AsyncIterator[T]: """Find a collection of instances based on a given ``Condition``. - :param cls: TODO + :param type_: The of the entity to be looked for. :param condition: The ``Condition`` that must be satisfied by all the instances. :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour is to retrieve them without any order pattern. :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the instances that meet the given condition. - :return: An asynchronous iterator of ``RootEntity`` instances. + :return: An asynchronous iterator of ``Entity`` instances. """ # noinspection PyTypeChecker - return self._snapshot_repository.find(cls.classname, condition, ordering, limit, **kwargs) + return self._snapshot_repository.find(type_, condition, ordering, limit, **kwargs) - async def create(self, cls: type[T], *args, **kwargs) -> tuple[T, Event]: - """Create a new ``RootEntity`` instance. + async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> tuple[T, Event]: + """Create a new ``Entity`` instance. - :param cls: TODO + :param type_or_instance: The instance to be created. If it is a ``type`` then the instance is created internally + using ``args`` and ``kwargs`` as parameters. :param args: Additional positional arguments. :param kwargs: Additional named arguments. - :return: A new ``RootEntity`` instance. + :return: A new ``Entity`` instance. """ if "uuid" in kwargs: raise EventRepositoryException( @@ -138,8 +140,15 @@ async def create(self, cls: type[T], *args, **kwargs) -> tuple[T, Event]: raise EventRepositoryException( f"The version must be computed internally on the repository. Obtained: {kwargs['updated_at']}" ) - - instance: T = cls(*args, **kwargs) + if isinstance(type_or_instance, type): + instance: T = type_or_instance(*args, **kwargs) + else: + instance = type_or_instance + if len(args) or len(kwargs): + raise EventRepositoryException( + f"Additional parameters are not provided when passing an already built {Entity!r} instance. " + f"Obtained: args={args!r}, kwargs={kwargs!r}" + ) event = Event.from_root_entity(instance) entry = await self._event_repository.submit(event) @@ -150,11 +159,11 @@ async def create(self, cls: type[T], *args, **kwargs) -> tuple[T, Event]: # noinspection PyMethodParameters,PyShadowingBuiltins async def update(self, instance: T, **kwargs) -> tuple[T, Optional[Event]]: - """Update an existing ``RootEntity`` instance. + """Update an existing ``Entity`` instance. - :param instance: TODO + :param instance: The instance to be updated. :param kwargs: Additional named arguments. - :return: An updated ``RootEntity`` instance. + :return: An updated ``Entity`` instance. """ if "version" in kwargs: diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py index 1638b6e6d..f08ccbb64 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py @@ -39,7 +39,7 @@ def test_constructor_raises(self): with self.assertRaises(NotProvidedException): EntityRepository(snapshot_repository=None) - async def test_create(self): + async def test_create_from_type(self): observed, _ = await self.repository.create(Car, doors=3, color="blue") expected = Car( 3, @@ -51,6 +51,11 @@ async def test_create(self): ) self.assertEqual(expected, observed) + async def test_create_from_instance(self): + instance = Car(doors=3, color="blue") + observed, _ = await self.repository.create(instance) + self.assertEqual(instance, observed) + async def test_create_raises(self): with self.assertRaises(EventRepositoryException): await self.repository.create(Car, uuid=uuid4(), doors=3, color="blue") @@ -60,6 +65,10 @@ async def test_create_raises(self): await self.repository.create(Car, created_at=current_datetime(), doors=3, color="blue") with self.assertRaises(EventRepositoryException): await self.repository.create(Car, updated_at=current_datetime(), doors=3, color="blue") + with self.assertRaises(EventRepositoryException): + await self.repository.create(Car(doors=3, color="blue"), "foo") + with self.assertRaises(EventRepositoryException): + await self.repository.create(Car(doors=3, color="blue"), foo="bar") async def test_classname(self): self.assertEqual("tests.utils.Car", Car.classname) From 46d5be61227e2125372d6ec559fda34338930201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 27 Apr 2022 09:34:51 +0200 Subject: [PATCH 43/75] ISSUE #159 * Minor change. --- .../minos/aggregate/entities/repositories.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py index 38b74285c..5c82ffaac 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py @@ -33,12 +33,12 @@ SnapshotRepository, ) from .models import ( - Entity, + RootEntity, ) logger = logging.getLogger(__name__) -T = TypeVar("T", bound=Entity) +T = TypeVar("T", bound=RootEntity) class EntityRepository: @@ -70,7 +70,7 @@ async def get(self, type_: type[T], uuid: UUID, **kwargs) -> T: :param type_: The of the entity to be looked for. :param uuid: The identifier of the instance. - :return: A ``Entity`` instance. + :return: A ``RootEntity`` instance. """ # noinspection PyTypeChecker return await self._snapshot_repository.get(type_, uuid, **kwargs) @@ -89,7 +89,7 @@ def get_all( is to retrieve them without any order pattern. :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the instances that meet the given condition. - :return: A ``Entity`` instance. + :return: A ``RootEntity`` instance. """ # noinspection PyTypeChecker return self._snapshot_repository.get_all(type_, ordering, limit, **kwargs) @@ -110,19 +110,19 @@ def find( is to retrieve them without any order pattern. :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the instances that meet the given condition. - :return: An asynchronous iterator of ``Entity`` instances. + :return: An asynchronous iterator of ``RootEntity`` instances. """ # noinspection PyTypeChecker return self._snapshot_repository.find(type_, condition, ordering, limit, **kwargs) async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> tuple[T, Event]: - """Create a new ``Entity`` instance. + """Create a new ``RootEntity`` instance. :param type_or_instance: The instance to be created. If it is a ``type`` then the instance is created internally using ``args`` and ``kwargs`` as parameters. :param args: Additional positional arguments. :param kwargs: Additional named arguments. - :return: A new ``Entity`` instance. + :return: A new ``RootEntity`` instance. """ if "uuid" in kwargs: raise EventRepositoryException( @@ -146,7 +146,7 @@ async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> instance = type_or_instance if len(args) or len(kwargs): raise EventRepositoryException( - f"Additional parameters are not provided when passing an already built {Entity!r} instance. " + f"Additional parameters are not provided when passing an already built {RootEntity!r} instance. " f"Obtained: args={args!r}, kwargs={kwargs!r}" ) @@ -159,11 +159,11 @@ async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> # noinspection PyMethodParameters,PyShadowingBuiltins async def update(self, instance: T, **kwargs) -> tuple[T, Optional[Event]]: - """Update an existing ``Entity`` instance. + """Update an existing ``RootEntity`` instance. :param instance: The instance to be updated. :param kwargs: Additional named arguments. - :return: An updated ``Entity`` instance. + :return: An updated ``RootEntity`` instance. """ if "version" in kwargs: From cb3e52098aaf02eba662c5825cc792d7598c09dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 27 Apr 2022 11:29:56 +0200 Subject: [PATCH 44/75] ISSUE #159 * Add `Aggregate.send_domain_event`. --- .../minos/aggregate/impl.py | 42 ++++++ .../tests/test_aggregate/test_impl.py | 140 ++++++++++++++++-- 2 files changed, 173 insertions(+), 9 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py index 8e09076d2..59ace1f40 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py @@ -2,8 +2,12 @@ annotations, ) +from asyncio import ( + gather, +) from typing import ( Generic, + Optional, TypeVar, get_args, ) @@ -16,18 +20,25 @@ SetupMixin, ) from minos.networks import ( + BrokerMessageV1, + BrokerMessageV1Payload, BrokerPublisher, ) from minos.transactions import ( TransactionRepository, ) +from .actions import ( + Action, +) from .entities import ( EntityRepository, RootEntity, ) from .events import ( + Event, EventRepository, + IncrementalFieldDiff, ) from .snapshots import ( SnapshotRepository, @@ -119,3 +130,34 @@ def root(self) -> type[RootEntity]: if not isinstance(root, type) or not issubclass(root, RootEntity): raise TypeError(f"{type(self)!r} must contain a {RootEntity!r} as generic value.") return root + + async def send_domain_event(self, delta: Optional[Event]) -> None: + """Send a domain event message containing a delta. + + :param delta: The delta to be sent. + :return: This method does not return anything. + """ + + if delta is None: + return + + suffix_mapper = { + Action.CREATE: "Created", + Action.UPDATE: "Updated", + Action.DELETE: "Deleted", + } + topic = f"{delta.simplified_name}{suffix_mapper[delta.action]}" + message = BrokerMessageV1(topic, BrokerMessageV1Payload(delta)) + futures = [self.broker_publisher.send(message)] + + if delta.action == Action.UPDATE: + for decomposed_event in delta.decompose(): + diff = next(iter(decomposed_event.fields_diff.flatten_values())) + composed_topic = f"{topic}.{diff.name}" + if isinstance(diff, IncrementalFieldDiff): + composed_topic += f".{diff.action.value}" + + message = BrokerMessageV1(composed_topic, BrokerMessageV1Payload(decomposed_event)) + futures.append(self.broker_publisher.send(message)) + + await gather(*futures) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py index 406cd23f4..11924c046 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py @@ -1,44 +1,68 @@ import unittest +from typing import ( + Optional, +) from unittest.mock import ( patch, ) from uuid import ( UUID, + uuid4, ) from minos.aggregate import ( + Action, Aggregate, + Event, + FieldDiff, + FieldDiffContainer, + IncrementalFieldDiff, + Ref, ) from minos.common import ( Config, NotProvidedException, + current_datetime, ) from minos.networks import ( + BrokerMessageV1, InMemoryBrokerPublisher, ) from tests.utils import ( CONFIG_FILE_PATH, AggregateTestCase, + Car, Order, OrderAggregate, + Owner, ) class TestAggregate(AggregateTestCase): + def setUp(self) -> None: + super().setUp() + self.aggregate = OrderAggregate.from_config(self.config) + + async def asyncSetUp(self) -> None: + await super().asyncSetUp() + await self.aggregate.setup() + + async def asyncTearDown(self) -> None: + await self.aggregate.destroy() + await super().asyncTearDown() + async def test_root(self): - async with OrderAggregate.from_config(CONFIG_FILE_PATH) as aggregate: - self.assertEqual(Order, aggregate.root) + self.assertEqual(Order, self.aggregate.root) def test_root_raises(self): with self.assertRaises(TypeError): Aggregate.from_config(CONFIG_FILE_PATH) async def test_from_config(self): - async with OrderAggregate.from_config(CONFIG_FILE_PATH) as aggregate: - self.assertEqual(self.transaction_repository, aggregate.transaction_repository) - self.assertEqual(self.event_repository, aggregate.event_repository) - self.assertEqual(self.snapshot_repository, aggregate.snapshot_repository) - self.assertEqual(self.broker_publisher, aggregate.broker_publisher) + self.assertEqual(self.transaction_repository, self.aggregate.transaction_repository) + self.assertEqual(self.event_repository, self.aggregate.event_repository) + self.assertEqual(self.snapshot_repository, self.aggregate.snapshot_repository) + self.assertEqual(self.broker_publisher, self.aggregate.broker_publisher) async def test_from_config_with_custom_publisher(self): with patch.object(Config, "get_aggregate", return_value={"publisher": {"client": InMemoryBrokerPublisher}}): @@ -60,10 +84,108 @@ def test_from_config_raises(self): OrderAggregate.from_config(CONFIG_FILE_PATH, broker_publisher=None) async def test_call(self): - async with OrderAggregate.from_config(CONFIG_FILE_PATH) as aggregate: - uuid = await aggregate.create_order() + uuid = await self.aggregate.create_order() self.assertIsInstance(uuid, UUID) + async def test_send_domain_event_none(self): + await self.aggregate.send_domain_event(None) + self.assertEqual(list(), self.broker_publisher.messages) + + async def test_send_domain_event_create(self): + delta = Event( + uuid=uuid4(), + name=Car.classname, + version=1, + action=Action.CREATE, + created_at=current_datetime(), + fields_diff=FieldDiffContainer( + [ + FieldDiff("doors", int, 3), + FieldDiff("color", str, "blue"), + FieldDiff("owner", Optional[Ref[Owner]], None), + ] + ), + ) + await self.aggregate.send_domain_event(delta) + + observed = self.broker_publisher.messages + + self.assertEqual(1, len(observed)) + self.assertIsInstance(observed[0], BrokerMessageV1) + self.assertEqual("CarCreated", observed[0].topic) + self.assertEqual(delta, observed[0].content) + + async def test_send_domain_event_update(self): + delta = Event( + uuid=uuid4(), + name=Car.classname, + version=2, + action=Action.UPDATE, + created_at=current_datetime(), + fields_diff=FieldDiffContainer( + [ + FieldDiff("color", str, "red"), + IncrementalFieldDiff("doors", int, 5, Action.CREATE), + ] + ), + ) + + await self.aggregate.send_domain_event(delta) + + observed = self.broker_publisher.messages + + self.assertEqual(3, len(observed)) + self.assertIsInstance(observed[0], BrokerMessageV1) + self.assertEqual("CarUpdated", observed[0].topic) + self.assertEqual(delta, observed[0].content) + + self.assertIsInstance(observed[1], BrokerMessageV1) + self.assertEqual("CarUpdated.color", observed[1].topic) + self.assertEqual( + Event( + uuid=delta.uuid, + name=Car.classname, + version=2, + action=Action.UPDATE, + created_at=delta.created_at, + fields_diff=FieldDiffContainer([FieldDiff("color", str, "red")]), + ), + observed[1].content, + ) + + self.assertIsInstance(observed[2], BrokerMessageV1) + self.assertEqual("CarUpdated.doors.create", observed[2].topic) + self.assertEqual( + Event( + uuid=delta.uuid, + name=Car.classname, + version=2, + action=Action.UPDATE, + created_at=delta.created_at, + fields_diff=FieldDiffContainer([IncrementalFieldDiff("doors", int, 5, Action.CREATE)]), + ), + observed[2].content, + ) + + async def test_send_domain_event_delete(self): + delta = Event( + uuid=uuid4(), + name=Car.classname, + version=2, + action=Action.DELETE, + created_at=current_datetime(), + fields_diff=FieldDiffContainer.empty(), + ) + + await self.aggregate.send_domain_event(delta) + + observed = self.broker_publisher.messages + + self.assertEqual(1, len(observed)) + self.assertIsInstance(observed[0], BrokerMessageV1) + self.assertEqual("CarDeleted", observed[0].topic) + self.assertEqual(delta, observed[0].content) + if __name__ == "__main__": unittest.main() From 630b7412ab660b925b6c3bc5ad53dcf1d6f8da4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 27 Apr 2022 11:32:20 +0200 Subject: [PATCH 45/75] ISSUE #159 * Rename `send_domain_event` as `publish_domain_event`. --- .../minos/aggregate/impl.py | 2 +- .../tests/test_aggregate/test_impl.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py index 59ace1f40..57f3011e9 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py @@ -131,7 +131,7 @@ def root(self) -> type[RootEntity]: raise TypeError(f"{type(self)!r} must contain a {RootEntity!r} as generic value.") return root - async def send_domain_event(self, delta: Optional[Event]) -> None: + async def publish_domain_event(self, delta: Optional[Event]) -> None: """Send a domain event message containing a delta. :param delta: The delta to be sent. diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py index 11924c046..bba41062e 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py @@ -87,11 +87,11 @@ async def test_call(self): uuid = await self.aggregate.create_order() self.assertIsInstance(uuid, UUID) - async def test_send_domain_event_none(self): - await self.aggregate.send_domain_event(None) + async def test_publish_domain_event_none(self): + await self.aggregate.publish_domain_event(None) self.assertEqual(list(), self.broker_publisher.messages) - async def test_send_domain_event_create(self): + async def test_publish_domain_event_create(self): delta = Event( uuid=uuid4(), name=Car.classname, @@ -106,7 +106,7 @@ async def test_send_domain_event_create(self): ] ), ) - await self.aggregate.send_domain_event(delta) + await self.aggregate.publish_domain_event(delta) observed = self.broker_publisher.messages @@ -115,7 +115,7 @@ async def test_send_domain_event_create(self): self.assertEqual("CarCreated", observed[0].topic) self.assertEqual(delta, observed[0].content) - async def test_send_domain_event_update(self): + async def test_publish_domain_event_update(self): delta = Event( uuid=uuid4(), name=Car.classname, @@ -130,7 +130,7 @@ async def test_send_domain_event_update(self): ), ) - await self.aggregate.send_domain_event(delta) + await self.aggregate.publish_domain_event(delta) observed = self.broker_publisher.messages @@ -167,7 +167,7 @@ async def test_send_domain_event_update(self): observed[2].content, ) - async def test_send_domain_event_delete(self): + async def test_publish_domain_event_delete(self): delta = Event( uuid=uuid4(), name=Car.classname, @@ -177,7 +177,7 @@ async def test_send_domain_event_delete(self): fields_diff=FieldDiffContainer.empty(), ) - await self.aggregate.send_domain_event(delta) + await self.aggregate.publish_domain_event(delta) observed = self.broker_publisher.messages From c477176a99818275ab3014439d3470d8db627855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 27 Apr 2022 12:04:40 +0200 Subject: [PATCH 46/75] ISSUE #413 * Rename `Event` as `Delta`. --- .../minos/aggregate/__init__.py | 26 +-- .../aggregate/{events => deltas}/__init__.py | 12 +- .../aggregate/{events => deltas}/entries.py | 38 ++-- .../aggregate/{events => deltas}/fields.py | 0 .../aggregate/{events => deltas}/models.py | 32 +-- .../aggregate/deltas/repositories/__init__.py | 10 + .../{events => deltas}/repositories/abc.py | 42 ++-- .../deltas/repositories/database/__init__.py | 6 + .../repositories/database/factories.py | 14 +- .../repositories/database/impl.py | 24 +-- .../{events => deltas}/repositories/memory.py | 20 +- .../minos/aggregate/entities/models.py | 40 ++-- .../minos/aggregate/entities/repositories.py | 76 +++---- .../aggregate/events/repositories/__init__.py | 10 - .../events/repositories/database/__init__.py | 6 - .../minos/aggregate/exceptions.py | 20 +- .../minos/aggregate/impl.py | 32 +-- .../minos/aggregate/snapshots/entries.py | 10 +- .../aggregate/snapshots/repositories/abc.py | 2 +- .../snapshots/repositories/database/impl.py | 66 +++--- .../snapshots/repositories/memory.py | 32 +-- .../minos/aggregate/testing/__init__.py | 6 +- .../aggregate/testing/deltas/__init__.py | 4 + .../testing/deltas/repositories/__init__.py | 6 + .../repositories/factories.py | 8 +- .../repositories/testcases.py | 144 ++++++------- .../aggregate/testing/events/__init__.py | 4 - .../testing/events/repositories/__init__.py | 6 - .../snapshots/repositories/testcases.py | 48 ++--- .../{test_events => test_deltas}/__init__.py | 0 .../test_entries.py | 54 ++--- .../test_fields.py | 6 +- .../test_models.py | 46 ++--- .../test_repositories/__init__.py | 0 .../test_repositories/test_abc.py | 192 +++++++++--------- .../test_repositories/test_database.py | 12 +- .../test_repositories/test_memory.py | 12 +- .../test_models/test_root/test_differences.py | 8 +- .../test_repositories/test_base.py | 26 +-- .../test_repositories/test_deltas.py | 8 +- .../tests/test_aggregate/test_exceptions.py | 22 +- .../tests/test_aggregate/test_impl.py | 18 +- .../test_snapshots/test_entries.py | 22 +- .../test_repositories/test_database.py | 4 +- .../test_repositories/test_memory.py | 2 +- .../tests/utils.py | 8 +- 46 files changed, 592 insertions(+), 592 deletions(-) rename packages/core/minos-microservice-aggregate/minos/aggregate/{events => deltas}/__init__.py (54%) rename packages/core/minos-microservice-aggregate/minos/aggregate/{events => deltas}/entries.py (83%) rename packages/core/minos-microservice-aggregate/minos/aggregate/{events => deltas}/fields.py (100%) rename packages/core/minos-microservice-aggregate/minos/aggregate/{events => deltas}/models.py (88%) create mode 100644 packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/__init__.py rename packages/core/minos-microservice-aggregate/minos/aggregate/{events => deltas}/repositories/abc.py (88%) create mode 100644 packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/database/__init__.py rename packages/core/minos-microservice-aggregate/minos/aggregate/{events => deltas}/repositories/database/factories.py (91%) rename packages/core/minos-microservice-aggregate/minos/aggregate/{events => deltas}/repositories/database/impl.py (78%) rename packages/core/minos-microservice-aggregate/minos/aggregate/{events => deltas}/repositories/memory.py (89%) delete mode 100644 packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/__init__.py delete mode 100644 packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/__init__.py create mode 100644 packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/__init__.py create mode 100644 packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/repositories/__init__.py rename packages/core/minos-microservice-aggregate/minos/aggregate/testing/{events => deltas}/repositories/factories.py (89%) rename packages/core/minos-microservice-aggregate/minos/aggregate/testing/{events => deltas}/repositories/testcases.py (72%) delete mode 100644 packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/__init__.py delete mode 100644 packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/__init__.py rename packages/core/minos-microservice-aggregate/tests/test_aggregate/{test_events => test_deltas}/__init__.py (100%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/{test_events => test_deltas}/test_entries.py (83%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/{test_events => test_deltas}/test_fields.py (98%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/{test_events => test_deltas}/test_models.py (88%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/{test_events => test_deltas}/test_repositories/__init__.py (100%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/{test_events => test_deltas}/test_repositories/test_abc.py (66%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/{test_events => test_deltas}/test_repositories/test_database.py (98%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/{test_events => test_deltas}/test_repositories/test_memory.py (52%) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py index 3aeefe81f..7447ee075 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py @@ -15,6 +15,17 @@ from .contextvars import ( IS_REPOSITORY_SERIALIZATION_CONTEXT_VAR, ) +from .deltas import ( + DatabaseDeltaRepository, + Delta, + DeltaDatabaseOperationFactory, + DeltaEntry, + DeltaRepository, + FieldDiff, + FieldDiffContainer, + IncrementalFieldDiff, + InMemoryDeltaRepository, +) from .entities import ( Entity, EntityRepository, @@ -26,22 +37,11 @@ RefResolver, RootEntity, ) -from .events import ( - DatabaseEventRepository, - Event, - EventDatabaseOperationFactory, - EventEntry, - EventRepository, - FieldDiff, - FieldDiffContainer, - IncrementalFieldDiff, - InMemoryEventRepository, -) from .exceptions import ( AggregateException, AlreadyDeletedException, - EventRepositoryConflictException, - EventRepositoryException, + DeltaRepositoryConflictException, + DeltaRepositoryException, NotFoundException, RefException, SnapshotRepositoryConflictException, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/__init__.py similarity index 54% rename from packages/core/minos-microservice-aggregate/minos/aggregate/events/__init__.py rename to packages/core/minos-microservice-aggregate/minos/aggregate/deltas/__init__.py index 08f4df4da..682ba90f3 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/__init__.py @@ -1,5 +1,5 @@ from .entries import ( - EventEntry, + DeltaEntry, ) from .fields import ( FieldDiff, @@ -7,11 +7,11 @@ IncrementalFieldDiff, ) from .models import ( - Event, + Delta, ) from .repositories import ( - DatabaseEventRepository, - EventDatabaseOperationFactory, - EventRepository, - InMemoryEventRepository, + DatabaseDeltaRepository, + DeltaDatabaseOperationFactory, + DeltaRepository, + InMemoryDeltaRepository, ) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/entries.py similarity index 83% rename from packages/core/minos-microservice-aggregate/minos/aggregate/events/entries.py rename to packages/core/minos-microservice-aggregate/minos/aggregate/deltas/entries.py index 2d33a57f7..1d95f63e6 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/entries.py @@ -28,7 +28,7 @@ FieldDiffContainer, ) from .models import ( - Event, + Delta, ) if TYPE_CHECKING: @@ -40,8 +40,8 @@ ) -class EventEntry: - """Class that represents an entry (or row) on the event repository database which stores the root entity changes.""" +class DeltaEntry: + """Class that represents an entry (or row) on the delta repository database which stores the root entity changes.""" __slots__ = ( "uuid", @@ -82,33 +82,33 @@ def __init__( self.transaction_uuid = transaction_uuid @classmethod - def from_event(cls, event: Event, *, transaction: Optional[TransactionEntry] = None, **kwargs) -> EventEntry: + def from_delta(cls, delta: Delta, *, transaction: Optional[TransactionEntry] = None, **kwargs) -> DeltaEntry: """Build a new instance from a ``RootEntity``. - :param event: The event. + :param delta: The delta. :param transaction: Optional transaction. :param kwargs: Additional named arguments. - :return: A new ``EventEntry`` instance. + :return: A new ``DeltaEntry`` instance. """ if transaction is not None: kwargs["transaction_uuid"] = transaction.uuid # noinspection PyTypeChecker return cls( - uuid=event.uuid, - name=event.name, - data=event.fields_diff.avro_bytes, - action=event.action, + uuid=delta.uuid, + name=delta.name, + data=delta.fields_diff.avro_bytes, + action=delta.action, **kwargs, ) @classmethod - def from_another(cls, another: EventEntry, **kwargs) -> EventEntry: - """Build a new instance from another ``EventEntry``. + def from_another(cls, another: DeltaEntry, **kwargs) -> DeltaEntry: + """Build a new instance from another ``DeltaEntry``. - :param another: The ``EventEntry``. + :param another: The ``DeltaEntry``. :param kwargs: Additional named arguments. - :return: A new ``EventEntry`` instance. + :return: A new ``DeltaEntry`` instance. """ return cls(**(another.as_raw() | kwargs | {"id": None})) @@ -138,12 +138,12 @@ def type_(self) -> type[RootEntity]: return import_module(self.name) @property - def event(self) -> Event: - """Get the stored ``Event`` instance. + def delta(self) -> Delta: + """Get the stored ``Delta`` instance. - :return: An ``Event`` instance. + :return: An ``Delta`` instance. """ - return Event( + return Delta( self.uuid, self.name, self.version, @@ -163,7 +163,7 @@ def field_diff_container(self) -> FieldDiffContainer: return FieldDiffContainer.from_avro_bytes(self.data) - def __eq__(self, other: "EventEntry") -> bool: + def __eq__(self, other: "DeltaEntry") -> bool: return type(self) == type(other) and tuple(self) == tuple(other) def __hash__(self) -> int: diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/fields.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/fields.py similarity index 100% rename from packages/core/minos-microservice-aggregate/minos/aggregate/events/fields.py rename to packages/core/minos-microservice-aggregate/minos/aggregate/deltas/fields.py diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/models.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py similarity index 88% rename from packages/core/minos-microservice-aggregate/minos/aggregate/events/models.py rename to packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py index 8e05918af..ccdea14c2 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/models.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py @@ -43,8 +43,8 @@ @total_ordering -class Event(DeclarativeModel): - """Event class.""" +class Delta(DeclarativeModel): + """Delta class.""" uuid: UUID name: str @@ -126,13 +126,13 @@ def get_fields(self, return_diff: bool = False) -> dict[str, Union[FieldDiff, An return self.fields_diff.get_all(return_diff) @classmethod - def from_difference(cls, a: RootEntity, b: RootEntity, action: Action = Action.UPDATE) -> Event: - """Build an ``Event`` instance from the difference of two instances. + def from_difference(cls, a: RootEntity, b: RootEntity, action: Action = Action.UPDATE) -> Delta: + """Build an ``Delta`` instance from the difference of two instances. :param a: One ``RootEntity`` instance. :param b: Another ``RootEntity`` instance. :param action: The action that generates the ``RootEntity`` difference. - :return: An ``Event`` instance. + :return: An ``Delta`` instance. """ logger.debug(f"Computing the {cls!r} between {a!r} and {b!r}...") @@ -155,12 +155,12 @@ def from_difference(cls, a: RootEntity, b: RootEntity, action: Action = Action.U ) @classmethod - def from_root_entity(cls, instance: RootEntity, action: Action = Action.CREATE) -> Event: - """Build an ``Event`` from a ``RootEntity`` (considering all fields as differences). + def from_root_entity(cls, instance: RootEntity, action: Action = Action.CREATE) -> Delta: + """Build an ``Delta`` from a ``RootEntity`` (considering all fields as differences). :param instance: A ``RootEntity`` instance. - :param action: The action that generates the event. - :return: An ``Event`` instance. + :param action: The action that generates the delta. + :return: An ``Delta`` instance. """ fields_diff = FieldDiffContainer.from_model(instance, ignore={"uuid", "version", "created_at", "updated_at"}) @@ -174,12 +174,12 @@ def from_root_entity(cls, instance: RootEntity, action: Action = Action.CREATE) ) @classmethod - def from_deleted_root_entity(cls, instance: RootEntity, action: Action = Action.DELETE) -> Event: - """Build an ``Event`` from a ``RootEntity`` (considering all fields as differences). + def from_deleted_root_entity(cls, instance: RootEntity, action: Action = Action.DELETE) -> Delta: + """Build an ``Delta`` from a ``RootEntity`` (considering all fields as differences). :param instance: A ``RootEntity`` instance. - :param action: The action that generates the event. - :return: An ``Event`` instance. + :param action: The action that generates the delta. + :return: An ``Delta`` instance. """ return cls( uuid=instance.uuid, @@ -190,10 +190,10 @@ def from_deleted_root_entity(cls, instance: RootEntity, action: Action = Action. fields_diff=FieldDiffContainer.empty(), ) - def decompose(self) -> list[Event]: - """Decompose the ``Event`` fields into multiple ``Event`` instances with once Field. + def decompose(self) -> list[Delta]: + """Decompose the ``Delta`` fields into multiple ``Delta`` instances with once Field. - :return: An list of``Event`` instances. + :return: An list of``Delta`` instances. """ return [ type(self)( diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/__init__.py new file mode 100644 index 000000000..64bd471ca --- /dev/null +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/__init__.py @@ -0,0 +1,10 @@ +from .abc import ( + DeltaRepository, +) +from .database import ( + DatabaseDeltaRepository, + DeltaDatabaseOperationFactory, +) +from .memory import ( + InMemoryDeltaRepository, +) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/abc.py similarity index 88% rename from packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py rename to packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/abc.py index 77f7a7afe..b457cb841 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/abc.py @@ -43,14 +43,14 @@ IS_REPOSITORY_SERIALIZATION_CONTEXT_VAR, ) from ...exceptions import ( - EventRepositoryConflictException, - EventRepositoryException, + DeltaRepositoryConflictException, + DeltaRepositoryException, ) from ..entries import ( - EventEntry, + DeltaEntry, ) from ..models import ( - Event, + Delta, ) if TYPE_CHECKING: @@ -59,9 +59,9 @@ ) -@Injectable("event_repository") -class EventRepository(ABC, TransactionalMixin): - """Base event repository class in ``minos``.""" +@Injectable("delta_repository") +class DeltaRepository(ABC, TransactionalMixin): + """Base delta repository class in ``minos``.""" _lock_pool: LockPool @@ -91,7 +91,7 @@ def transaction(self, **kwargs) -> TransactionEntry: """ return TransactionEntry(repository=self.transaction_repository, **kwargs) - async def create(self, entry: Union[Event, EventEntry]) -> EventEntry: + async def create(self, entry: Union[Delta, DeltaEntry]) -> DeltaEntry: """Store new creation entry into the repository. :param entry: Entry to be stored. @@ -101,7 +101,7 @@ async def create(self, entry: Union[Event, EventEntry]) -> EventEntry: entry.action = Action.CREATE return await self.submit(entry) - async def update(self, entry: Union[Event, EventEntry]) -> EventEntry: + async def update(self, entry: Union[Delta, DeltaEntry]) -> DeltaEntry: """Store new update entry into the repository. :param entry: Entry to be stored. @@ -111,7 +111,7 @@ async def update(self, entry: Union[Event, EventEntry]) -> EventEntry: entry.action = Action.UPDATE return await self.submit(entry) - async def delete(self, entry: Union[Event, EventEntry]) -> EventEntry: + async def delete(self, entry: Union[Delta, DeltaEntry]) -> DeltaEntry: """Store new deletion entry into the repository. :param entry: Entry to be stored. @@ -121,7 +121,7 @@ async def delete(self, entry: Union[Event, EventEntry]) -> EventEntry: entry.action = Action.DELETE return await self.submit(entry) - async def submit(self, entry: Union[Event, EventEntry], **kwargs) -> EventEntry: + async def submit(self, entry: Union[Delta, DeltaEntry], **kwargs) -> DeltaEntry: """Store new entry into the repository. :param entry: The entry to be stored. @@ -133,15 +133,15 @@ async def submit(self, entry: Union[Event, EventEntry], **kwargs) -> EventEntry: try: transaction = TRANSACTION_CONTEXT_VAR.get() - if isinstance(entry, Event): - entry = EventEntry.from_event(entry, transaction=transaction) + if isinstance(entry, Delta): + entry = DeltaEntry.from_delta(entry, transaction=transaction) if not isinstance(entry.action, Action): - raise EventRepositoryException("The 'EventEntry.action' attribute must be an 'Action' instance.") + raise DeltaRepositoryException("The 'DeltaEntry.action' attribute must be an 'Action' instance.") async with self.write_lock(): if not await self.validate(entry, **kwargs): - raise EventRepositoryConflictException(f"{entry!r} could not be committed!", await self.offset) + raise DeltaRepositoryConflictException(f"{entry!r} could not be committed!", await self.offset) entry = await self._submit(entry, **kwargs) @@ -151,7 +151,7 @@ async def submit(self, entry: Union[Event, EventEntry], **kwargs) -> EventEntry: return entry # noinspection PyUnusedLocal - async def validate(self, entry: EventEntry, transaction_uuid_ne: Optional[UUID] = None, **kwargs) -> bool: + async def validate(self, entry: DeltaEntry, transaction_uuid_ne: Optional[UUID] = None, **kwargs) -> bool: """Check if it is able to submit the given entry. :param entry: The entry to be validated. @@ -178,7 +178,7 @@ async def validate(self, entry: EventEntry, transaction_uuid_ne: Optional[UUID] return True @abstractmethod - async def _submit(self, entry: EventEntry, **kwargs) -> EventEntry: + async def _submit(self, entry: DeltaEntry, **kwargs) -> DeltaEntry: raise NotImplementedError # noinspection PyShadowingBuiltins @@ -200,7 +200,7 @@ async def select( transaction_uuid_ne: Optional[UUID] = None, transaction_uuid_in: Optional[tuple[UUID, ...]] = None, **kwargs, - ) -> AsyncIterator[EventEntry]: + ) -> AsyncIterator[DeltaEntry]: """Perform a selection query of entries stored in to the repository. :param uuid: The identifier must be equal to the given value. @@ -245,7 +245,7 @@ async def select( yield entry @abstractmethod - async def _select(self, *args, **kwargs) -> AsyncIterator[EventEntry]: + async def _select(self, *args, **kwargs) -> AsyncIterator[DeltaEntry]: """Perform a selection query of entries stored in to the repository.""" @property @@ -266,7 +266,7 @@ def write_lock(self) -> Lock: :return: An asynchronous context manager. """ - return self._lock_pool.acquire("aggregate_event_write_lock") + return self._lock_pool.acquire("aggregate_delta_write_lock") async def get_collided_transactions(self, transaction_uuid: UUID) -> set[UUID]: """Get the set of collided transaction identifiers. @@ -295,5 +295,5 @@ async def commit_transaction(self, transaction_uuid: UUID, destination_transacti :return: This method does not return anything. """ async for entry in self.select(transaction_uuid=transaction_uuid): - new = EventEntry.from_another(entry, transaction_uuid=destination_transaction_uuid) + new = DeltaEntry.from_another(entry, transaction_uuid=destination_transaction_uuid) await self.submit(new, transaction_uuid_ne=transaction_uuid) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/database/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/database/__init__.py new file mode 100644 index 000000000..eb22003a7 --- /dev/null +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/database/__init__.py @@ -0,0 +1,6 @@ +from .factories import ( + DeltaDatabaseOperationFactory, +) +from .impl import ( + DatabaseDeltaRepository, +) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/factories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/database/factories.py similarity index 91% rename from packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/factories.py rename to packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/database/factories.py index 1860507f9..a35e1375f 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/factories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/database/factories.py @@ -25,12 +25,12 @@ ) -class EventDatabaseOperationFactory(DatabaseOperationFactory, ABC): - """Event Database Operation Factory base class.""" +class DeltaDatabaseOperationFactory(DatabaseOperationFactory, ABC): + """Delta Database Operation Factory base class.""" @abstractmethod def build_create(self) -> DatabaseOperation: - """Build the database operation to create the event table. + """Build the database operation to create the delta table. :return: A ``DatabaseOperation`` instance.s """ @@ -49,14 +49,14 @@ def build_submit( lock: Optional[int], **kwargs, ) -> DatabaseOperation: - """Build the database operation to submit a row into the event table. + """Build the database operation to submit a row into the delta table. - :param transaction_uuids: The sequence of nested transaction in on top of the current event's transaction. + :param transaction_uuids: The sequence of nested transaction in on top of the current delta's transaction. :param uuid: The identifier of the entity. - :param action: The action of the event. + :param action: The action of the delta. :param name: The name of the entity. :param version: The version of the entity - :param data: The data of the event. + :param data: The data of the delta. :param created_at: The creation datetime. :param transaction_uuid: The identifier of the transaction. :param lock: The lock identifier. diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/database/impl.py similarity index 78% rename from packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/impl.py rename to packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/database/impl.py index 42d492fa2..63cbbfb6d 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/database/impl.py @@ -15,25 +15,25 @@ ) from ....exceptions import ( - EventRepositoryConflictException, + DeltaRepositoryConflictException, ) from ...entries import ( - EventEntry, + DeltaEntry, ) from ..abc import ( - EventRepository, + DeltaRepository, ) from .factories import ( - EventDatabaseOperationFactory, + DeltaDatabaseOperationFactory, ) -class DatabaseEventRepository(DatabaseMixin[EventDatabaseOperationFactory], EventRepository): - """Database-based implementation of the event repository class.""" +class DatabaseDeltaRepository(DatabaseMixin[DeltaDatabaseOperationFactory], DeltaRepository): + """Database-based implementation of the delta repository class.""" def __init__(self, *args, database_key: Optional[tuple[str]] = None, **kwargs): if database_key is None: - database_key = ("aggregate", "event") + database_key = ("aggregate", "delta") super().__init__(*args, database_key=database_key, **kwargs) async def _setup(self) -> None: @@ -41,13 +41,13 @@ async def _setup(self) -> None: operation = self.database_operation_factory.build_create() await self.execute_on_database(operation) - async def _submit(self, entry: EventEntry, **kwargs) -> EventEntry: + async def _submit(self, entry: DeltaEntry, **kwargs) -> DeltaEntry: operation = await self._build_submit_operation(entry) try: response = await self.execute_on_database_and_fetch_one(operation) except IntegrityException: - raise EventRepositoryConflictException( + raise DeltaRepositoryConflictException( f"{entry!r} could not be submitted due to a key (uuid, version, transaction) collision", await self.offset, ) @@ -55,7 +55,7 @@ async def _submit(self, entry: EventEntry, **kwargs) -> EventEntry: entry.id, entry.uuid, entry.version, entry.created_at = response return entry - async def _build_submit_operation(self, entry: EventEntry) -> DatabaseOperation: + async def _build_submit_operation(self, entry: DeltaEntry) -> DatabaseOperation: lock = None if entry.uuid != NULL_UUID: lock = entry.uuid.int & (1 << 32) - 1 @@ -70,10 +70,10 @@ async def _build_submit_operation(self, entry: EventEntry) -> DatabaseOperation: transaction_uuids=transaction_uuids, **entry.as_raw(), lock=lock ) - async def _select(self, streaming_mode: Optional[bool] = None, **kwargs) -> AsyncIterator[EventEntry]: + async def _select(self, streaming_mode: Optional[bool] = None, **kwargs) -> AsyncIterator[DeltaEntry]: operation = self.database_operation_factory.build_query(**kwargs) async for row in self.execute_on_database_and_fetch_all(operation, streaming_mode=streaming_mode): - yield EventEntry(*row) + yield DeltaEntry(*row) @property async def _offset(self) -> int: diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/memory.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/memory.py similarity index 89% rename from packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/memory.py rename to packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/memory.py index 73dcd74f0..3c7786814 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/memory.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/memory.py @@ -23,18 +23,18 @@ ) from ...exceptions import ( - EventRepositoryConflictException, + DeltaRepositoryConflictException, ) from ..entries import ( - EventEntry, + DeltaEntry, ) from .abc import ( - EventRepository, + DeltaRepository, ) -class InMemoryEventRepository(EventRepository): - """Memory-based implementation of the event repository class in ``minos``.""" +class InMemoryDeltaRepository(DeltaRepository): + """Memory-based implementation of the delta repository class in ``minos``.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -42,7 +42,7 @@ def __init__(self, *args, **kwargs): self._id_generator = count() self._next_versions = defaultdict(int) - async def _submit(self, entry: EventEntry, **kwargs) -> EventEntry: + async def _submit(self, entry: DeltaEntry, **kwargs) -> DeltaEntry: if entry.uuid == NULL_UUID: entry.uuid = uuid4() @@ -50,7 +50,7 @@ async def _submit(self, entry: EventEntry, **kwargs) -> EventEntry: if entry.version is None: entry.version = next_version if entry.version < next_version: - raise EventRepositoryConflictException( + raise DeltaRepositoryConflictException( f"{entry!r} could not be submitted due to a key (uuid, version, transaction) collision", await self.offset, ) @@ -65,7 +65,7 @@ async def _submit(self, entry: EventEntry, **kwargs) -> EventEntry: def _generate_next_id(self) -> int: return next(self._id_generator) + 1 - def _get_next_version_id(self, entry: EventEntry) -> int: + def _get_next_version_id(self, entry: DeltaEntry) -> int: key = (entry.name, entry.uuid, entry.transaction_uuid) self._next_versions[key] += 1 return self._next_versions[key] @@ -89,10 +89,10 @@ async def _select( transaction_uuid_in: Optional[tuple[UUID, ...]] = None, *args, **kwargs, - ) -> AsyncIterator[EventEntry]: + ) -> AsyncIterator[DeltaEntry]: # noinspection DuplicatedCode - def _fn_filter(entry: EventEntry) -> bool: + def _fn_filter(entry: DeltaEntry) -> bool: if uuid is not None and uuid != entry.uuid: return False if name is not None and name != entry.name: diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py index 290d85456..7333c5b8d 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py @@ -22,8 +22,8 @@ DeclarativeModel, ) -from ..events import ( - Event, +from ..deltas import ( + Delta, IncrementalFieldDiff, ) @@ -72,7 +72,7 @@ def __init__( super().__init__(version, created_at, updated_at, *args, uuid=uuid, **kwargs) - def diff(self, another: RootEntity) -> Event: + def diff(self, another: RootEntity) -> Delta: """Compute the difference with another instance. Both ``RootEntity`` instances (``self`` and ``another``) must share the same ``uuid`` value. @@ -80,21 +80,21 @@ def diff(self, another: RootEntity) -> Event: :param another: Another ``RootEntity`` instance. :return: An ``FieldDiffContainer`` instance. """ - return Event.from_difference(self, another) + return Delta.from_difference(self, another) - def apply_diff(self, event: Event) -> None: + def apply_diff(self, delta: Delta) -> None: """Apply the differences over the instance. - :param event: The ``FieldDiffContainer`` containing the values to be set. + :param delta: The ``FieldDiffContainer`` containing the values to be set. :return: This method does not return anything. """ - if self.uuid != event.uuid: + if self.uuid != delta.uuid: raise ValueError( - f"To apply the difference, it must have same uuid. " f"Expected: {self.uuid!r} Obtained: {event.uuid!r}" + f"To apply the difference, it must have same uuid. " f"Expected: {self.uuid!r} Obtained: {delta.uuid!r}" ) - logger.debug(f"Applying {event!r} to {self!r}...") - for diff in event.fields_diff.flatten_values(): + logger.debug(f"Applying {delta!r} to {self!r}...") + for diff in delta.fields_diff.flatten_values(): if isinstance(diff, IncrementalFieldDiff): container = getattr(self, diff.name) if diff.action.is_delete: @@ -103,24 +103,24 @@ def apply_diff(self, event: Event) -> None: container.add(diff.value) else: setattr(self, diff.name, diff.value) - self.version = event.version - self.updated_at = event.created_at + self.version = delta.version + self.updated_at = delta.created_at @classmethod - def from_diff(cls: Type[T], event: Event, *args, **kwargs) -> T: - """Build a new instance from an ``Event``. + def from_diff(cls: Type[T], delta: Delta, *args, **kwargs) -> T: + """Build a new instance from an ``Delta``. - :param event: The difference that contains the data. + :param delta: The difference that contains the data. :param args: Additional positional arguments. :param kwargs: Additional named arguments. :return: A new ``RootEntity`` instance. """ return cls( *args, - uuid=event.uuid, - version=event.version, - created_at=event.created_at, - updated_at=event.created_at, - **event.get_fields(), + uuid=delta.uuid, + version=delta.version, + created_at=delta.created_at, + updated_at=delta.created_at, + **delta.get_fields(), **kwargs, ) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py index 5c82ffaac..28928aea0 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py @@ -17,13 +17,13 @@ NotProvidedException, ) -from ..events import ( - Event, - EventEntry, - EventRepository, +from ..deltas import ( + Delta, + DeltaEntry, + DeltaRepository, ) from ..exceptions import ( - EventRepositoryException, + DeltaRepositoryException, ) from ..queries import ( _Condition, @@ -44,25 +44,25 @@ class EntityRepository: """Entity Repository class.""" - _event_repository: EventRepository + _delta_repository: DeltaRepository _snapshot_repository: SnapshotRepository # noinspection PyUnusedLocal @Inject() def __init__( self, - event_repository: EventRepository, + delta_repository: DeltaRepository, snapshot_repository: SnapshotRepository, *args, **kwargs, ): - if event_repository is None: - raise NotProvidedException(f"A {EventRepository!r} instance is required.") + if delta_repository is None: + raise NotProvidedException(f"A {DeltaRepository!r} instance is required.") if snapshot_repository is None: raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") - self._event_repository = event_repository + self._delta_repository = delta_repository self._snapshot_repository = snapshot_repository async def get(self, type_: type[T], uuid: UUID, **kwargs) -> T: @@ -115,7 +115,7 @@ def find( # noinspection PyTypeChecker return self._snapshot_repository.find(type_, condition, ordering, limit, **kwargs) - async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> tuple[T, Event]: + async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> tuple[T, Delta]: """Create a new ``RootEntity`` instance. :param type_or_instance: The instance to be created. If it is a ``type`` then the instance is created internally @@ -125,19 +125,19 @@ async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> :return: A new ``RootEntity`` instance. """ if "uuid" in kwargs: - raise EventRepositoryException( + raise DeltaRepositoryException( f"The identifier must be computed internally on the repository. Obtained: {kwargs['uuid']}" ) if "version" in kwargs: - raise EventRepositoryException( + raise DeltaRepositoryException( f"The version must be computed internally on the repository. Obtained: {kwargs['version']}" ) if "created_at" in kwargs: - raise EventRepositoryException( + raise DeltaRepositoryException( f"The version must be computed internally on the repository. Obtained: {kwargs['created_at']}" ) if "updated_at" in kwargs: - raise EventRepositoryException( + raise DeltaRepositoryException( f"The version must be computed internally on the repository. Obtained: {kwargs['updated_at']}" ) if isinstance(type_or_instance, type): @@ -145,20 +145,20 @@ async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> else: instance = type_or_instance if len(args) or len(kwargs): - raise EventRepositoryException( + raise DeltaRepositoryException( f"Additional parameters are not provided when passing an already built {RootEntity!r} instance. " f"Obtained: args={args!r}, kwargs={kwargs!r}" ) - event = Event.from_root_entity(instance) - entry = await self._event_repository.submit(event) + delta = Delta.from_root_entity(instance) + entry = await self._delta_repository.submit(delta) self._update_from_repository_entry(instance, entry) - return instance, entry.event + return instance, entry.delta # noinspection PyMethodParameters,PyShadowingBuiltins - async def update(self, instance: T, **kwargs) -> tuple[T, Optional[Event]]: + async def update(self, instance: T, **kwargs) -> tuple[T, Optional[Delta]]: """Update an existing ``RootEntity`` instance. :param instance: The instance to be updated. @@ -167,15 +167,15 @@ async def update(self, instance: T, **kwargs) -> tuple[T, Optional[Event]]: """ if "version" in kwargs: - raise EventRepositoryException( + raise DeltaRepositoryException( f"The version must be computed internally on the repository. Obtained: {kwargs['version']}" ) if "created_at" in kwargs: - raise EventRepositoryException( + raise DeltaRepositoryException( f"The version must be computed internally on the repository. Obtained: {kwargs['created_at']}" ) if "updated_at" in kwargs: - raise EventRepositoryException( + raise DeltaRepositoryException( f"The version must be computed internally on the repository. Obtained: {kwargs['updated_at']}" ) @@ -183,17 +183,17 @@ async def update(self, instance: T, **kwargs) -> tuple[T, Optional[Event]]: setattr(instance, key, value) previous = await self.get(type(instance), instance.uuid) - event = instance.diff(previous) - if not len(event.fields_diff): + delta = instance.diff(previous) + if not len(delta.fields_diff): return instance - entry = await self._event_repository.submit(event) + entry = await self._delta_repository.submit(delta) self._update_from_repository_entry(instance, entry) - return instance, entry.event + return instance, entry.delta - async def save(self, instance: T) -> Optional[Event]: + async def save(self, instance: T) -> Optional[Delta]: """Store the current instance on the repository. If didn't exist previously creates a new one, otherwise updates the existing one. @@ -201,11 +201,11 @@ async def save(self, instance: T) -> Optional[Event]: is_creation = instance.uuid == NULL_UUID if is_creation != (instance.version == 0): if is_creation: - raise EventRepositoryException( + raise DeltaRepositoryException( f"The version must be computed internally on the repository. Obtained: {instance.version}" ) else: - raise EventRepositoryException( + raise DeltaRepositoryException( f"The uuid must be computed internally on the repository. Obtained: {instance.uuid}" ) @@ -215,11 +215,11 @@ async def save(self, instance: T) -> Optional[Event]: if k not in {"uuid", "version", "created_at", "updated_at"} } if is_creation: - new, event = await self.create(type(instance), **values) + new, delta = await self.create(type(instance), **values) instance._fields |= new.fields else: - _, event = await self.update(instance, **values) - return event + _, delta = await self.update(instance, **values) + return delta async def refresh(self, instance: T) -> None: """Refresh the state of the given instance. @@ -229,19 +229,19 @@ async def refresh(self, instance: T) -> None: new = await self.get(type(instance), instance.uuid) instance._fields |= new.fields - async def delete(self, instance: T) -> Event: + async def delete(self, instance: T) -> Delta: """Delete the given root entity instance. :return: This method does not return anything. """ - event = Event.from_deleted_root_entity(instance) - entry = await self._event_repository.submit(event) + delta = Delta.from_deleted_root_entity(instance) + entry = await self._delta_repository.submit(delta) self._update_from_repository_entry(instance, entry) - return entry.event + return entry.delta @staticmethod - def _update_from_repository_entry(instance: T, entry: EventEntry) -> None: + def _update_from_repository_entry(instance: T, entry: DeltaEntry) -> None: instance.uuid = entry.uuid instance.version = entry.version if entry.action.is_create: diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/__init__.py deleted file mode 100644 index d4c3e79b1..000000000 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -from .abc import ( - EventRepository, -) -from .database import ( - DatabaseEventRepository, - EventDatabaseOperationFactory, -) -from .memory import ( - InMemoryEventRepository, -) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/__init__.py deleted file mode 100644 index c37452705..000000000 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/events/repositories/database/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from .factories import ( - EventDatabaseOperationFactory, -) -from .impl import ( - DatabaseEventRepository, -) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py b/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py index 4f44d70d1..c0ab98e74 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py @@ -11,24 +11,24 @@ ) if TYPE_CHECKING: + from .deltas import ( + Delta, + ) from .entities import ( RootEntity, ) - from .events import ( - Event, - ) class AggregateException(MinosException): """Base Aggregate module exception""" -class EventRepositoryException(AggregateException): - """Base event repository exception.""" +class DeltaRepositoryException(AggregateException): + """Base delta repository exception.""" -class EventRepositoryConflictException(EventRepositoryException): - """Exception to be raised when some ``EventEntry`` raises a conflict.""" +class DeltaRepositoryConflictException(DeltaRepositoryException): + """Exception to be raised when some ``DeltaEntry`` raises a conflict.""" def __init__(self, error_message: str, offset: int): super().__init__(error_message) @@ -42,12 +42,12 @@ class SnapshotRepositoryException(AggregateException): class SnapshotRepositoryConflictException(SnapshotRepositoryException): """Exception to be raised when current version is newer than the one to be processed.""" - def __init__(self, previous: RootEntity, event: Event): + def __init__(self, previous: RootEntity, delta: Delta): self.previous = previous - self.event = event + self.delta = delta super().__init__( f"Version for {repr(previous.classname)} root entity must be " - f"greater than {previous.version}. Obtained: {event.version}" + f"greater than {previous.version}. Obtained: {delta.version}" ) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py index 57f3011e9..753ca5251 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py @@ -31,15 +31,15 @@ from .actions import ( Action, ) +from .deltas import ( + Delta, + DeltaRepository, + IncrementalFieldDiff, +) from .entities import ( EntityRepository, RootEntity, ) -from .events import ( - Event, - EventRepository, - IncrementalFieldDiff, -) from .snapshots import ( SnapshotRepository, ) @@ -52,7 +52,7 @@ class Aggregate(Generic[RT], SetupMixin): """Base Service class""" transaction_repository: TransactionRepository - event_repository: EventRepository + delta_repository: DeltaRepository snapshot_repository: SnapshotRepository repository: EntityRepository broker_publisher: BrokerPublisher @@ -61,7 +61,7 @@ class Aggregate(Generic[RT], SetupMixin): def __init__( self, transaction_repository: TransactionRepository, - event_repository: EventRepository, + delta_repository: DeltaRepository, snapshot_repository: SnapshotRepository, broker_publisher: BrokerPublisher, *args, @@ -69,8 +69,8 @@ def __init__( ): if transaction_repository is None: raise NotProvidedException(f"A {TransactionRepository!r} object must be provided.") - if event_repository is None: - raise NotProvidedException(f"A {EventRepository!r} object must be provided.") + if delta_repository is None: + raise NotProvidedException(f"A {DeltaRepository!r} object must be provided.") if snapshot_repository is None: raise NotProvidedException(f"A {SnapshotRepository!r} object must be provided.") if broker_publisher is None: @@ -80,10 +80,10 @@ def __init__( self._check_root() - self.repository = EntityRepository(event_repository, snapshot_repository) + self.repository = EntityRepository(delta_repository, snapshot_repository) self.transaction_repository = transaction_repository - self.event_repository = event_repository + self.delta_repository = delta_repository self.snapshot_repository = snapshot_repository self.broker_publisher = broker_publisher @@ -131,8 +131,8 @@ def root(self) -> type[RootEntity]: raise TypeError(f"{type(self)!r} must contain a {RootEntity!r} as generic value.") return root - async def publish_domain_event(self, delta: Optional[Event]) -> None: - """Send a domain event message containing a delta. + async def publish_domain_event(self, delta: Optional[Delta]) -> None: + """Send a domain delta message containing a delta. :param delta: The delta to be sent. :return: This method does not return anything. @@ -151,13 +151,13 @@ async def publish_domain_event(self, delta: Optional[Event]) -> None: futures = [self.broker_publisher.send(message)] if delta.action == Action.UPDATE: - for decomposed_event in delta.decompose(): - diff = next(iter(decomposed_event.fields_diff.flatten_values())) + for decomposed_delta in delta.decompose(): + diff = next(iter(decomposed_delta.fields_diff.flatten_values())) composed_topic = f"{topic}.{diff.name}" if isinstance(diff, IncrementalFieldDiff): composed_topic += f".{diff.action.value}" - message = BrokerMessageV1(composed_topic, BrokerMessageV1Payload(decomposed_event)) + message = BrokerMessageV1(composed_topic, BrokerMessageV1Payload(decomposed_delta)) futures.append(self.broker_publisher.send(message)) await gather(*futures) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py index 6a92f5078..c0ebdef96 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py @@ -23,8 +23,8 @@ import_module, ) -from ..events import ( - EventEntry, +from ..deltas import ( + DeltaEntry, ) from ..exceptions import ( AlreadyDeletedException, @@ -96,10 +96,10 @@ def from_root_entity(cls, instance: RootEntity, **kwargs) -> SnapshotEntry: ) @classmethod - def from_event_entry(cls, entry: EventEntry) -> SnapshotEntry: - """Build a new ``SnapshotEntry`` from a deletion event. + def from_delta_entry(cls, entry: DeltaEntry) -> SnapshotEntry: + """Build a new ``SnapshotEntry`` from a deletion delta. - :param entry: The event entry containing the delete information. + :param entry: The delta entry containing the delete information. :return: A new ``SnapshotEntry`` instance. """ return cls( diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py index 00530c1cf..51ae15417 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py @@ -50,7 +50,7 @@ class SnapshotRepository(ABC, SetupMixin): """Base Snapshot class. - The snapshot provides a direct accessor to the ``RootEntity`` instances stored as events by the event repository + The snapshot provides a direct accessor to the ``RootEntity`` instances stored as deltas by the delta repository class. """ diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py index 4777db37b..b5d9147e4 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py @@ -31,10 +31,10 @@ TransactionStatus, ) -from ....events import ( - Event, - EventEntry, - EventRepository, +from ....deltas import ( + Delta, + DeltaEntry, + DeltaRepository, ) from ....exceptions import ( NotFoundException, @@ -63,7 +63,7 @@ class DatabaseSnapshotRepository(SnapshotRepository, DatabaseMixin[SnapshotDatabaseOperationFactory]): """Database Snapshot Repository class. - The snapshot provides a direct accessor to the ``RootEntity`` instances stored as events by the event repository + The snapshot provides a direct accessor to the ``RootEntity`` instances stored as deltas by the delta repository class. """ @@ -71,7 +71,7 @@ class DatabaseSnapshotRepository(SnapshotRepository, DatabaseMixin[SnapshotDatab def __init__( self, *args, - event_repository: EventRepository, + delta_repository: DeltaRepository, transaction_repository: TransactionRepository, database_key: Optional[tuple[str]] = None, **kwargs, @@ -80,13 +80,13 @@ def __init__( database_key = ("aggregate", "snapshot") super().__init__(*args, database_key=database_key, **kwargs) - if event_repository is None: - raise NotProvidedException("An event repository instance is required.") + if delta_repository is None: + raise NotProvidedException("An delta repository instance is required.") if transaction_repository is None: raise NotProvidedException("A transaction repository instance is required.") - self._event_repository = event_repository + self._delta_repository = delta_repository self._transaction_repository = transaction_repository async def _setup(self) -> None: @@ -125,7 +125,7 @@ async def is_synced(self, name: str, **kwargs) -> bool: :return: ``True`` if it has the latest version for the identifier or ``False`` otherwise. """ offset = await self._load_offset() - iterable = self._event_repository.select(id_gt=offset, name=name, **kwargs) + iterable = self._delta_repository.select(id_gt=offset, name=name, **kwargs) try: await iterable.__anext__() return False @@ -137,12 +137,12 @@ async def _synchronize(self, **kwargs) -> None: transaction_uuids = set() offset = initial_offset - async for event_entry in self._event_repository.select(id_gt=offset, **kwargs): + async for delta_entry in self._delta_repository.select(id_gt=offset, **kwargs): with suppress(SnapshotRepositoryConflictException): - await self._dispatch_one(event_entry, **kwargs) + await self._dispatch_one(delta_entry, **kwargs) - offset = max(event_entry.id, offset) - transaction_uuids.add(event_entry.transaction_uuid) + offset = max(delta_entry.id, offset) + transaction_uuids.add(delta_entry.transaction_uuid) await self._clean_transactions(transaction_uuids) @@ -161,49 +161,49 @@ async def _store_offset(self, offset: int) -> None: operation = self.database_operation_factory.build_submit_offset(offset) await self.execute_on_database(operation) - async def _dispatch_one(self, event_entry: EventEntry, **kwargs) -> SnapshotEntry: - if event_entry.action.is_delete: - return await self._submit_delete(event_entry) + async def _dispatch_one(self, delta_entry: DeltaEntry, **kwargs) -> SnapshotEntry: + if delta_entry.action.is_delete: + return await self._submit_delete(delta_entry) - return await self._submit_update_or_create(event_entry, **kwargs) + return await self._submit_update_or_create(delta_entry, **kwargs) - async def _submit_delete(self, event_entry: EventEntry) -> SnapshotEntry: - snapshot_entry = SnapshotEntry.from_event_entry(event_entry) + async def _submit_delete(self, delta_entry: DeltaEntry) -> SnapshotEntry: + snapshot_entry = SnapshotEntry.from_delta_entry(delta_entry) snapshot_entry = await self._submit_entry(snapshot_entry) return snapshot_entry - async def _submit_update_or_create(self, event_entry: EventEntry, **kwargs) -> SnapshotEntry: - instance = await self._build_instance(event_entry, **kwargs) + async def _submit_update_or_create(self, delta_entry: DeltaEntry, **kwargs) -> SnapshotEntry: + instance = await self._build_instance(delta_entry, **kwargs) - snapshot_entry = SnapshotEntry.from_root_entity(instance, transaction_uuid=event_entry.transaction_uuid) + snapshot_entry = SnapshotEntry.from_root_entity(instance, transaction_uuid=delta_entry.transaction_uuid) snapshot_entry = await self._submit_entry(snapshot_entry) return snapshot_entry - async def _build_instance(self, event_entry: EventEntry, **kwargs) -> RootEntity: - diff = event_entry.event + async def _build_instance(self, delta_entry: DeltaEntry, **kwargs) -> RootEntity: + diff = delta_entry.delta try: - transaction = await self._transaction_repository.get(uuid=event_entry.transaction_uuid) + transaction = await self._transaction_repository.get(uuid=delta_entry.transaction_uuid) except TransactionNotFoundException: transaction = None instance = await self._update_instance_if_exists(diff, transaction=transaction, **kwargs) return instance - async def _update_instance_if_exists(self, event: Event, **kwargs) -> RootEntity: + async def _update_instance_if_exists(self, delta: Delta, **kwargs) -> RootEntity: # noinspection PyBroadException try: # noinspection PyTypeChecker - previous = await self._select_one_instance(event.name, event.uuid, **kwargs) + previous = await self._select_one_instance(delta.name, delta.uuid, **kwargs) except NotFoundException: # noinspection PyTypeChecker - cls = import_module(event.name) - return cls.from_diff(event, **kwargs) + cls = import_module(delta.name) + return cls.from_diff(delta, **kwargs) - if previous.version >= event.version: - raise SnapshotRepositoryConflictException(previous, event) + if previous.version >= delta.version: + raise SnapshotRepositoryConflictException(previous, delta) - previous.apply_diff(event) + previous.apply_diff(delta) return previous async def _select_one_instance(self, name: str, uuid: UUID, **kwargs) -> RootEntity: diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py index 2771caabd..e1a5af915 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py @@ -30,9 +30,9 @@ TransactionStatus, ) -from ...events import ( - EventEntry, - EventRepository, +from ...deltas import ( + DeltaEntry, + DeltaRepository, ) from ...exceptions import ( AlreadyDeletedException, @@ -52,7 +52,7 @@ class InMemorySnapshotRepository(SnapshotRepository): """InMemory Snapshot class. - The snapshot provides a direct accessor to the ``RootEntity`` instances stored as events by the event repository + The snapshot provides a direct accessor to the ``RootEntity`` instances stored as deltas by the delta repository class. """ @@ -60,19 +60,19 @@ class InMemorySnapshotRepository(SnapshotRepository): def __init__( self, *args, - event_repository: EventRepository, + delta_repository: DeltaRepository, transaction_repository: TransactionRepository, **kwargs, ): super().__init__(*args, **kwargs) - if event_repository is None: - raise NotProvidedException("An event repository instance is required.") + if delta_repository is None: + raise NotProvidedException("An delta repository instance is required.") if transaction_repository is None: raise NotProvidedException("A transaction repository instance is required.") - self._event_repository = event_repository + self._delta_repository = delta_repository self._transaction_repository = transaction_repository async def _find_entries( @@ -84,7 +84,7 @@ async def _find_entries( exclude_deleted: bool, **kwargs, ) -> AsyncIterator[SnapshotEntry]: - uuids = {v.uuid async for v in self._event_repository.select(name=name)} + uuids = {v.uuid async for v in self._delta_repository.select(name=name)} entries = list() for uuid in uuids: @@ -134,7 +134,7 @@ async def _get( self, name: str, uuid: UUID, transaction: Optional[TransactionEntry] = None, **kwargs ) -> SnapshotEntry: transaction_uuids = await self._get_transaction_uuids(transaction) - entries = await self._get_event_entries(name, uuid, transaction_uuids) + entries = await self._get_delta_entries(name, uuid, transaction_uuids) return self._build_instance(entries, **kwargs) async def _get_transaction_uuids(self, transaction: Optional[TransactionEntry]) -> tuple[UUID, ...]: @@ -151,10 +151,10 @@ async def _get_transaction_uuids(self, transaction: Optional[TransactionEntry]) return transaction_uuids - async def _get_event_entries(self, name: str, uuid: UUID, transaction_uuids: tuple[UUID, ...]) -> list[EventEntry]: + async def _get_delta_entries(self, name: str, uuid: UUID, transaction_uuids: tuple[UUID, ...]) -> list[DeltaEntry]: entries = [ v - async for v in self._event_repository.select(name=name, uuid=uuid) + async for v in self._delta_repository.select(name=name, uuid=uuid) if v.transaction_uuid in transaction_uuids ] @@ -169,14 +169,14 @@ async def _get_event_entries(self, name: str, uuid: UUID, transaction_uuids: tup return entries @staticmethod - def _build_instance(entries: list[EventEntry], **kwargs) -> SnapshotEntry: + def _build_instance(entries: list[DeltaEntry], **kwargs) -> SnapshotEntry: if entries[-1].action.is_delete: - return SnapshotEntry.from_event_entry(entries[-1]) + return SnapshotEntry.from_delta_entry(entries[-1]) cls = entries[0].type_ - instance = cls.from_diff(entries[0].event, **kwargs) + instance = cls.from_diff(entries[0].delta, **kwargs) for entry in entries[1:]: - instance.apply_diff(entry.event) + instance.apply_diff(entry.delta) snapshot = SnapshotEntry.from_root_entity(instance) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/__init__.py index 1ec1456db..38e2f2efa 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/__init__.py @@ -1,6 +1,6 @@ -from .events import ( - EventRepositoryTestCase, - MockedEventDatabaseOperationFactory, +from .deltas import ( + DeltaRepositoryTestCase, + MockedDeltaDatabaseOperationFactory, ) from .snapshots import ( MockedSnapshotDatabaseOperationFactory, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/__init__.py new file mode 100644 index 000000000..a1bbebf7f --- /dev/null +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/__init__.py @@ -0,0 +1,4 @@ +from .repositories import ( + DeltaRepositoryTestCase, + MockedDeltaDatabaseOperationFactory, +) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/repositories/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/repositories/__init__.py new file mode 100644 index 000000000..b15531c47 --- /dev/null +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/repositories/__init__.py @@ -0,0 +1,6 @@ +from .factories import ( + MockedDeltaDatabaseOperationFactory, +) +from .testcases import ( + DeltaRepositoryTestCase, +) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/factories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/repositories/factories.py similarity index 89% rename from packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/factories.py rename to packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/repositories/factories.py index 8bf90cf35..eb47eebb4 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/factories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/repositories/factories.py @@ -19,12 +19,12 @@ from ....actions import ( Action, ) -from ....events import ( - EventDatabaseOperationFactory, +from ....deltas import ( + DeltaDatabaseOperationFactory, ) -class MockedEventDatabaseOperationFactory(EventDatabaseOperationFactory): +class MockedDeltaDatabaseOperationFactory(DeltaDatabaseOperationFactory): """For testing purposes.""" def build_create(self) -> DatabaseOperation: @@ -74,4 +74,4 @@ def build_query_offset(self) -> DatabaseOperation: return MockedDatabaseOperation("select_max_id") -MockedDatabaseClient.set_factory(EventDatabaseOperationFactory, MockedEventDatabaseOperationFactory) +MockedDatabaseClient.set_factory(DeltaDatabaseOperationFactory, MockedDeltaDatabaseOperationFactory) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/testcases.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/repositories/testcases.py similarity index 72% rename from packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/testcases.py rename to packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/repositories/testcases.py index 2ac3d71f7..01d78f6d8 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/testcases.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/deltas/repositories/testcases.py @@ -17,10 +17,10 @@ from minos.aggregate import ( Action, - EventEntry, - EventRepository, - EventRepositoryConflictException, - EventRepositoryException, + DeltaEntry, + DeltaRepository, + DeltaRepositoryConflictException, + DeltaRepositoryException, FieldDiffContainer, ) from minos.common import ( @@ -35,12 +35,12 @@ ) -class EventRepositoryTestCase(MinosTestCase, ABC): +class DeltaRepositoryTestCase(MinosTestCase, ABC): __test__ = False def setUp(self) -> None: super().setUp() - self.event_repository = self.build_event_repository() + self.delta_repository = self.build_delta_repository() self.field_diff_container_patcher = patch( "minos.aggregate.FieldDiffContainer.from_avro_bytes", return_value=FieldDiffContainer.empty() ) @@ -55,7 +55,7 @@ def setUp(self) -> None: self.second_transaction = uuid4() self.entries = [ - EventEntry( + DeltaEntry( self.uuid_1, "example.Car", 1, @@ -64,7 +64,7 @@ def setUp(self) -> None: Action.CREATE, current_datetime(), ), - EventEntry( + DeltaEntry( self.uuid_1, "example.Car", 2, @@ -73,7 +73,7 @@ def setUp(self) -> None: Action.UPDATE, current_datetime(), ), - EventEntry( + DeltaEntry( self.uuid_2, "example.Car", 1, @@ -82,7 +82,7 @@ def setUp(self) -> None: Action.CREATE, current_datetime(), ), - EventEntry( + DeltaEntry( self.uuid_1, "example.Car", 3, @@ -91,7 +91,7 @@ def setUp(self) -> None: Action.UPDATE, current_datetime(), ), - EventEntry( + DeltaEntry( self.uuid_1, "example.Car", 4, @@ -100,7 +100,7 @@ def setUp(self) -> None: Action.DELETE, current_datetime(), ), - EventEntry( + DeltaEntry( self.uuid_2, "example.Car", 2, @@ -109,7 +109,7 @@ def setUp(self) -> None: Action.UPDATE, current_datetime(), ), - EventEntry( + DeltaEntry( self.uuid_4, "example.MotorCycle", 1, @@ -118,7 +118,7 @@ def setUp(self) -> None: Action.CREATE, current_datetime(), ), - EventEntry( + DeltaEntry( self.uuid_2, "example.Car", 3, @@ -128,7 +128,7 @@ def setUp(self) -> None: current_datetime(), transaction_uuid=self.first_transaction, ), - EventEntry( + DeltaEntry( self.uuid_2, "example.Car", 3, @@ -138,7 +138,7 @@ def setUp(self) -> None: current_datetime(), transaction_uuid=self.second_transaction, ), - EventEntry( + DeltaEntry( self.uuid_2, "example.Car", 4, @@ -152,10 +152,10 @@ def setUp(self) -> None: async def asyncSetUp(self): await super().asyncSetUp() - await self.event_repository.setup() + await self.delta_repository.setup() async def asyncTearDown(self): - await self.event_repository.destroy() + await self.delta_repository.destroy() await super().asyncTearDown() def tearDown(self): @@ -166,28 +166,28 @@ async def populate(self) -> None: await self.transaction_repository.submit(TransactionEntry(self.first_transaction)) await self.transaction_repository.submit(TransactionEntry(self.second_transaction)) - await self.event_repository.create(EventEntry(self.uuid_1, "example.Car", 1, bytes("foo", "utf-8"))) - await self.event_repository.update(EventEntry(self.uuid_1, "example.Car", 2, bytes("bar", "utf-8"))) - await self.event_repository.create(EventEntry(self.uuid_2, "example.Car", 1, bytes("hello", "utf-8"))) - await self.event_repository.update(EventEntry(self.uuid_1, "example.Car", 3, bytes("foobar", "utf-8"))) - await self.event_repository.delete(EventEntry(self.uuid_1, "example.Car", 4)) - await self.event_repository.update(EventEntry(self.uuid_2, "example.Car", 2, bytes("bye", "utf-8"))) - await self.event_repository.create(EventEntry(self.uuid_4, "example.MotorCycle", 1, bytes("one", "utf-8"))) - await self.event_repository.update( - EventEntry(self.uuid_2, "example.Car", 3, bytes("hola", "utf-8"), transaction_uuid=self.first_transaction) + await self.delta_repository.create(DeltaEntry(self.uuid_1, "example.Car", 1, bytes("foo", "utf-8"))) + await self.delta_repository.update(DeltaEntry(self.uuid_1, "example.Car", 2, bytes("bar", "utf-8"))) + await self.delta_repository.create(DeltaEntry(self.uuid_2, "example.Car", 1, bytes("hello", "utf-8"))) + await self.delta_repository.update(DeltaEntry(self.uuid_1, "example.Car", 3, bytes("foobar", "utf-8"))) + await self.delta_repository.delete(DeltaEntry(self.uuid_1, "example.Car", 4)) + await self.delta_repository.update(DeltaEntry(self.uuid_2, "example.Car", 2, bytes("bye", "utf-8"))) + await self.delta_repository.create(DeltaEntry(self.uuid_4, "example.MotorCycle", 1, bytes("one", "utf-8"))) + await self.delta_repository.update( + DeltaEntry(self.uuid_2, "example.Car", 3, bytes("hola", "utf-8"), transaction_uuid=self.first_transaction) ) - await self.event_repository.update( - EventEntry(self.uuid_2, "example.Car", 3, bytes("salut", "utf-8"), transaction_uuid=self.second_transaction) + await self.delta_repository.update( + DeltaEntry(self.uuid_2, "example.Car", 3, bytes("salut", "utf-8"), transaction_uuid=self.second_transaction) ) - await self.event_repository.update( - EventEntry(self.uuid_2, "example.Car", 4, bytes("adios", "utf-8"), transaction_uuid=self.first_transaction) + await self.delta_repository.update( + DeltaEntry(self.uuid_2, "example.Car", 4, bytes("adios", "utf-8"), transaction_uuid=self.first_transaction) ) @abstractmethod - def build_event_repository(self) -> EventRepository: + def build_delta_repository(self) -> DeltaRepository: """For testing purposes.""" - def assert_equal_repository_entries(self, expected: list[EventEntry], observed: list[EventEntry]) -> None: + def assert_equal_repository_entries(self, expected: list[DeltaEntry], observed: list[DeltaEntry]) -> None: """For testing purposes.""" self.assertEqual(len(expected), len(observed)) @@ -203,108 +203,108 @@ def assert_equal_repository_entries(self, expected: list[EventEntry], observed: self.assertAlmostEqual(e.created_at or current_datetime(), o.created_at, delta=timedelta(seconds=5)) async def test_generate_uuid(self): - await self.event_repository.create(EventEntry(NULL_UUID, "example.Car", 1, bytes("foo", "utf-8"))) - observed = [v async for v in self.event_repository.select()] + await self.delta_repository.create(DeltaEntry(NULL_UUID, "example.Car", 1, bytes("foo", "utf-8"))) + observed = [v async for v in self.delta_repository.select()] self.assertEqual(1, len(observed)) self.assertIsInstance(observed[0].uuid, UUID) self.assertNotEqual(NULL_UUID, observed[0].uuid) async def test_submit(self): - await self.event_repository.submit(EventEntry(self.uuid, "example.Car", action=Action.CREATE)) - expected = [EventEntry(self.uuid, "example.Car", 1, bytes(), 1, Action.CREATE)] - observed = [v async for v in self.event_repository.select()] + await self.delta_repository.submit(DeltaEntry(self.uuid, "example.Car", action=Action.CREATE)) + expected = [DeltaEntry(self.uuid, "example.Car", 1, bytes(), 1, Action.CREATE)] + observed = [v async for v in self.delta_repository.select()] self.assert_equal_repository_entries(expected, observed) async def test_submit_with_version(self): - await self.event_repository.submit(EventEntry(self.uuid, "example.Car", version=3, action=Action.CREATE)) - expected = [EventEntry(self.uuid, "example.Car", 3, bytes(), 1, Action.CREATE)] - observed = [v async for v in self.event_repository.select()] + await self.delta_repository.submit(DeltaEntry(self.uuid, "example.Car", version=3, action=Action.CREATE)) + expected = [DeltaEntry(self.uuid, "example.Car", 3, bytes(), 1, Action.CREATE)] + observed = [v async for v in self.delta_repository.select()] self.assert_equal_repository_entries(expected, observed) async def test_submit_with_created_at(self): created_at = datetime(2021, 10, 25, 8, 30, tzinfo=timezone.utc) - await self.event_repository.submit( - EventEntry(self.uuid, "example.Car", created_at=created_at, action=Action.CREATE) + await self.delta_repository.submit( + DeltaEntry(self.uuid, "example.Car", created_at=created_at, action=Action.CREATE) ) - expected = [EventEntry(self.uuid, "example.Car", 1, bytes(), 1, Action.CREATE, created_at=created_at)] - observed = [v async for v in self.event_repository.select()] + expected = [DeltaEntry(self.uuid, "example.Car", 1, bytes(), 1, Action.CREATE, created_at=created_at)] + observed = [v async for v in self.delta_repository.select()] self.assert_equal_repository_entries(expected, observed) async def test_submit_raises_duplicate(self): - await self.event_repository.submit(EventEntry(self.uuid, "example.Car", 1, action=Action.CREATE)) - with self.assertRaises(EventRepositoryConflictException): - await self.event_repository.submit(EventEntry(self.uuid, "example.Car", 1, action=Action.CREATE)) + await self.delta_repository.submit(DeltaEntry(self.uuid, "example.Car", 1, action=Action.CREATE)) + with self.assertRaises(DeltaRepositoryConflictException): + await self.delta_repository.submit(DeltaEntry(self.uuid, "example.Car", 1, action=Action.CREATE)) async def test_submit_raises_no_action(self): - with self.assertRaises(EventRepositoryException): - await self.event_repository.submit(EventEntry(self.uuid, "example.Car", 1, "foo".encode())) + with self.assertRaises(DeltaRepositoryException): + await self.delta_repository.submit(DeltaEntry(self.uuid, "example.Car", 1, "foo".encode())) async def test_select_empty(self): - self.assertEqual([], [v async for v in self.event_repository.select()]) + self.assertEqual([], [v async for v in self.delta_repository.select()]) async def test_offset(self): - self.assertEqual(0, await self.event_repository.offset) - await self.event_repository.submit(EventEntry(self.uuid, "example.Car", version=3, action=Action.CREATE)) - self.assertEqual(1, await self.event_repository.offset) + self.assertEqual(0, await self.delta_repository.offset) + await self.delta_repository.submit(DeltaEntry(self.uuid, "example.Car", version=3, action=Action.CREATE)) + self.assertEqual(1, await self.delta_repository.offset) async def test_select(self): await self.populate() expected = self.entries - observed = [v async for v in self.event_repository.select()] + observed = [v async for v in self.delta_repository.select()] self.assert_equal_repository_entries(expected, observed) async def test_select_id(self): await self.populate() expected = [self.entries[1]] - observed = [v async for v in self.event_repository.select(id=2)] + observed = [v async for v in self.delta_repository.select(id=2)] self.assert_equal_repository_entries(expected, observed) async def test_select_id_lt(self): await self.populate() expected = self.entries[:4] - observed = [v async for v in self.event_repository.select(id_lt=5)] + observed = [v async for v in self.delta_repository.select(id_lt=5)] self.assert_equal_repository_entries(expected, observed) async def test_select_id_gt(self): await self.populate() expected = self.entries[4:] - observed = [v async for v in self.event_repository.select(id_gt=4)] + observed = [v async for v in self.delta_repository.select(id_gt=4)] self.assert_equal_repository_entries(expected, observed) async def test_select_id_le(self): await self.populate() expected = self.entries[:4] - observed = [v async for v in self.event_repository.select(id_le=4)] + observed = [v async for v in self.delta_repository.select(id_le=4)] self.assert_equal_repository_entries(expected, observed) async def test_select_id_ge(self): await self.populate() expected = self.entries[4:] - observed = [v async for v in self.event_repository.select(id_ge=5)] + observed = [v async for v in self.delta_repository.select(id_ge=5)] self.assert_equal_repository_entries(expected, observed) async def test_select_uuid(self): await self.populate() expected = [self.entries[2], self.entries[5], self.entries[7], self.entries[8], self.entries[9]] - observed = [v async for v in self.event_repository.select(uuid=self.uuid_2)] + observed = [v async for v in self.delta_repository.select(uuid=self.uuid_2)] self.assert_equal_repository_entries(expected, observed) async def test_select_name(self): await self.populate() expected = [self.entries[6]] - observed = [v async for v in self.event_repository.select(name="example.MotorCycle")] + observed = [v async for v in self.delta_repository.select(name="example.MotorCycle")] self.assert_equal_repository_entries(expected, observed) async def test_select_version(self): await self.populate() expected = [self.entries[4], self.entries[9]] - observed = [v async for v in self.event_repository.select(version=4)] + observed = [v async for v in self.delta_repository.select(version=4)] self.assert_equal_repository_entries(expected, observed) async def test_select_version_lt(self): await self.populate() expected = [self.entries[0], self.entries[2], self.entries[6]] - observed = [v async for v in self.event_repository.select(version_lt=2)] + observed = [v async for v in self.delta_repository.select(version_lt=2)] self.assert_equal_repository_entries(expected, observed) async def test_select_version_gt(self): @@ -318,13 +318,13 @@ async def test_select_version_gt(self): self.entries[8], self.entries[9], ] - observed = [v async for v in self.event_repository.select(version_gt=1)] + observed = [v async for v in self.delta_repository.select(version_gt=1)] self.assert_equal_repository_entries(expected, observed) async def test_select_version_le(self): await self.populate() expected = [self.entries[0], self.entries[2], self.entries[6]] - observed = [v async for v in self.event_repository.select(version_le=1)] + observed = [v async for v in self.delta_repository.select(version_le=1)] self.assert_equal_repository_entries(expected, observed) async def test_select_version_ge(self): @@ -338,25 +338,25 @@ async def test_select_version_ge(self): self.entries[8], self.entries[9], ] - observed = [v async for v in self.event_repository.select(version_ge=2)] + observed = [v async for v in self.delta_repository.select(version_ge=2)] self.assert_equal_repository_entries(expected, observed) async def test_select_transaction_uuid_null(self): await self.populate() expected = self.entries[:7] - observed = [v async for v in self.event_repository.select(transaction_uuid=NULL_UUID)] + observed = [v async for v in self.delta_repository.select(transaction_uuid=NULL_UUID)] self.assert_equal_repository_entries(expected, observed) async def test_select_transaction_uuid(self): await self.populate() expected = [self.entries[7], self.entries[9]] - observed = [v async for v in self.event_repository.select(transaction_uuid=self.first_transaction)] + observed = [v async for v in self.delta_repository.select(transaction_uuid=self.first_transaction)] self.assert_equal_repository_entries(expected, observed) async def test_select_transaction_uuid_ne(self): await self.populate() expected = [self.entries[7], self.entries[8], self.entries[9]] - observed = [v async for v in self.event_repository.select(transaction_uuid_ne=NULL_UUID)] + observed = [v async for v in self.delta_repository.select(transaction_uuid_ne=NULL_UUID)] self.assert_equal_repository_entries(expected, observed) async def test_select_transaction_uuid_in(self): @@ -364,7 +364,7 @@ async def test_select_transaction_uuid_in(self): expected = [self.entries[7], self.entries[8], self.entries[9]] observed = [ v - async for v in self.event_repository.select( + async for v in self.delta_repository.select( transaction_uuid_in=(self.first_transaction, self.second_transaction) ) ] @@ -373,5 +373,5 @@ async def test_select_transaction_uuid_in(self): async def test_select_combined(self): await self.populate() expected = [self.entries[2], self.entries[5], self.entries[7], self.entries[8], self.entries[9]] - observed = [v async for v in self.event_repository.select(name="example.Car", uuid=self.uuid_2)] + observed = [v async for v in self.delta_repository.select(name="example.Car", uuid=self.uuid_2)] self.assert_equal_repository_entries(expected, observed) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/__init__.py deleted file mode 100644 index 33ee0ba5f..000000000 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .repositories import ( - EventRepositoryTestCase, - MockedEventDatabaseOperationFactory, -) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/__init__.py deleted file mode 100644 index f8147fc40..000000000 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/events/repositories/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from .factories import ( - MockedEventDatabaseOperationFactory, -) -from .testcases import ( - EventRepositoryTestCase, -) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py index 1495d8bbd..ef01450bd 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py @@ -24,7 +24,7 @@ Action, AlreadyDeletedException, Condition, - EventEntry, + DeltaEntry, FieldDiff, FieldDiffContainer, NotFoundException, @@ -87,24 +87,24 @@ async def populate(self) -> None: diff = FieldDiffContainer([FieldDiff("doors", int, 3), FieldDiff("color", str, "blue")]) name: str = classname(self.Car) - await self.event_repository.create(EventEntry(self.uuid_1, name, 1, diff.avro_bytes)) - await self.event_repository.update(EventEntry(self.uuid_1, name, 2, diff.avro_bytes)) - await self.event_repository.create(EventEntry(self.uuid_2, name, 1, diff.avro_bytes)) - await self.event_repository.update(EventEntry(self.uuid_1, name, 3, diff.avro_bytes)) - await self.event_repository.delete(EventEntry(self.uuid_1, name, 4)) - await self.event_repository.update(EventEntry(self.uuid_2, name, 2, diff.avro_bytes)) - await self.event_repository.update( - EventEntry(self.uuid_2, name, 3, diff.avro_bytes, transaction_uuid=self.transaction_1) + await self.delta_repository.create(DeltaEntry(self.uuid_1, name, 1, diff.avro_bytes)) + await self.delta_repository.update(DeltaEntry(self.uuid_1, name, 2, diff.avro_bytes)) + await self.delta_repository.create(DeltaEntry(self.uuid_2, name, 1, diff.avro_bytes)) + await self.delta_repository.update(DeltaEntry(self.uuid_1, name, 3, diff.avro_bytes)) + await self.delta_repository.delete(DeltaEntry(self.uuid_1, name, 4)) + await self.delta_repository.update(DeltaEntry(self.uuid_2, name, 2, diff.avro_bytes)) + await self.delta_repository.update( + DeltaEntry(self.uuid_2, name, 3, diff.avro_bytes, transaction_uuid=self.transaction_1) ) - await self.event_repository.delete( - EventEntry(self.uuid_2, name, 3, bytes(), transaction_uuid=self.transaction_2) + await self.delta_repository.delete( + DeltaEntry(self.uuid_2, name, 3, bytes(), transaction_uuid=self.transaction_2) ) - await self.event_repository.update( - EventEntry(self.uuid_2, name, 4, diff.avro_bytes, transaction_uuid=self.transaction_1) + await self.delta_repository.update( + DeltaEntry(self.uuid_2, name, 4, diff.avro_bytes, transaction_uuid=self.transaction_1) ) - await self.event_repository.create(EventEntry(self.uuid_3, name, 1, diff.avro_bytes)) - await self.event_repository.delete( - EventEntry(self.uuid_2, name, 3, bytes(), transaction_uuid=self.transaction_3) + await self.delta_repository.create(DeltaEntry(self.uuid_3, name, 1, diff.avro_bytes)) + await self.delta_repository.delete( + DeltaEntry(self.uuid_2, name, 3, bytes(), transaction_uuid=self.transaction_3) ) await self.transaction_repository.submit(TransactionEntry(self.transaction_1, TransactionStatus.PENDING)) await self.transaction_repository.submit(TransactionEntry(self.transaction_2, TransactionStatus.PENDING)) @@ -296,11 +296,11 @@ async def test_dispatch_ignore_previous_version(self): async def _fn(*args, id_gt: Optional[int] = None, **kwargs): if id_gt is not None and id_gt > 0: return - yield EventEntry(self.uuid_1, name, 1, diff.avro_bytes, 1, Action.CREATE, current_datetime()) - yield EventEntry(self.uuid_1, name, 3, diff.avro_bytes, 2, Action.CREATE, current_datetime()) - yield EventEntry(self.uuid_1, name, 2, diff.avro_bytes, 3, Action.CREATE, current_datetime()) + yield DeltaEntry(self.uuid_1, name, 1, diff.avro_bytes, 1, Action.CREATE, current_datetime()) + yield DeltaEntry(self.uuid_1, name, 3, diff.avro_bytes, 2, Action.CREATE, current_datetime()) + yield DeltaEntry(self.uuid_1, name, 2, diff.avro_bytes, 3, Action.CREATE, current_datetime()) - self.event_repository.select = MagicMock(side_effect=_fn) + self.delta_repository.select = MagicMock(side_effect=_fn) await self.snapshot_repository.synchronize() observed = [v async for v in self.snapshot_repository.find_entries(name, condition)] @@ -322,8 +322,8 @@ async def _fn(*args, id_gt: Optional[int] = None, **kwargs): async def test_dispatch_with_offset(self): await self.populate() - mock = MagicMock(side_effect=self.event_repository.select) - self.event_repository.select = mock + mock = MagicMock(side_effect=self.delta_repository.select) + self.delta_repository.select = mock await self.snapshot_repository.synchronize() self.assertEqual(1, mock.call_count) @@ -331,12 +331,12 @@ async def test_dispatch_with_offset(self): mock.reset_mock() # noinspection PyTypeChecker - entry = EventEntry( + entry = DeltaEntry( uuid=self.uuid_3, name=self.Car.classname, data=FieldDiffContainer([FieldDiff("doors", int, 3), FieldDiff("color", str, "blue")]).avro_bytes, ) - await self.event_repository.create(entry) + await self.delta_repository.create(entry) await self.snapshot_repository.synchronize() self.assertEqual(1, mock.call_count) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/__init__.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/__init__.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/__init__.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/__init__.py diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_entries.py similarity index 83% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_entries.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_entries.py index 266c39575..1326b077f 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_entries.py @@ -8,8 +8,8 @@ from minos.aggregate import ( Action, - Event, - EventEntry, + Delta, + DeltaEntry, FieldDiff, FieldDiffContainer, ) @@ -31,7 +31,7 @@ def setUp(self) -> None: self.transaction_uuid = uuid4() def test_constructor(self): - entry = EventEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) + entry = DeltaEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) self.assertEqual(self.uuid, entry.uuid) self.assertEqual("example.Car", entry.name) self.assertEqual(0, entry.version) @@ -43,11 +43,11 @@ def test_constructor(self): # noinspection SpellCheckingInspection def test_constructor_with_memoryview_data(self): - entry = EventEntry(self.uuid, "example.Car", 0, memoryview(bytes("car", "utf-8"))) + entry = DeltaEntry(self.uuid, "example.Car", 0, memoryview(bytes("car", "utf-8"))) self.assertEqual(bytes("car", "utf-8"), entry.data) def test_constructor_extended(self): - entry = EventEntry( + entry = DeltaEntry( uuid=self.uuid, name="example.Car", version=0, @@ -66,12 +66,12 @@ def test_constructor_extended(self): self.assertEqual(datetime(2020, 10, 13, 8, 45, 32), entry.created_at) self.assertEqual(self.transaction_uuid, entry.transaction_uuid) - async def test_from_event(self): + async def test_from_delta(self): fields_diff = FieldDiffContainer([FieldDiff("doors", int, 3), FieldDiff("color", str, "blue")]) created_at = current_datetime() - event = Event(self.uuid, Car.classname, 1, Action.CREATE, created_at, fields_diff) + delta = Delta(self.uuid, Car.classname, 1, Action.CREATE, created_at, fields_diff) - entry = EventEntry.from_event(event) + entry = DeltaEntry.from_delta(delta) self.assertEqual(self.uuid, entry.uuid) self.assertEqual("tests.utils.Car", entry.name) self.assertEqual(None, entry.version) @@ -81,13 +81,13 @@ async def test_from_event(self): self.assertEqual(None, entry.created_at) self.assertEqual(NULL_UUID, entry.transaction_uuid) - async def test_from_event_with_transaction(self): + async def test_from_delta_with_transaction(self): transaction = TransactionEntry(self.transaction_uuid) fields_diff = FieldDiffContainer([FieldDiff("doors", int, 3), FieldDiff("color", str, "blue")]) created_at = current_datetime() - event = Event(self.uuid, Car.classname, 1, Action.CREATE, created_at, fields_diff) + delta = Delta(self.uuid, Car.classname, 1, Action.CREATE, created_at, fields_diff) - entry = EventEntry.from_event(event, transaction=transaction) + entry = DeltaEntry.from_delta(delta, transaction=transaction) self.assertEqual(self.uuid, entry.uuid) self.assertEqual("tests.utils.Car", entry.name) self.assertEqual(None, entry.version) @@ -99,7 +99,7 @@ async def test_from_event_with_transaction(self): async def test_from_another(self): created_at = datetime(2020, 10, 13, 8, 45, 32) - another = EventEntry( + another = DeltaEntry( uuid=self.uuid, name="example.Car", version=0, @@ -110,7 +110,7 @@ async def test_from_another(self): transaction_uuid=self.transaction_uuid, ) transaction_uuid = uuid4() - entry = EventEntry.from_another(another, transaction_uuid=transaction_uuid) + entry = DeltaEntry.from_another(another, transaction_uuid=transaction_uuid) self.assertEqual(self.uuid, entry.uuid) self.assertEqual("example.Car", entry.name) @@ -121,50 +121,50 @@ async def test_from_another(self): self.assertEqual(created_at, entry.created_at) self.assertEqual(transaction_uuid, entry.transaction_uuid) - def test_event(self): + def test_delta(self): field_diff_container = FieldDiffContainer([FieldDiff("doors", int, 3), FieldDiff("color", str, "blue")]) version = 1 now = current_datetime() - event = Event(self.uuid, Car.classname, version, Action.CREATE, now, field_diff_container) + delta = Delta(self.uuid, Car.classname, version, Action.CREATE, now, field_diff_container) - entry = EventEntry.from_event(event) + entry = DeltaEntry.from_delta(delta) entry.version = version entry.created_at = now - self.assertEqual(event, entry.event) + self.assertEqual(delta, entry.delta) def test_field_diff_container(self): field_diff_container = FieldDiffContainer([FieldDiff("doors", int, 3), FieldDiff("color", str, "blue")]) - entry = EventEntry(self.uuid, "example.Car", 0, field_diff_container.avro_bytes) + entry = DeltaEntry(self.uuid, "example.Car", 0, field_diff_container.avro_bytes) self.assertEqual(field_diff_container, entry.field_diff_container) def test_field_diff_container_empty(self): - entry = EventEntry(self.uuid, "example.Car", 0, bytes()) + entry = DeltaEntry(self.uuid, "example.Car", 0, bytes()) self.assertEqual(FieldDiffContainer.empty(), entry.field_diff_container) def test_id_setup(self): - entry = EventEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) + entry = DeltaEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) self.assertEqual(None, entry.id) entry.id = 5678 self.assertEqual(5678, entry.id) def test_action_setup(self): - entry = EventEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) + entry = DeltaEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) self.assertEqual(None, entry.action) entry.action = Action.CREATE self.assertEqual(Action.CREATE, entry.action) def test_equals(self): - a = EventEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) - b = EventEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) + a = DeltaEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) + b = DeltaEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) self.assertEqual(a, b) def test_hash(self): - entry = EventEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) + entry = DeltaEntry(self.uuid, "example.Car", 0, bytes("car", "utf-8")) self.assertIsInstance(hash(entry), int) def test_repr(self): @@ -175,7 +175,7 @@ def test_repr(self): action = Action.CREATE created_at = datetime(2020, 10, 13, 8, 45, 32) transaction_uuid = uuid4() - entry = EventEntry( + entry = DeltaEntry( uuid=self.uuid, name=name, version=version, @@ -186,7 +186,7 @@ def test_repr(self): transaction_uuid=transaction_uuid, ) expected = ( - f"EventEntry(uuid={self.uuid!r}, name={name!r}, " + f"DeltaEntry(uuid={self.uuid!r}, name={name!r}, " f"version={version!r}, len(data)={len(data)!r}, id={id_!r}, action={action!r}, created_at={created_at!r}, " f"transaction_uuid={transaction_uuid!r})" ) @@ -200,7 +200,7 @@ def test_as_raw(self): action = Action.CREATE created_at = datetime(2020, 10, 13, 8, 45, 32) transaction_uuid = uuid4() - entry = EventEntry( + entry = DeltaEntry( uuid=self.uuid, name=name, version=version, diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_fields.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_fields.py similarity index 98% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_fields.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_fields.py index 333d8705a..562a941f5 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_fields.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_fields.py @@ -102,7 +102,7 @@ def test_avro_schema(self): "type": { "fields": [{"name": "name", "type": "string"}, {"name": "value", "type": "int"}], "name": "FieldDiff", - "namespace": "minos.aggregate.events.fields.hola", + "namespace": "minos.aggregate.deltas.fields.hola", "type": "record", }, }, @@ -111,13 +111,13 @@ def test_avro_schema(self): "type": { "fields": [{"name": "name", "type": "string"}, {"name": "value", "type": "string"}], "name": "FieldDiff", - "namespace": "minos.aggregate.events.fields.adios", + "namespace": "minos.aggregate.deltas.fields.adios", "type": "record", }, }, ], "name": "FieldDiffContainer", - "namespace": "minos.aggregate.events.fields.uno", + "namespace": "minos.aggregate.deltas.fields.uno", "type": "record", } ] diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_models.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_models.py similarity index 88% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_models.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_models.py index b1b2de705..581579584 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_models.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_models.py @@ -9,7 +9,7 @@ from minos.aggregate import ( Action, - Event, + Delta, FieldDiff, FieldDiffContainer, IncrementalFieldDiff, @@ -25,7 +25,7 @@ ) -class TestEvent(AggregateTestCase): +class TestDelta(AggregateTestCase): async def asyncSetUp(self) -> None: await super().asyncSetUp() @@ -36,7 +36,7 @@ async def asyncSetUp(self) -> None: self.final = Car(5, "yellow", uuid=self.uuid, version=3) self.another = Car(3, "blue", uuid=self.uuid_another, version=1) - self.diff = Event( + self.diff = Delta( uuid=self.uuid, name=Car.classname, version=1, @@ -56,27 +56,27 @@ def test_simplified_name(self): def test_total_ordering(self): observed = [ - Event.from_root_entity(Car(3, "blue", version=4)), - Event.from_root_entity(Car(3, "blue", version=1)), - Event.from_root_entity(Car(3, "blue", version=3)), - Event.from_root_entity(Car(3, "blue", version=2)), + Delta.from_root_entity(Car(3, "blue", version=4)), + Delta.from_root_entity(Car(3, "blue", version=1)), + Delta.from_root_entity(Car(3, "blue", version=3)), + Delta.from_root_entity(Car(3, "blue", version=2)), ] observed.sort() expected = [ - Event.from_root_entity(Car(3, "blue", version=1)), - Event.from_root_entity(Car(3, "blue", version=2)), - Event.from_root_entity(Car(3, "blue", version=3)), - Event.from_root_entity(Car(3, "blue", version=4)), + Delta.from_root_entity(Car(3, "blue", version=1)), + Delta.from_root_entity(Car(3, "blue", version=2)), + Delta.from_root_entity(Car(3, "blue", version=3)), + Delta.from_root_entity(Car(3, "blue", version=4)), ] self.assertEqual(expected, observed) def test_from_root_entity(self): - observed = Event.from_root_entity(self.initial) + observed = Delta.from_root_entity(self.initial) self.assertEqual(self.diff, observed) def test_from_deleted_root_entity(self): - expected = Event( + expected = Delta( uuid=self.uuid, name=Car.classname, version=1, @@ -84,11 +84,11 @@ def test_from_deleted_root_entity(self): created_at=self.initial.updated_at, fields_diff=FieldDiffContainer.empty(), ) - observed = Event.from_deleted_root_entity(self.initial) + observed = Delta.from_deleted_root_entity(self.initial) self.assertEqual(expected, observed) def test_from_difference(self): - expected = Event( + expected = Delta( uuid=self.uuid, name=Car.classname, version=3, @@ -96,22 +96,22 @@ def test_from_difference(self): created_at=self.final.updated_at, fields_diff=FieldDiffContainer([FieldDiff("doors", int, 5), FieldDiff("color", str, "yellow")]), ) - observed = Event.from_difference(self.final, self.initial) + observed = Delta.from_difference(self.final, self.initial) self.assertEqual(expected, observed) def test_from_difference_raises(self): with self.assertRaises(ValueError): - Event.from_difference(self.initial, self.another) + Delta.from_difference(self.initial, self.another) def test_avro_serialization(self): serialized = self.diff.avro_bytes self.assertIsInstance(serialized, bytes) - deserialized = Event.from_avro_bytes(serialized) + deserialized = Delta.from_avro_bytes(serialized) self.assertEqual(self.diff, deserialized) def test_decompose(self): - aggr = Event( + aggr = Delta( uuid=self.uuid, name=Car.classname, version=3, @@ -121,7 +121,7 @@ def test_decompose(self): ) expected = [ - Event( + Delta( uuid=self.uuid, name=Car.classname, version=3, @@ -129,7 +129,7 @@ def test_decompose(self): created_at=aggr.created_at, fields_diff=FieldDiffContainer([FieldDiff("doors", int, 5)]), ), - Event( + Delta( uuid=self.uuid, name=Car.classname, version=3, @@ -143,9 +143,9 @@ def test_decompose(self): self.assertEqual(expected, observed) -class TestEventAccessors(unittest.TestCase): +class TestDeltaAccessors(unittest.TestCase): def setUp(self) -> None: - self.diff = Event( + self.diff = Delta( uuid=uuid4(), name="src.domain.Car", version=1, diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/__init__.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_repositories/__init__.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/__init__.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_repositories/__init__.py diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_repositories/test_abc.py similarity index 66% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_repositories/test_abc.py index 663409b89..19dd09e22 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_repositories/test_abc.py @@ -19,11 +19,11 @@ from minos.aggregate import ( IS_REPOSITORY_SERIALIZATION_CONTEXT_VAR, Action, - Event, - EventEntry, - EventRepository, - EventRepositoryConflictException, - EventRepositoryException, + Delta, + DeltaEntry, + DeltaRepository, + DeltaRepositoryConflictException, + DeltaRepositoryException, FieldDiff, FieldDiffContainer, ) @@ -47,13 +47,13 @@ ) -class _EventRepository(EventRepository): +class _DeltaRepository(DeltaRepository): """For testing purposes.""" - async def _submit(self, entry: EventEntry, **kwargs) -> EventEntry: + async def _submit(self, entry: DeltaEntry, **kwargs) -> DeltaEntry: """For testing purposes.""" - def _select(self, *args, **kwargs) -> AsyncIterator[EventEntry]: + def _select(self, *args, **kwargs) -> AsyncIterator[DeltaEntry]: """For testing purposes.""" @property @@ -62,44 +62,44 @@ async def _offset(self) -> int: return 0 -class TestEventRepository(AggregateTestCase): +class TestDeltaRepository(AggregateTestCase): def setUp(self) -> None: super().setUp() - self.event_repository = _EventRepository() + self.delta_repository = _DeltaRepository() def test_subclass(self): - self.assertTrue(issubclass(EventRepository, (ABC, SetupMixin))) + self.assertTrue(issubclass(DeltaRepository, (ABC, SetupMixin))) def test_abstract(self): # noinspection PyUnresolvedReferences - self.assertEqual({"_submit", "_select", "_offset"}, EventRepository.__abstractmethods__) + self.assertEqual({"_submit", "_select", "_offset"}, DeltaRepository.__abstractmethods__) def test_constructor(self): - repository = _EventRepository() + repository = _DeltaRepository() self.assertEqual(self.transaction_repository, repository.transaction_repository) self.assertEqual(self.pool_factory.get_pool("lock"), repository._lock_pool) async def test_constructor_raises(self): with self.assertRaises(NotProvidedException): # noinspection PyTypeChecker - _EventRepository(transaction_repository=None) + _DeltaRepository(transaction_repository=None) with self.assertRaises(NotProvidedException): # noinspection PyArgumentEqualDefault - _EventRepository(lock_pool=None, pool_factory=None) + _DeltaRepository(lock_pool=None, pool_factory=None) def test_transaction(self): uuid = uuid4() - transaction = self.event_repository.transaction(uuid=uuid) + transaction = self.delta_repository.transaction(uuid=uuid) self.assertEqual(TransactionEntry(uuid), transaction) self.assertEqual(self.transaction_repository, transaction.repository) async def test_create(self): mock = AsyncMock(side_effect=lambda x: x) - self.event_repository.submit = mock + self.delta_repository.submit = mock - entry = EventEntry(uuid4(), "example.Car", 0, bytes()) + entry = DeltaEntry(uuid4(), "example.Car", 0, bytes()) - self.assertEqual(entry, await self.event_repository.create(entry)) + self.assertEqual(entry, await self.delta_repository.create(entry)) self.assertEqual(Action.CREATE, entry.action) self.assertEqual(1, mock.call_count) @@ -107,11 +107,11 @@ async def test_create(self): async def test_update(self): mock = AsyncMock(side_effect=lambda x: x) - self.event_repository.submit = mock + self.delta_repository.submit = mock - entry = EventEntry(uuid4(), "example.Car", 0, bytes()) + entry = DeltaEntry(uuid4(), "example.Car", 0, bytes()) - self.assertEqual(entry, await self.event_repository.update(entry)) + self.assertEqual(entry, await self.delta_repository.update(entry)) self.assertEqual(Action.UPDATE, entry.action) self.assertEqual(1, mock.call_count) @@ -119,11 +119,11 @@ async def test_update(self): async def test_delete(self): mock = AsyncMock(side_effect=lambda x: x) - self.event_repository.submit = mock + self.delta_repository.submit = mock - entry = EventEntry(uuid4(), "example.Car", 0, bytes()) + entry = DeltaEntry(uuid4(), "example.Car", 0, bytes()) - self.assertEqual(entry, await self.event_repository.delete(entry)) + self.assertEqual(entry, await self.delta_repository.delete(entry)) self.assertEqual(Action.DELETE, entry.action) self.assertEqual(1, mock.call_count) @@ -134,17 +134,17 @@ async def test_submit(self): id_ = 12 field_diff_container = FieldDiffContainer([FieldDiff("color", str, "red")]) - async def _fn(e: EventEntry) -> EventEntry: + async def _fn(e: DeltaEntry) -> DeltaEntry: e.id = id_ e.version = 56 e.created_at = created_at return e submit_mock = AsyncMock(side_effect=_fn) - self.event_repository._submit = submit_mock + self.delta_repository._submit = submit_mock uuid = uuid4() - event = Event( + delta = Delta( uuid=uuid, name="example.Car", version=2, @@ -154,11 +154,11 @@ async def _fn(e: EventEntry) -> EventEntry: ) validate_mock = AsyncMock(return_value=True) - self.event_repository.validate = validate_mock + self.delta_repository.validate = validate_mock - observed = await self.event_repository.submit(event) + observed = await self.delta_repository.submit(delta) - self.assertIsInstance(observed, EventEntry) + self.assertIsInstance(observed, DeltaEntry) self.assertEqual(uuid, observed.uuid) self.assertEqual("example.Car", observed.name) self.assertEqual(56, observed.version) @@ -176,17 +176,17 @@ async def test_submit_in_transaction(self): TRANSACTION_CONTEXT_VAR.set(transaction) - async def _fn(e: EventEntry) -> EventEntry: + async def _fn(e: DeltaEntry) -> DeltaEntry: e.id = id_ e.version = 56 e.created_at = created_at return e submit_mock = AsyncMock(side_effect=_fn) - self.event_repository._submit = submit_mock + self.delta_repository._submit = submit_mock uuid = uuid4() - event = Event( + delta = Delta( uuid=uuid, name="example.Car", version=2, @@ -196,11 +196,11 @@ async def _fn(e: EventEntry) -> EventEntry: ) validate_mock = AsyncMock(return_value=True) - self.event_repository.validate = validate_mock + self.delta_repository.validate = validate_mock - observed = await self.event_repository.submit(event) + observed = await self.delta_repository.submit(delta) - self.assertIsInstance(observed, EventEntry) + self.assertIsInstance(observed, DeltaEntry) self.assertEqual(uuid, observed.uuid) self.assertEqual("example.Car", observed.name) self.assertEqual(56, observed.version) @@ -211,32 +211,32 @@ async def _fn(e: EventEntry) -> EventEntry: self.assertEqual(transaction.uuid, observed.transaction_uuid) async def test_submit_raises_missing_action(self): - entry = EventEntry(uuid4(), "example.Car", 0, bytes()) - with self.assertRaises(EventRepositoryException): - await self.event_repository.submit(entry) + entry = DeltaEntry(uuid4(), "example.Car", 0, bytes()) + with self.assertRaises(DeltaRepositoryException): + await self.delta_repository.submit(entry) async def test_submit_raises_conflict(self): validate_mock = AsyncMock(return_value=False) - self.event_repository.validate = validate_mock + self.delta_repository.validate = validate_mock - entry = EventEntry(uuid4(), "example.Car", 0, bytes(), action=Action.CREATE) - with self.assertRaises(EventRepositoryConflictException): - await self.event_repository.submit(entry) + entry = DeltaEntry(uuid4(), "example.Car", 0, bytes(), action=Action.CREATE) + with self.assertRaises(DeltaRepositoryConflictException): + await self.delta_repository.submit(entry) async def test_submit_context_var(self): - mocked_event = AsyncMock() - mocked_event.action = Action.CREATE + mocked_delta = AsyncMock() + mocked_delta.action = Action.CREATE async def _fn(entry): self.assertEqual(True, IS_REPOSITORY_SERIALIZATION_CONTEXT_VAR.get()) return entry mocked_submit = AsyncMock(side_effect=_fn) - self.event_repository._submit = mocked_submit + self.delta_repository._submit = mocked_submit self.assertEqual(False, IS_REPOSITORY_SERIALIZATION_CONTEXT_VAR.get()) - await self.event_repository.submit(mocked_event) + await self.delta_repository.submit(mocked_delta) self.assertEqual(False, IS_REPOSITORY_SERIALIZATION_CONTEXT_VAR.get()) self.assertEqual(1, mocked_submit.call_count) @@ -245,22 +245,22 @@ async def test_validate_true(self): uuid = uuid4() transaction_uuid = uuid4() - events = [] + deltas = [] transactions = [TransactionEntry(transaction_uuid, TransactionStatus.RESERVING)] - select_event_mock = MagicMock(return_value=FakeAsyncIterator(events)) - self.event_repository.select = select_event_mock + select_delta_mock = MagicMock(return_value=FakeAsyncIterator(deltas)) + self.delta_repository.select = select_delta_mock select_transaction_mock = MagicMock(return_value=FakeAsyncIterator(transactions)) self.transaction_repository.select = select_transaction_mock - entry = EventEntry(uuid, "example.Car") + entry = DeltaEntry(uuid, "example.Car") - self.assertTrue(await self.event_repository.validate(entry)) + self.assertTrue(await self.delta_repository.validate(entry)) self.assertEqual( [call(uuid=uuid, transaction_uuid_in=(transaction_uuid,))], - select_event_mock.call_args_list, + select_delta_mock.call_args_list, ) self.assertEqual( @@ -279,17 +279,17 @@ async def test_validate_with_skip(self): transaction_uuid = uuid4() another_transaction_uuid = uuid4() - events = [] + deltas = [] transactions = [TransactionEntry(another_transaction_uuid, TransactionStatus.RESERVING)] - select_event_mock = MagicMock(return_value=FakeAsyncIterator(events)) - self.event_repository.select = select_event_mock + select_delta_mock = MagicMock(return_value=FakeAsyncIterator(deltas)) + self.delta_repository.select = select_delta_mock select_transaction_mock = MagicMock(return_value=FakeAsyncIterator(transactions)) self.transaction_repository.select = select_transaction_mock - entry = EventEntry(uuid, "example.Car") - self.assertTrue(await self.event_repository.validate(entry, transaction_uuid_ne=transaction_uuid)) + entry = DeltaEntry(uuid, "example.Car") + self.assertTrue(await self.delta_repository.validate(entry, transaction_uuid_ne=transaction_uuid)) self.assertEqual( [ @@ -304,32 +304,32 @@ async def test_validate_with_skip(self): self.assertEqual( [call(uuid=uuid, transaction_uuid_in=(another_transaction_uuid,))], - select_event_mock.call_args_list, + select_delta_mock.call_args_list, ) async def test_validate_false(self): uuid = uuid4() transaction_uuid = uuid4() - events = [ - EventEntry(uuid, "example.Car", 1), - EventEntry(uuid, "example.Car", 2, transaction_uuid=transaction_uuid), + deltas = [ + DeltaEntry(uuid, "example.Car", 1), + DeltaEntry(uuid, "example.Car", 2, transaction_uuid=transaction_uuid), ] transactions = [TransactionEntry(transaction_uuid, TransactionStatus.RESERVED)] - select_event_mock = MagicMock(return_value=FakeAsyncIterator(events)) - self.event_repository.select = select_event_mock + select_delta_mock = MagicMock(return_value=FakeAsyncIterator(deltas)) + self.delta_repository.select = select_delta_mock select_transaction_mock = MagicMock(return_value=FakeAsyncIterator(transactions)) self.transaction_repository.select = select_transaction_mock - entry = EventEntry(uuid, "example.Car") + entry = DeltaEntry(uuid, "example.Car") - self.assertFalse(await self.event_repository.validate(entry)) + self.assertFalse(await self.delta_repository.validate(entry)) self.assertEqual( [call(uuid=uuid, transaction_uuid_in=(transaction_uuid,))], - select_event_mock.call_args_list, + select_delta_mock.call_args_list, ) self.assertEqual( @@ -349,17 +349,17 @@ def test_write_lock(self): self.pool_factory.get_pool("lock").acquire = mock - self.assertEqual(expected, self.event_repository.write_lock()) - self.assertEqual([call("aggregate_event_write_lock")], mock.call_args_list) + self.assertEqual(expected, self.delta_repository.write_lock()) + self.assertEqual([call("aggregate_delta_write_lock")], mock.call_args_list) async def test_select(self): mock = MagicMock(return_value=FakeAsyncIterator(range(5))) - self.event_repository._select = mock + self.delta_repository._select = mock uuid = uuid4() transaction_uuid = uuid4() - iterable = self.event_repository.select(uuid=uuid, name=Car, id_gt=56, transaction_uuid=transaction_uuid) + iterable = self.delta_repository.select(uuid=uuid, name=Car, id_gt=56, transaction_uuid=transaction_uuid) observed = [a async for a in iterable] self.assertEqual(list(range(5)), observed) @@ -386,9 +386,9 @@ async def test_select(self): async def test_offset(self): with patch( - f"{__name__}._EventRepository._offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=56) + f"{__name__}._DeltaRepository._offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=56) ) as mock: - self.assertEqual(56, await self.event_repository.offset) + self.assertEqual(56, await self.delta_repository.offset) self.assertEqual(1, mock.call_count) async def test_get_collided_transactions(self): @@ -397,28 +397,28 @@ async def test_get_collided_transactions(self): agg_uuid = uuid4() - select_event_1 = [ - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 3, bytes(), 2, Action.UPDATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 2, bytes(), 3, Action.UPDATE, transaction_uuid=uuid), + select_delta_1 = [ + DeltaEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), + DeltaEntry(agg_uuid, "c.Car", 3, bytes(), 2, Action.UPDATE, transaction_uuid=uuid), + DeltaEntry(agg_uuid, "c.Car", 2, bytes(), 3, Action.UPDATE, transaction_uuid=uuid), ] - select_event_2 = [ - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), - EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=another), + select_delta_2 = [ + DeltaEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid), + DeltaEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=another), ] - select_event_mock = MagicMock( - side_effect=[FakeAsyncIterator(select_event_1), FakeAsyncIterator(select_event_2)] + select_delta_mock = MagicMock( + side_effect=[FakeAsyncIterator(select_delta_1), FakeAsyncIterator(select_delta_2)] ) - self.event_repository.select = select_event_mock + self.delta_repository.select = select_delta_mock expected = {another} - observed = await self.event_repository.get_collided_transactions(uuid) + observed = await self.delta_repository.get_collided_transactions(uuid) self.assertEqual(expected, observed) self.assertEqual( - [call(transaction_uuid=uuid), call(uuid=agg_uuid, version=3)], select_event_mock.call_args_list + [call(transaction_uuid=uuid), call(uuid=agg_uuid, version=3)], select_delta_mock.call_args_list ) async def test_commit(self) -> None: @@ -427,24 +427,24 @@ async def test_commit(self) -> None: agg_uuid = uuid4() async def _fn(*args, **kwargs): - yield EventEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid) - yield EventEntry(agg_uuid, "c.Car", 3, bytes(), 2, Action.UPDATE, transaction_uuid=uuid) - yield EventEntry(agg_uuid, "c.Car", 2, bytes(), 3, Action.UPDATE, transaction_uuid=uuid) + yield DeltaEntry(agg_uuid, "c.Car", 1, bytes(), 1, Action.CREATE, transaction_uuid=uuid) + yield DeltaEntry(agg_uuid, "c.Car", 3, bytes(), 2, Action.UPDATE, transaction_uuid=uuid) + yield DeltaEntry(agg_uuid, "c.Car", 2, bytes(), 3, Action.UPDATE, transaction_uuid=uuid) select_mock = MagicMock(side_effect=_fn) submit_mock = AsyncMock() - self.event_repository.select = select_mock - self.event_repository.submit = submit_mock + self.delta_repository.select = select_mock + self.delta_repository.submit = submit_mock - with patch.object(EventRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55)): - await self.event_repository.commit_transaction(uuid, NULL_UUID) + with patch.object(DeltaRepository, "offset", new_callable=PropertyMock, side_effect=AsyncMock(return_value=55)): + await self.delta_repository.commit_transaction(uuid, NULL_UUID) self.assertEqual( [ - call(EventEntry(agg_uuid, "c.Car", 1, bytes(), action=Action.CREATE), transaction_uuid_ne=uuid), - call(EventEntry(agg_uuid, "c.Car", 3, bytes(), action=Action.UPDATE), transaction_uuid_ne=uuid), - call(EventEntry(agg_uuid, "c.Car", 2, bytes(), action=Action.UPDATE), transaction_uuid_ne=uuid), + call(DeltaEntry(agg_uuid, "c.Car", 1, bytes(), action=Action.CREATE), transaction_uuid_ne=uuid), + call(DeltaEntry(agg_uuid, "c.Car", 3, bytes(), action=Action.UPDATE), transaction_uuid_ne=uuid), + call(DeltaEntry(agg_uuid, "c.Car", 2, bytes(), action=Action.UPDATE), transaction_uuid_ne=uuid), ], submit_mock.call_args_list, ) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_database.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_repositories/test_database.py similarity index 98% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_database.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_repositories/test_database.py index fef33992f..ca30b68f2 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_database.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_repositories/test_database.py @@ -12,11 +12,11 @@ from minos.aggregate import ( Action, - DatabaseEventRepository, - EventRepository, + DatabaseDeltaRepository, + DeltaRepository, ) from minos.aggregate.testing import ( - EventRepositoryTestCase, + DeltaRepositoryTestCase, ) from minos.common import ( DatabaseClient, @@ -29,12 +29,12 @@ ) -class TestDatabaseEventRepositorySubmit(AggregateTestCase, EventRepositoryTestCase): +class TestDatabaseDeltaRepositorySubmit(AggregateTestCase, DeltaRepositoryTestCase): __test__ = True - def build_event_repository(self) -> EventRepository: + def build_delta_repository(self) -> DeltaRepository: """For testing purposes.""" - return DatabaseEventRepository.from_config(self.config) + return DatabaseDeltaRepository.from_config(self.config) async def test_generate_uuid(self): fetch_one = [ diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_memory.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_repositories/test_memory.py similarity index 52% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_memory.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_repositories/test_memory.py index c1efcdce1..41690bc96 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_events/test_repositories/test_memory.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_repositories/test_memory.py @@ -1,23 +1,23 @@ import unittest from minos.aggregate import ( - EventRepository, - InMemoryEventRepository, + DeltaRepository, + InMemoryDeltaRepository, ) from minos.aggregate.testing import ( - EventRepositoryTestCase, + DeltaRepositoryTestCase, ) from tests.utils import ( AggregateTestCase, ) -class TestInMemoryEventRepositorySubmit(AggregateTestCase, EventRepositoryTestCase): +class TestInMemoryDeltaRepositorySubmit(AggregateTestCase, DeltaRepositoryTestCase): __test__ = True - def build_event_repository(self) -> EventRepository: + def build_delta_repository(self) -> DeltaRepository: """For testing purposes.""" - return InMemoryEventRepository() + return InMemoryDeltaRepository() if __name__ == "__main__": diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_differences.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_differences.py index 0e2f5f1bb..b365664d2 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_differences.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_differences.py @@ -5,7 +5,7 @@ from minos.aggregate import ( Action, - Event, + Delta, FieldDiff, FieldDiffContainer, ) @@ -43,7 +43,7 @@ async def asyncSetUp(self) -> None: ) def test_diff(self): - expected = Event( + expected = Delta( uuid=self.uuid, name=Car.classname, version=3, @@ -55,7 +55,7 @@ def test_diff(self): self.assertEqual(expected, observed) def test_apply_diff(self): - diff = Event( + diff = Delta( uuid=self.uuid, name=Car.classname, version=3, @@ -67,7 +67,7 @@ def test_apply_diff(self): self.assertEqual(self.final, self.initial) def test_apply_diff_raises(self): - diff = Event( + diff = Delta( uuid=self.uuid_another, name=Car.classname, version=3, diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py index f08ccbb64..267b890f1 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py @@ -12,8 +12,8 @@ from minos.aggregate import ( AlreadyDeletedException, Condition, + DeltaRepositoryException, EntityRepository, - EventRepositoryException, NotFoundException, Ordering, ) @@ -35,7 +35,7 @@ def setUp(self) -> None: def test_constructor_raises(self): with self.assertRaises(NotProvidedException): - EntityRepository(event_repository=None) + EntityRepository(delta_repository=None) with self.assertRaises(NotProvidedException): EntityRepository(snapshot_repository=None) @@ -57,17 +57,17 @@ async def test_create_from_instance(self): self.assertEqual(instance, observed) async def test_create_raises(self): - with self.assertRaises(EventRepositoryException): + with self.assertRaises(DeltaRepositoryException): await self.repository.create(Car, uuid=uuid4(), doors=3, color="blue") - with self.assertRaises(EventRepositoryException): + with self.assertRaises(DeltaRepositoryException): await self.repository.create(Car, version=1, doors=3, color="blue") - with self.assertRaises(EventRepositoryException): + with self.assertRaises(DeltaRepositoryException): await self.repository.create(Car, created_at=current_datetime(), doors=3, color="blue") - with self.assertRaises(EventRepositoryException): + with self.assertRaises(DeltaRepositoryException): await self.repository.create(Car, updated_at=current_datetime(), doors=3, color="blue") - with self.assertRaises(EventRepositoryException): + with self.assertRaises(DeltaRepositoryException): await self.repository.create(Car(doors=3, color="blue"), "foo") - with self.assertRaises(EventRepositoryException): + with self.assertRaises(DeltaRepositoryException): await self.repository.create(Car(doors=3, color="blue"), foo="bar") async def test_classname(self): @@ -142,11 +142,11 @@ async def test_update_no_changes(self): self.assertEqual(car, await self.repository.get(Car, car.uuid)) async def test_update_raises(self): - with self.assertRaises(EventRepositoryException): + with self.assertRaises(DeltaRepositoryException): await self.repository.update(Car(3, "blue"), version=1) - with self.assertRaises(EventRepositoryException): + with self.assertRaises(DeltaRepositoryException): await self.repository.update(Car(3, "blue"), created_at=current_datetime()) - with self.assertRaises(EventRepositoryException): + with self.assertRaises(DeltaRepositoryException): await self.repository.update(Car(3, "blue"), updated_at=current_datetime()) async def test_refresh(self): @@ -200,9 +200,9 @@ async def test_save_update(self): self.assertEqual(expected, await self.repository.get(Car, uuid)) async def test_save_raises(self): - with self.assertRaises(EventRepositoryException): + with self.assertRaises(DeltaRepositoryException): await self.repository.save(Car(3, "blue", uuid=uuid4())) - with self.assertRaises(EventRepositoryException): + with self.assertRaises(DeltaRepositoryException): await self.repository.save(Car(3, "blue", version=1)) async def test_delete(self): diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_deltas.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_deltas.py index 21cb0ee22..64d5761c2 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_deltas.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_deltas.py @@ -5,8 +5,8 @@ from minos.aggregate import ( Action, + Delta, EntityRepository, - Event, FieldDiff, FieldDiffContainer, Ref, @@ -27,7 +27,7 @@ async def test_create(self): car, delta = await self.repository.create(Car, doors=3, color="blue") self.assertEqual( - Event( + Delta( uuid=car.uuid, name=Car.classname, version=1, @@ -50,7 +50,7 @@ async def test_update(self): _, delta = await self.repository.update(car, color="red") self.assertEqual( - Event( + Delta( uuid=car.uuid, name=Car.classname, version=2, @@ -67,7 +67,7 @@ async def test_delete(self): delta = await self.repository.delete(car) self.assertEqual( - Event( + Delta( uuid=car.uuid, name=Car.classname, version=2, diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py index b11622997..123e38e61 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py @@ -3,9 +3,9 @@ from minos.aggregate import ( AggregateException, AlreadyDeletedException, - Event, - EventRepositoryConflictException, - EventRepositoryException, + Delta, + DeltaRepositoryConflictException, + DeltaRepositoryException, NotFoundException, SnapshotRepositoryConflictException, SnapshotRepositoryException, @@ -23,15 +23,15 @@ class TestExceptions(AggregateTestCase): def test_base(self): self.assertTrue(issubclass(AggregateException, MinosException)) - def test_event(self): - self.assertTrue(issubclass(EventRepositoryException, AggregateException)) + def test_delta(self): + self.assertTrue(issubclass(DeltaRepositoryException, AggregateException)) - def test_event_conflict(self): + def test_delta_conflict(self): message = "There was a conflict" offset = 56 - exception = EventRepositoryConflictException(message, offset) + exception = DeltaRepositoryConflictException(message, offset) - self.assertIsInstance(exception, EventRepositoryException) + self.assertIsInstance(exception, DeltaRepositoryException) self.assertEqual(message, str(exception)) self.assertEqual(offset, exception.offset) @@ -40,12 +40,12 @@ def test_snapshot(self): def test_snapshot_conflict(self): entity = Car(3, "red") - event = Event.from_root_entity(entity) - exception = SnapshotRepositoryConflictException(entity, event) + delta = Delta.from_root_entity(entity) + exception = SnapshotRepositoryConflictException(entity, delta) self.assertIsInstance(exception, SnapshotRepositoryException) self.assertEqual(entity, exception.previous) - self.assertEqual(event, exception.event) + self.assertEqual(delta, exception.delta) def test_snapshot_not_found(self): self.assertTrue(issubclass(NotFoundException, SnapshotRepositoryException)) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py index bba41062e..4ef65906a 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_impl.py @@ -13,7 +13,7 @@ from minos.aggregate import ( Action, Aggregate, - Event, + Delta, FieldDiff, FieldDiffContainer, IncrementalFieldDiff, @@ -60,7 +60,7 @@ def test_root_raises(self): async def test_from_config(self): self.assertEqual(self.transaction_repository, self.aggregate.transaction_repository) - self.assertEqual(self.event_repository, self.aggregate.event_repository) + self.assertEqual(self.delta_repository, self.aggregate.delta_repository) self.assertEqual(self.snapshot_repository, self.aggregate.snapshot_repository) self.assertEqual(self.broker_publisher, self.aggregate.broker_publisher) @@ -68,7 +68,7 @@ async def test_from_config_with_custom_publisher(self): with patch.object(Config, "get_aggregate", return_value={"publisher": {"client": InMemoryBrokerPublisher}}): async with OrderAggregate.from_config(CONFIG_FILE_PATH) as aggregate: self.assertEqual(self.transaction_repository, aggregate.transaction_repository) - self.assertEqual(self.event_repository, aggregate.event_repository) + self.assertEqual(self.delta_repository, aggregate.delta_repository) self.assertEqual(self.snapshot_repository, aggregate.snapshot_repository) self.assertIsInstance(aggregate.broker_publisher, InMemoryBrokerPublisher) self.assertNotEqual(self.broker_publisher, aggregate.broker_publisher) @@ -77,7 +77,7 @@ def test_from_config_raises(self): with self.assertRaises(NotProvidedException): OrderAggregate.from_config(CONFIG_FILE_PATH, transaction_repository=None) with self.assertRaises(NotProvidedException): - OrderAggregate.from_config(CONFIG_FILE_PATH, event_repository=None) + OrderAggregate.from_config(CONFIG_FILE_PATH, delta_repository=None) with self.assertRaises(NotProvidedException): OrderAggregate.from_config(CONFIG_FILE_PATH, snapshot_repository=None) with self.assertRaises(NotProvidedException): @@ -92,7 +92,7 @@ async def test_publish_domain_event_none(self): self.assertEqual(list(), self.broker_publisher.messages) async def test_publish_domain_event_create(self): - delta = Event( + delta = Delta( uuid=uuid4(), name=Car.classname, version=1, @@ -116,7 +116,7 @@ async def test_publish_domain_event_create(self): self.assertEqual(delta, observed[0].content) async def test_publish_domain_event_update(self): - delta = Event( + delta = Delta( uuid=uuid4(), name=Car.classname, version=2, @@ -142,7 +142,7 @@ async def test_publish_domain_event_update(self): self.assertIsInstance(observed[1], BrokerMessageV1) self.assertEqual("CarUpdated.color", observed[1].topic) self.assertEqual( - Event( + Delta( uuid=delta.uuid, name=Car.classname, version=2, @@ -156,7 +156,7 @@ async def test_publish_domain_event_update(self): self.assertIsInstance(observed[2], BrokerMessageV1) self.assertEqual("CarUpdated.doors.create", observed[2].topic) self.assertEqual( - Event( + Delta( uuid=delta.uuid, name=Car.classname, version=2, @@ -168,7 +168,7 @@ async def test_publish_domain_event_update(self): ) async def test_publish_domain_event_delete(self): - delta = Event( + delta = Delta( uuid=uuid4(), name=Car.classname, version=2, diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py index 6d597c56d..b0afaf616 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py @@ -12,8 +12,8 @@ from minos.aggregate import ( AlreadyDeletedException, - Event, - EventEntry, + Delta, + DeltaEntry, SnapshotEntry, ) from minos.common import ( @@ -89,17 +89,17 @@ def test_from_root_entity(self): self.assertEqual(car.created_at, entry.created_at) self.assertEqual(car.updated_at, entry.updated_at) - def test_from_event_entry(self): + def test_from_delta_entry(self): car = Car(3, "blue", uuid=self.uuid, version=1) - event_entry = EventEntry.from_event(Event.from_root_entity(car), version=1) + delta_entry = DeltaEntry.from_delta(Delta.from_root_entity(car), version=1) with patch("minos.common.AvroSchemaEncoder.generate_random_str", return_value="hello"): - snapshot_entry = SnapshotEntry.from_event_entry(event_entry) - self.assertEqual(event_entry.uuid, snapshot_entry.uuid) - self.assertEqual(event_entry.name, snapshot_entry.name) - self.assertEqual(event_entry.version, snapshot_entry.version) - self.assertEqual(event_entry.created_at, snapshot_entry.created_at) - self.assertEqual(event_entry.created_at, snapshot_entry.updated_at) - self.assertEqual(event_entry.transaction_uuid, snapshot_entry.transaction_uuid) + snapshot_entry = SnapshotEntry.from_delta_entry(delta_entry) + self.assertEqual(delta_entry.uuid, snapshot_entry.uuid) + self.assertEqual(delta_entry.name, snapshot_entry.name) + self.assertEqual(delta_entry.version, snapshot_entry.version) + self.assertEqual(delta_entry.created_at, snapshot_entry.created_at) + self.assertEqual(delta_entry.created_at, snapshot_entry.updated_at) + self.assertEqual(delta_entry.transaction_uuid, snapshot_entry.transaction_uuid) def test_equals(self): a = SnapshotEntry(self.uuid, "example.Car", 0, self.schema, self.data) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py index 76eadca7f..21d9be392 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py @@ -35,14 +35,14 @@ class TestDatabaseSnapshotRepository(AggregateTestCase, SnapshotRepositoryTestCa def test_constructor_raises(self): with self.assertRaises(NotProvidedException): # noinspection PyTypeChecker - DatabaseSnapshotRepository(event_repository=None) + DatabaseSnapshotRepository(delta_repository=None) with self.assertRaises(NotProvidedException): # noinspection PyTypeChecker DatabaseSnapshotRepository(transaction_repository=None) async def test_is_synced(self): - self.event_repository.select = MagicMock(side_effect=[FakeAsyncIterator([1]), FakeAsyncIterator([])]) + self.delta_repository.select = MagicMock(side_effect=[FakeAsyncIterator([1]), FakeAsyncIterator([])]) with patch.object(DatabaseClient, "fetch_one", return_value=(0,)): self.assertFalse(await self.snapshot_repository.is_synced(SnapshotRepositoryTestCase.Car)) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_memory.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_memory.py index 0fbc1b325..f70984283 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_memory.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_memory.py @@ -24,7 +24,7 @@ def build_snapshot_repository(self) -> SnapshotRepository: def test_constructor_raises(self): with self.assertRaises(NotProvidedException): # noinspection PyTypeChecker - InMemorySnapshotRepository(event_repository=None) + InMemorySnapshotRepository(delta_repository=None) with self.assertRaises(NotProvidedException): # noinspection PyTypeChecker diff --git a/packages/core/minos-microservice-aggregate/tests/utils.py b/packages/core/minos-microservice-aggregate/tests/utils.py index 5d1bb900f..377441f4f 100644 --- a/packages/core/minos-microservice-aggregate/tests/utils.py +++ b/packages/core/minos-microservice-aggregate/tests/utils.py @@ -20,7 +20,7 @@ Entity, EntitySet, ExternalEntity, - InMemoryEventRepository, + InMemoryDeltaRepository, InMemorySnapshotRepository, Ref, RootEntity, @@ -68,20 +68,20 @@ def get_injections(self): broker_publisher = InMemoryBrokerPublisher() broker_subscriber_builder = InMemoryBrokerSubscriberBuilder() transaction_repository = InMemoryTransactionRepository(lock_pool=pool_factory.get_pool("lock")) - event_repository = InMemoryEventRepository( + delta_repository = InMemoryDeltaRepository( broker_publisher=broker_publisher, transaction_repository=transaction_repository, lock_pool=pool_factory.get_pool("lock"), ) snapshot_repository = InMemorySnapshotRepository( - event_repository=event_repository, transaction_repository=transaction_repository + delta_repository=delta_repository, transaction_repository=transaction_repository ) return [ pool_factory, broker_publisher, broker_subscriber_builder, transaction_repository, - event_repository, + delta_repository, snapshot_repository, ] From 61f7a5ee2aae4c2f4fe400a201406052a0f63826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 27 Apr 2022 12:28:06 +0200 Subject: [PATCH 47/75] ISSUE #413 * Fix broken tests on `minos-microservice-cqrs`. --- .../core/minos-microservice-cqrs/minos/cqrs/handlers.py | 4 ++-- .../tests/test_cqrs/test_handlers.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/core/minos-microservice-cqrs/minos/cqrs/handlers.py b/packages/core/minos-microservice-cqrs/minos/cqrs/handlers.py index 53d3770b8..28dafc63c 100644 --- a/packages/core/minos-microservice-cqrs/minos/cqrs/handlers.py +++ b/packages/core/minos-microservice-cqrs/minos/cqrs/handlers.py @@ -8,7 +8,7 @@ ) from minos.aggregate import ( - Event, + Delta, RefResolver, ) @@ -27,7 +27,7 @@ async def handle(cls, diff: T, resolve_references: bool = False, **kwargs) -> T: :param kwargs: Additional named arguments. :return: The original instance with the ``Ref`` references already resolved. """ - if not isinstance(diff, Event) or not resolve_references: + if not isinstance(diff, Delta) or not resolve_references: return diff try: diff --git a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py index 9b866b178..0b6b401e0 100644 --- a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py +++ b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py @@ -8,7 +8,7 @@ from minos.aggregate import ( Action, - Event, + Delta, FieldDiff, FieldDiffContainer, Ref, @@ -32,7 +32,7 @@ def setUp(self) -> None: self.uuid = uuid4() self.bars = [Bar(uuid4(), 1, "hello"), Bar(uuid4(), 1, "world")] self.now = current_datetime() - self.diff = Event( + self.diff = Delta( self.uuid, "Foo", 1, @@ -44,7 +44,7 @@ def setUp(self) -> None: self.broker_pool = BrokerClientPool({}) async def test_handle_resolving_dependencies(self): - value = Event( + value = Delta( self.uuid, "Foo", 1, @@ -71,7 +71,7 @@ async def test_handle_raises(self): with patch("minos.aggregate.RefResolver.resolve", side_effect=ValueError): observed = await PreEventHandler.handle(self.diff, resolve_references=True, broker_pool=self.broker_pool) - expected = Event( + expected = Delta( self.uuid, "Foo", 1, From 6f8007b33a3bba0818b2353924381840a1699495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 27 Apr 2022 12:35:53 +0200 Subject: [PATCH 48/75] ISSUE #413 * Fix broken tests on `minos-database-aiopg`. --- .../minos/common/config/v1.py | 6 +++--- .../tests/config/v1.yml | 2 +- .../tests/config/v2.yml | 2 +- .../test_config/test_v1/test_base.py | 6 +++--- .../test_config/test_v2/test_base.py | 6 +++--- .../test_config/test_v2/test_parameterized.py | 4 ++-- .../minos-microservice-common/tests/utils.py | 4 ++-- .../tests/test_cqrs/test_services.py | 2 +- .../minos/plugins/aiopg/__init__.py | 2 +- .../minos/plugins/aiopg/factories/__init__.py | 2 +- .../aiopg/factories/aggregate/__init__.py | 2 +- .../aiopg/factories/aggregate/events.py | 6 +++--- .../test_aggregate/test_events/test_factory.py | 10 +++++----- .../test_events/test_repositories.py | 18 +++++++++--------- .../minos-database-aiopg/tests/utils.py | 8 ++++---- 15 files changed, 40 insertions(+), 40 deletions(-) diff --git a/packages/core/minos-microservice-common/minos/common/config/v1.py b/packages/core/minos-microservice-common/minos/common/config/v1.py index b7aabd9e6..33ea89e1a 100644 --- a/packages/core/minos-microservice-common/minos/common/config/v1.py +++ b/packages/core/minos-microservice-common/minos/common/config/v1.py @@ -291,7 +291,7 @@ def _get_databases(self) -> dict[str, dict[str, Any]]: databases["broker"] = self._get_database_broker() with suppress(MinosConfigException): - databases["event"] = self._get_database_event() + databases["delta"] = self._get_database_delta() with suppress(MinosConfigException): databases["snapshot"] = self._get_database_snapshot() @@ -303,7 +303,7 @@ def _get_databases(self) -> dict[str, dict[str, Any]]: databases["query"] = self._get_database_query() with suppress(MinosConfigException): - databases["default"] = self._get_database_event() + databases["default"] = self._get_database_delta() return databases @@ -314,7 +314,7 @@ def _get_database_saga(self) -> dict[str, Any]: raw = self._get_database_by_name("saga.storage") return raw - def _get_database_event(self) -> dict[str, Any]: + def _get_database_delta(self) -> dict[str, Any]: return self._get_database_by_name("repository") def _get_database_query(self) -> dict[str, Any]: diff --git a/packages/core/minos-microservice-common/tests/config/v1.yml b/packages/core/minos-microservice-common/tests/config/v1.yml index 950aaa4e1..6e6840c0b 100644 --- a/packages/core/minos-microservice-common/tests/config/v1.yml +++ b/packages/core/minos-microservice-common/tests/config/v1.yml @@ -12,7 +12,7 @@ service: - tests.utils.FakeHttpConnector - tests.utils.FakeBrokerPublisher - tests.utils.FakeBrokerSubscriberBuilder - - tests.utils.FakeEventRepository + - tests.utils.FakeDeltaRepository - tests.utils.FakeSnapshotRepository - tests.utils.FakeTransactionRepository - tests.utils.FakeDiscoveryConnector diff --git a/packages/core/minos-microservice-common/tests/config/v2.yml b/packages/core/minos-microservice-common/tests/config/v2.yml index 0a8e5f1fb..87002721e 100644 --- a/packages/core/minos-microservice-common/tests/config/v2.yml +++ b/packages/core/minos-microservice-common/tests/config/v2.yml @@ -64,7 +64,7 @@ aggregate: entities: - builtins.int repositories: - event: tests.utils.FakeEventRepository + delta: tests.utils.FakeDeltaRepository snapshot: tests.utils.FakeSnapshotRepository transaction: tests.utils.FakeTransactionRepository routers: diff --git a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v1/test_base.py b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v1/test_base.py index 8f9421473..0db122ba0 100644 --- a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v1/test_base.py +++ b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v1/test_base.py @@ -17,8 +17,8 @@ FakeBrokerSubscriberBuilder, FakeCustomInjection, FakeDatabasePool, + FakeDeltaRepository, FakeDiscoveryConnector, - FakeEventRepository, FakeHttpConnector, FakeHttpPort, FakeLockPool, @@ -56,7 +56,7 @@ def test_injections(self): FakeHttpConnector, FakeBrokerPublisher, FakeBrokerSubscriberBuilder, - FakeEventRepository, + FakeDeltaRepository, FakeSnapshotRepository, FakeTransactionRepository, FakeDiscoveryConnector, @@ -237,7 +237,7 @@ def test_database_default(self): def test_database_event(self): config = ConfigV1(self.file_path, with_environment=False) - database_config = config.get_database_by_name("event") + database_config = config.get_database_by_name("delta") self.assertEqual("order_db", database_config["database"]) self.assertEqual("minos", database_config["user"]) self.assertEqual("min0s", database_config["password"]) diff --git a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py index c1716d88a..f0d9b8363 100644 --- a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py +++ b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_base.py @@ -19,8 +19,8 @@ FakeBrokerSubscriberBuilder, FakeCustomInjection, FakeDatabasePool, + FakeDeltaRepository, FakeDiscoveryConnector, - FakeEventRepository, FakeHttpConnector, FakeHttpPort, FakeLockPool, @@ -45,7 +45,7 @@ def test_aggregate(self): "publisher": {"client": bytes, "foo": "bar"}, "entities": [int], "repositories": { - "event": FakeEventRepository, + "delta": FakeDeltaRepository, "snapshot": FakeSnapshotRepository, "transaction": FakeTransactionRepository, }, @@ -66,7 +66,7 @@ def test_injections(self): FakeBrokerSubscriberBuilder(FakeBrokerSubscriber), FakeDiscoveryConnector, FakeSagaManager, - FakeEventRepository, + FakeDeltaRepository, FakeSnapshotRepository, FakeTransactionRepository, FakeAggregate, diff --git a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py index dd9b2d946..2274f82d7 100644 --- a/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py +++ b/packages/core/minos-microservice-common/tests/test_common/test_config/test_v2/test_parameterized.py @@ -16,8 +16,8 @@ FakeBrokerSubscriber, FakeBrokerSubscriberBuilder, FakeCustomInjection, + FakeDeltaRepository, FakeDiscoveryConnector, - FakeEventRepository, FakeSagaManager, FakeSnapshotRepository, FakeTransactionRepository, @@ -42,7 +42,7 @@ def test_injections_nones(self): FakeBrokerSubscriberBuilder(FakeBrokerSubscriber), FakeDiscoveryConnector, FakeSagaManager, - FakeEventRepository, + FakeDeltaRepository, FakeSnapshotRepository, FakeTransactionRepository, FakeAggregate, diff --git a/packages/core/minos-microservice-common/tests/utils.py b/packages/core/minos-microservice-common/tests/utils.py index 2208c598a..ebdf45aad 100644 --- a/packages/core/minos-microservice-common/tests/utils.py +++ b/packages/core/minos-microservice-common/tests/utils.py @@ -182,8 +182,8 @@ class FakeSagaManager: """For testing purposes.""" -@Injectable("event_repository") -class FakeEventRepository: +@Injectable("delta_repository") +class FakeDeltaRepository: """For testing purposes.""" diff --git a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py index 4ebbe5639..2f4ad0331 100644 --- a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py +++ b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py @@ -54,7 +54,7 @@ async def test_constructor(self): self.assertEqual(self.injector.pool_factory, self.service.pool_factory) with self.assertRaises(AttributeError): - self.service.event_repository + self.service.delta_repository async def test_pre_event(self): with patch("minos.cqrs.PreEventHandler.handle") as mock: diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py index 1a2ff659a..d80cd5021 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py @@ -13,7 +13,7 @@ AiopgBrokerQueueDatabaseOperationFactory, AiopgBrokerSubscriberDuplicateValidatorDatabaseOperationFactory, AiopgBrokerSubscriberQueueDatabaseOperationFactory, - AiopgEventDatabaseOperationFactory, + AiopgDeltaDatabaseOperationFactory, AiopgLockDatabaseOperationFactory, AiopgManagementDatabaseOperationFactory, AiopgSnapshotDatabaseOperationFactory, diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py index 28e8086dd..b1f57cbb0 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/__init__.py @@ -1,5 +1,5 @@ from .aggregate import ( - AiopgEventDatabaseOperationFactory, + AiopgDeltaDatabaseOperationFactory, AiopgSnapshotDatabaseOperationFactory, AiopgSnapshotQueryDatabaseOperationBuilder, ) diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/__init__.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/__init__.py index 9441bc05d..57a165063 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/__init__.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/__init__.py @@ -1,5 +1,5 @@ from .events import ( - AiopgEventDatabaseOperationFactory, + AiopgDeltaDatabaseOperationFactory, ) from .snapshots import ( AiopgSnapshotDatabaseOperationFactory, diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/events.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/events.py index 701578bb2..f46df3b1f 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/events.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/events.py @@ -22,7 +22,7 @@ from minos.aggregate import ( Action, - EventDatabaseOperationFactory, + DeltaDatabaseOperationFactory, ) from minos.common import ( ComposedDatabaseOperation, @@ -38,7 +38,7 @@ # noinspection SqlNoDataSourceInspection,SqlResolve,PyMethodMayBeStatic -class AiopgEventDatabaseOperationFactory(EventDatabaseOperationFactory): +class AiopgDeltaDatabaseOperationFactory(DeltaDatabaseOperationFactory): """Aiopg Event Database Operation Factory class.""" def build_table_name(self) -> str: @@ -303,4 +303,4 @@ def build_query_offset(self) -> DatabaseOperation: return AiopgDatabaseOperation(f"SELECT MAX(id) FROM {self.build_table_name()};".strip()) -AiopgDatabaseClient.set_factory(EventDatabaseOperationFactory, AiopgEventDatabaseOperationFactory) +AiopgDatabaseClient.set_factory(DeltaDatabaseOperationFactory, AiopgDeltaDatabaseOperationFactory) diff --git a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_events/test_factory.py b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_events/test_factory.py index 9c33d3906..d2d1194b9 100644 --- a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_events/test_factory.py +++ b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_events/test_factory.py @@ -5,7 +5,7 @@ from minos.aggregate import ( Action, - EventDatabaseOperationFactory, + DeltaDatabaseOperationFactory, ) from minos.common import ( ComposedDatabaseOperation, @@ -13,16 +13,16 @@ ) from minos.plugins.aiopg import ( AiopgDatabaseOperation, - AiopgEventDatabaseOperationFactory, + AiopgDeltaDatabaseOperationFactory, ) -class TestAiopgEventDatabaseOperationFactory(unittest.TestCase): +class TestAiopgDeltaDatabaseOperationFactory(unittest.TestCase): def setUp(self) -> None: - self.factory = AiopgEventDatabaseOperationFactory() + self.factory = AiopgDeltaDatabaseOperationFactory() def test_is_subclass(self): - self.assertTrue(issubclass(AiopgEventDatabaseOperationFactory, EventDatabaseOperationFactory)) + self.assertTrue(issubclass(AiopgDeltaDatabaseOperationFactory, DeltaDatabaseOperationFactory)) def test_build_table_name(self): self.assertEqual("aggregate_event", self.factory.build_table_name()) diff --git a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_events/test_repositories.py b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_events/test_repositories.py index bf57368d0..9d1f836af 100644 --- a/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_events/test_repositories.py +++ b/packages/plugins/minos-database-aiopg/tests/test_aiopg/test_factories/test_aggregate/test_events/test_repositories.py @@ -1,11 +1,11 @@ import unittest from minos.aggregate import ( - DatabaseEventRepository, - EventRepository, + DatabaseDeltaRepository, + DeltaRepository, ) from minos.aggregate.testing import ( - EventRepositoryTestCase, + DeltaRepositoryTestCase, ) from minos.common import ( DatabaseClientPool, @@ -20,21 +20,21 @@ # noinspection SqlNoDataSourceInspection -class TestDatabaseEventRepositorySubmit(AiopgTestCase, EventRepositoryTestCase): +class TestDatabaseDeltaRepositorySubmit(AiopgTestCase, DeltaRepositoryTestCase): __test__ = True - def build_event_repository(self) -> EventRepository: + def build_delta_repository(self) -> DeltaRepository: """Fort testing purposes.""" - return DatabaseEventRepository.from_config(self.config) + return DatabaseDeltaRepository.from_config(self.config) def test_constructor(self): pool = DatabaseClientPool.from_config(self.config) - repository = DatabaseEventRepository(pool) - self.assertIsInstance(repository, DatabaseEventRepository) + repository = DatabaseDeltaRepository(pool) + self.assertIsInstance(repository, DatabaseDeltaRepository) self.assertIsInstance(repository.database_pool, DatabaseClientPool) def test_from_config(self): - repository = DatabaseEventRepository.from_config(self.config) + repository = DatabaseDeltaRepository.from_config(self.config) self.assertIsInstance(repository.database_pool, DatabaseClientPool) async def test_setup(self): diff --git a/packages/plugins/minos-database-aiopg/tests/utils.py b/packages/plugins/minos-database-aiopg/tests/utils.py index b6d0ce527..2c8c03c41 100644 --- a/packages/plugins/minos-database-aiopg/tests/utils.py +++ b/packages/plugins/minos-database-aiopg/tests/utils.py @@ -3,7 +3,7 @@ ) from minos.aggregate import ( - InMemoryEventRepository, + InMemoryDeltaRepository, InMemorySnapshotRepository, ) from minos.common import ( @@ -46,13 +46,13 @@ def get_injections(self): transaction_repository = InMemoryTransactionRepository( lock_pool=pool_factory.get_pool("lock"), ) - event_repository = InMemoryEventRepository( + delta_repository = InMemoryDeltaRepository( broker_publisher=broker_publisher, transaction_repository=transaction_repository, lock_pool=pool_factory.get_pool("lock"), ) snapshot_repository = InMemorySnapshotRepository( - event_repository=event_repository, + delta_repository=delta_repository, transaction_repository=transaction_repository, ) return [ @@ -60,7 +60,7 @@ def get_injections(self): broker_publisher, broker_subscriber_builder, transaction_repository, - event_repository, + delta_repository, snapshot_repository, ] From b5463661413afe464e9697b2ed3dec1aaea81bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 27 Apr 2022 14:45:05 +0200 Subject: [PATCH 49/75] ISSUE #175 * Refactor `Delta` constructor methods. --- .../minos/aggregate/deltas/models.py | 30 ++++++------------- .../minos/aggregate/entities/repositories.py | 5 ++-- .../test_aggregate/test_deltas/test_models.py | 24 +++++++-------- .../tests/test_aggregate/test_exceptions.py | 2 +- .../test_snapshots/test_entries.py | 2 +- 5 files changed, 26 insertions(+), 37 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py index ccdea14c2..f39982535 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py @@ -36,7 +36,7 @@ if TYPE_CHECKING: from ..entities import ( - RootEntity, + Entity, ) logger = logging.getLogger(__name__) @@ -126,7 +126,7 @@ def get_fields(self, return_diff: bool = False) -> dict[str, Union[FieldDiff, An return self.fields_diff.get_all(return_diff) @classmethod - def from_difference(cls, a: RootEntity, b: RootEntity, action: Action = Action.UPDATE) -> Delta: + def from_difference(cls, a: Entity, b: Entity, action: Action = Action.UPDATE) -> Delta: """Build an ``Delta`` instance from the difference of two instances. :param a: One ``RootEntity`` instance. @@ -155,15 +155,20 @@ def from_difference(cls, a: RootEntity, b: RootEntity, action: Action = Action.U ) @classmethod - def from_root_entity(cls, instance: RootEntity, action: Action = Action.CREATE) -> Delta: + def from_entity(cls, instance: Entity, action: Action = Action.CREATE) -> Delta: """Build an ``Delta`` from a ``RootEntity`` (considering all fields as differences). :param instance: A ``RootEntity`` instance. :param action: The action that generates the delta. :return: An ``Delta`` instance. """ + if action != Action.DELETE: + fields_diff = FieldDiffContainer.from_model( + instance, ignore={"uuid", "version", "created_at", "updated_at"} + ) + else: + fields_diff = FieldDiffContainer.empty() - fields_diff = FieldDiffContainer.from_model(instance, ignore={"uuid", "version", "created_at", "updated_at"}) return cls( uuid=instance.uuid, name=instance.classname, @@ -173,23 +178,6 @@ def from_root_entity(cls, instance: RootEntity, action: Action = Action.CREATE) fields_diff=fields_diff, ) - @classmethod - def from_deleted_root_entity(cls, instance: RootEntity, action: Action = Action.DELETE) -> Delta: - """Build an ``Delta`` from a ``RootEntity`` (considering all fields as differences). - - :param instance: A ``RootEntity`` instance. - :param action: The action that generates the delta. - :return: An ``Delta`` instance. - """ - return cls( - uuid=instance.uuid, - name=instance.classname, - version=instance.version, - action=action, - created_at=instance.updated_at, - fields_diff=FieldDiffContainer.empty(), - ) - def decompose(self) -> list[Delta]: """Decompose the ``Delta`` fields into multiple ``Delta`` instances with once Field. diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py index 28928aea0..2d099fe7d 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py @@ -16,6 +16,7 @@ Inject, NotProvidedException, ) +from ..actions import Action from ..deltas import ( Delta, @@ -150,7 +151,7 @@ async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> f"Obtained: args={args!r}, kwargs={kwargs!r}" ) - delta = Delta.from_root_entity(instance) + delta = Delta.from_entity(instance) entry = await self._delta_repository.submit(delta) self._update_from_repository_entry(instance, entry) @@ -234,7 +235,7 @@ async def delete(self, instance: T) -> Delta: :return: This method does not return anything. """ - delta = Delta.from_deleted_root_entity(instance) + delta = Delta.from_entity(instance, action=Action.DELETE) entry = await self._delta_repository.submit(delta) self._update_from_repository_entry(instance, entry) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_models.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_models.py index 581579584..b2c4c59fa 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_models.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_models.py @@ -56,26 +56,26 @@ def test_simplified_name(self): def test_total_ordering(self): observed = [ - Delta.from_root_entity(Car(3, "blue", version=4)), - Delta.from_root_entity(Car(3, "blue", version=1)), - Delta.from_root_entity(Car(3, "blue", version=3)), - Delta.from_root_entity(Car(3, "blue", version=2)), + Delta.from_entity(Car(3, "blue", version=4)), + Delta.from_entity(Car(3, "blue", version=1)), + Delta.from_entity(Car(3, "blue", version=3)), + Delta.from_entity(Car(3, "blue", version=2)), ] observed.sort() expected = [ - Delta.from_root_entity(Car(3, "blue", version=1)), - Delta.from_root_entity(Car(3, "blue", version=2)), - Delta.from_root_entity(Car(3, "blue", version=3)), - Delta.from_root_entity(Car(3, "blue", version=4)), + Delta.from_entity(Car(3, "blue", version=1)), + Delta.from_entity(Car(3, "blue", version=2)), + Delta.from_entity(Car(3, "blue", version=3)), + Delta.from_entity(Car(3, "blue", version=4)), ] self.assertEqual(expected, observed) - def test_from_root_entity(self): - observed = Delta.from_root_entity(self.initial) + def test_from_entity(self): + observed = Delta.from_entity(self.initial) self.assertEqual(self.diff, observed) - def test_from_deleted_root_entity(self): + def test_from_entity_deleted(self): expected = Delta( uuid=self.uuid, name=Car.classname, @@ -84,7 +84,7 @@ def test_from_deleted_root_entity(self): created_at=self.initial.updated_at, fields_diff=FieldDiffContainer.empty(), ) - observed = Delta.from_deleted_root_entity(self.initial) + observed = Delta.from_entity(self.initial, action=Action.DELETE) self.assertEqual(expected, observed) def test_from_difference(self): diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py index 123e38e61..73527a576 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_exceptions.py @@ -40,7 +40,7 @@ def test_snapshot(self): def test_snapshot_conflict(self): entity = Car(3, "red") - delta = Delta.from_root_entity(entity) + delta = Delta.from_entity(entity) exception = SnapshotRepositoryConflictException(entity, delta) self.assertIsInstance(exception, SnapshotRepositoryException) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py index b0afaf616..b4f5f2bb3 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py @@ -91,7 +91,7 @@ def test_from_root_entity(self): def test_from_delta_entry(self): car = Car(3, "blue", uuid=self.uuid, version=1) - delta_entry = DeltaEntry.from_delta(Delta.from_root_entity(car), version=1) + delta_entry = DeltaEntry.from_delta(Delta.from_entity(car), version=1) with patch("minos.common.AvroSchemaEncoder.generate_random_str", return_value="hello"): snapshot_entry = SnapshotEntry.from_delta_entry(delta_entry) self.assertEqual(delta_entry.uuid, snapshot_entry.uuid) From a2310304d38f070007665d6218e3302aacd76ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 27 Apr 2022 15:20:58 +0200 Subject: [PATCH 50/75] ISSUE #175 * Minor change. --- .../minos/aggregate/entities/repositories.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py index 2d099fe7d..8545dfe21 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py @@ -34,12 +34,12 @@ SnapshotRepository, ) from .models import ( - RootEntity, + Entity, ) logger = logging.getLogger(__name__) -T = TypeVar("T", bound=RootEntity) +T = TypeVar("T", bound=Entity) class EntityRepository: From fc46b37eefeb1edd16dacc6195d76f5a21a3ed6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Tue, 3 May 2022 13:20:27 +0200 Subject: [PATCH 51/75] ISSUE #65 * Minor improvements related with `minos-microservice-transactions`. --- .../workflows/minos-database-aiopg-tests.yml | 1 + .../minos-microservice-aggregate-tests.yml | 1 + .../minos-microservice-saga-tests.yml | 2 +- .../poetry.lock | 48 +++++++++---------- .../pyproject.toml | 8 ++-- poetry.lock | 24 +++++++++- 6 files changed, 53 insertions(+), 31 deletions(-) diff --git a/.github/workflows/minos-database-aiopg-tests.yml b/.github/workflows/minos-database-aiopg-tests.yml index 9dbc735cc..f19cc6f08 100644 --- a/.github/workflows/minos-database-aiopg-tests.yml +++ b/.github/workflows/minos-database-aiopg-tests.yml @@ -10,6 +10,7 @@ on: - 'packages/plugins/minos-database-aiopg/**' - 'packages/core/minos-microservice-aggregate/**' - 'packages/core/minos-microservice-networks/**' + - 'packages/core/minos-microservice-transactions/**' - 'packages/core/minos-microservice-common/**' jobs: diff --git a/.github/workflows/minos-microservice-aggregate-tests.yml b/.github/workflows/minos-microservice-aggregate-tests.yml index 4b8604ea6..4f1364e53 100644 --- a/.github/workflows/minos-microservice-aggregate-tests.yml +++ b/.github/workflows/minos-microservice-aggregate-tests.yml @@ -9,6 +9,7 @@ on: paths: - 'packages/core/minos-microservice-aggregate/**' - 'packages/core/minos-microservice-networks/**' + - 'packages/core/minos-microservice-transactions/**' - 'packages/core/minos-microservice-common/**' jobs: diff --git a/.github/workflows/minos-microservice-saga-tests.yml b/.github/workflows/minos-microservice-saga-tests.yml index dbd6cad17..e32652733 100644 --- a/.github/workflows/minos-microservice-saga-tests.yml +++ b/.github/workflows/minos-microservice-saga-tests.yml @@ -9,7 +9,7 @@ on: paths: - 'packages/core/minos-microservice-saga/**' - 'packages/core/minos-microservice-networks/**' - - 'packages/core/minos-microservice-aggregate/**' + - 'packages/core/minos-microservice-transactions/**' - 'packages/core/minos-microservice-common/**' jobs: diff --git a/packages/core/minos-microservice-transactions/poetry.lock b/packages/core/minos-microservice-transactions/poetry.lock index 251cb1d6b..bd6b50f9b 100644 --- a/packages/core/minos-microservice-transactions/poetry.lock +++ b/packages/core/minos-microservice-transactions/poetry.lock @@ -73,7 +73,7 @@ python-versions = "*" [[package]] name = "click" -version = "8.1.2" +version = "8.1.3" description = "Composable command line interface toolkit" category = "dev" optional = false @@ -134,7 +134,7 @@ yaml = ["pyyaml"] [[package]] name = "fastavro" -version = "1.4.10" +version = "1.4.11" description = "Fast read/write of AVRO files" category = "main" optional = false @@ -191,7 +191,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0.dev1" +version = "0.7.0.dev4" description = "The common core of the Minos Framework" category = "main" optional = false @@ -307,7 +307,7 @@ diagrams = ["railroad-diagrams", "jinja2"] [[package]] name = "pytest" -version = "7.1.1" +version = "7.1.2" description = "pytest: simple powerful testing with Python" category = "dev" optional = false @@ -419,8 +419,8 @@ cached-property = [ {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, ] click = [ - {file = "click-8.1.2-py3-none-any.whl", hash = "sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e"}, - {file = "click-8.1.2.tar.gz", hash = "sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"}, + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, @@ -512,22 +512,22 @@ dependency-injector = [ {file = "dependency_injector-4.39.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ca126bbed370b8c002c859ebeb76f6d83eba2d7fb5d66f37f47cfc19661d2889"}, ] fastavro = [ - {file = "fastavro-1.4.10-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:f225c81e869b3cefef6f2b478cd452693181ed7e645be3cea4d82024354ecaa0"}, - {file = "fastavro-1.4.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7669302c9124b7cd6c1bdff80c77116b2290c984814077fb7d01d7389586054"}, - {file = "fastavro-1.4.10-cp310-cp310-win_amd64.whl", hash = "sha256:995525bdfbdfef205ea148b5bc6a9fe5ccf921931123c39d9aad75a2b661681e"}, - {file = "fastavro-1.4.10-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:64244c53f1e4853184c2f7383d0332e1dcb34c38c05e6613530ade0378e8acfc"}, - {file = "fastavro-1.4.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c60965da6dc7a91e00ccd84d84797fad746555f44e8a816c4cc460fb231c44fe"}, - {file = "fastavro-1.4.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10eb25378f37dc00c10e83c4c0442c1a6d1b871f74a6dfdfc12b6447962bbdd0"}, - {file = "fastavro-1.4.10-cp37-cp37m-win_amd64.whl", hash = "sha256:d5719adf6045fc743de5fa738d561a81e58dc782c94f1b16cb21b5dd6253e7fd"}, - {file = "fastavro-1.4.10-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:24c4a1a8cc92e135ecfcd9cbd1f6cfa088cbc74d78c18e02a609cb11fa33778d"}, - {file = "fastavro-1.4.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0934490b0c3bcfd6bcbacbcb5144c6b5e4298cda209fbb17c856adf5405127dd"}, - {file = "fastavro-1.4.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a23763d73412c077aee401a0368c64cbc23859e26711dbae78a3cf0227f65165"}, - {file = "fastavro-1.4.10-cp38-cp38-win_amd64.whl", hash = "sha256:09f1dfdd8192ae09e0f477d1f024d8054fccdb099ad495d2a796bcee3cadebd1"}, - {file = "fastavro-1.4.10-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:0c6695753fa3035bbd0fa5cb21bf1b5dad39483c669b32ca0bb55fb07c1ccc87"}, - {file = "fastavro-1.4.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35f960dbba04647d8d6d5616f879622d2a1e8a84eb2d2e02a883a22e0803463a"}, - {file = "fastavro-1.4.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9660878ca01e3dbbee12385c5902a2b6b12ecbb5af4733d1026175a14b1ef67f"}, - {file = "fastavro-1.4.10-cp39-cp39-win_amd64.whl", hash = "sha256:64cbd386e408b3bcb2de53b1f847163073eb0d0d0338db65f76051c6ba9a9bc1"}, - {file = "fastavro-1.4.10.tar.gz", hash = "sha256:a24f9dd803c44bfb599476b000f9bd0088f7ac2401e6c20818f38d8af12785a0"}, + {file = "fastavro-1.4.11-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:44f01008f95d685edacc4b10366c755d25612df00924349f7d34a29f08522ce3"}, + {file = "fastavro-1.4.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18f5e736d12e67348f253da8a332d7c3b483ca04f2b6e772befa79d1a46bac9d"}, + {file = "fastavro-1.4.11-cp310-cp310-win_amd64.whl", hash = "sha256:8dca11bc3191cd7de0a3c4b76a70dac493356a219e96ebcde0def1f06faddef7"}, + {file = "fastavro-1.4.11-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:7a2a0bf03686f9d860e8f8476be000f5b3e6cc9af6853dbabab2ef9cfa5dc3a0"}, + {file = "fastavro-1.4.11-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c17e3decfac260e1be4d02d1903d2483eec2f3ce7f92c9b808a0f6a81572c4b"}, + {file = "fastavro-1.4.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19ba25c6529f50722a7618cc4ca24c7d265def57fd9f94e4e554e1df8cce38d2"}, + {file = "fastavro-1.4.11-cp37-cp37m-win_amd64.whl", hash = "sha256:ceaba04da9419f40899a670eb62eb373a127b511bb8e3ae4f6f1f23ec49bd0e4"}, + {file = "fastavro-1.4.11-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:732eab3a1ae5d2c3f4b52e747c55bcc41c4df0eb7e8a395038080741a3c0a934"}, + {file = "fastavro-1.4.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c03d3c802b71f44e7b3442abae961bba996258244bd222b242ad1e5cb7754e57"}, + {file = "fastavro-1.4.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7cb7475a9b25b9f8aebe7eb756dafedd0369434571062f3883d894281befd7c"}, + {file = "fastavro-1.4.11-cp38-cp38-win_amd64.whl", hash = "sha256:ce0776f54591aef90bcd02bd919964abe4c2ad2a10a4336c3a1b66cef289b41c"}, + {file = "fastavro-1.4.11-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:621e72cc365c9539d7590e7b43e48a62e6bfb4c2de7c16837fed54d113d7312c"}, + {file = "fastavro-1.4.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842b25782f911ee8c626f9d9fedc2ef01aeac272536fe90ee6d45b2ae7cdb024"}, + {file = "fastavro-1.4.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8491bfcba25c9d661289f884688e5a4f56f2ee389a240d0ad02692495a9a087"}, + {file = "fastavro-1.4.11-cp39-cp39-win_amd64.whl", hash = "sha256:c94130a8c8d80073eb0276844915aa5e928ae322024e76dc57943542ccda211c"}, + {file = "fastavro-1.4.11.tar.gz", hash = "sha256:7c64332ad52de0134be9a933ca986514c3ff85c63d54bc5398c31f0498ac1820"}, ] flake8 = [ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, @@ -617,8 +617,8 @@ pyparsing = [ {file = "pyparsing-3.0.8.tar.gz", hash = "sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954"}, ] pytest = [ - {file = "pytest-7.1.1-py3-none-any.whl", hash = "sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea"}, - {file = "pytest-7.1.1.tar.gz", hash = "sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63"}, + {file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"}, + {file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"}, ] pyyaml = [ {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, diff --git a/packages/core/minos-microservice-transactions/pyproject.toml b/packages/core/minos-microservice-transactions/pyproject.toml index 8a9906365..b1937eff1 100644 --- a/packages/core/minos-microservice-transactions/pyproject.toml +++ b/packages/core/minos-microservice-transactions/pyproject.toml @@ -21,12 +21,12 @@ keywords = [ "saga", ] packages = [ - { include = "minos" } + { include = "minos" }, ] include = [ - "AUTHORS.md", - "HISTORY.md", - "LICENSE", + { path = "AUTHORS.md", format = "sdist" }, + { path = "HISTORY.md", format = "sdist" }, + { path = "LICENSE", format = "sdist" }, ] [tool.poetry.dependencies] diff --git a/poetry.lock b/poetry.lock index 4ced573c3..e761b7a7b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -597,6 +597,7 @@ aiopg = "^1.2.1" minos-microservice-aggregate = "^0.7.0*" minos-microservice-common = "^0.7.0*" minos-microservice-networks = "^0.7.0*" +minos-microservice-transactions = "^0.7.0*" psycopg2-binary = "^2.9.3" [package.source] @@ -692,6 +693,7 @@ develop = true cached-property = "^1.5.2" minos-microservice-common = "^0.7.0*" minos-microservice-networks = "^0.7.0*" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" @@ -765,14 +767,31 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-aggregate = "^0.7.0*" minos-microservice-common = "^0.7.0*" minos-microservice-networks = "^0.7.0*" +minos-microservice-transactions = "^0.7.0*" [package.source] type = "directory" url = "packages/core/minos-microservice-saga" +[[package]] +name = "minos-microservice-transactions" +version = "0.0.0" +description = "The transactions core of the Minos Framework" +category = "main" +optional = false +python-versions = "^3.9" +develop = true + +[package.dependencies] +cached-property = "^1.5.2" +minos-microservice-common = "^0.7.0*" + +[package.source] +type = "directory" +url = "packages/core/minos-microservice-transactions" + [[package]] name = "minos-router-graphql" version = "0.7.0.dev4" @@ -1308,7 +1327,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest- [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "aaacb6ce77b50b2d9589e233496a4e0af9713e9156ace0f4f12b4dd3a4ebcfef" +content-hash = "904cd0155e041277a9d0b51612836a71634e6dd7831bc95b100feb04cd9d7f38" [metadata.files] aio-pika = [ @@ -1822,6 +1841,7 @@ minos-microservice-common = [] minos-microservice-cqrs = [] minos-microservice-networks = [] minos-microservice-saga = [] +minos-microservice-transactions = [] minos-router-graphql = [] mistune = [ {file = "mistune-0.8.4-py2.py3-none-any.whl", hash = "sha256:88a1051873018da288eee8538d476dffe1262495144b33ecb586c4ab266bb8d4"}, From 95982ff323fdf939ab6252a4558c5ec78563967a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Tue, 3 May 2022 14:59:18 +0200 Subject: [PATCH 52/75] ISSUE #175 * Replacing `RootEntity` by `Entity`. --- .../minos/aggregate/deltas/entries.py | 14 +++--- .../minos/aggregate/deltas/models.py | 12 ++--- .../aggregate/deltas/repositories/abc.py | 4 +- .../minos/aggregate/entities/repositories.py | 20 ++++---- .../minos/aggregate/exceptions.py | 8 +-- .../minos/aggregate/snapshots/entries.py | 22 ++++---- .../aggregate/snapshots/repositories/abc.py | 50 +++++++++---------- .../repositories/database/factories.py | 8 +-- .../snapshots/repositories/database/impl.py | 14 +++--- .../snapshots/repositories/memory.py | 2 +- .../minos/aggregate/snapshots/services.py | 8 +-- .../minos/transactions/repositories/abc.py | 2 +- .../factories/aggregate/snapshots/impl.py | 10 ++-- 13 files changed, 88 insertions(+), 86 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/entries.py index 1d95f63e6..aebd342e6 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/entries.py @@ -20,6 +20,9 @@ NULL_UUID, import_module, ) +from minos.transactions import ( + TransactionEntry, +) from ..actions import ( Action, @@ -33,10 +36,7 @@ if TYPE_CHECKING: from ..entities import ( - RootEntity, - ) - from ..transactions import ( - TransactionEntry, + Entity, ) @@ -83,7 +83,7 @@ def __init__( @classmethod def from_delta(cls, delta: Delta, *, transaction: Optional[TransactionEntry] = None, **kwargs) -> DeltaEntry: - """Build a new instance from a ``RootEntity``. + """Build a new instance from a ``Entity``. :param delta: The delta. :param transaction: Optional transaction. @@ -129,8 +129,8 @@ def as_raw(self) -> dict[str, Any]: } @property - def type_(self) -> type[RootEntity]: - """Load the concrete ``RootEntity`` class. + def type_(self) -> type[Entity]: + """Load the concrete ``Entity`` class. :return: A ``Type`` object. """ diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py index f39982535..347ad2b9d 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py @@ -56,7 +56,7 @@ class Delta(DeclarativeModel): @property def simplified_name(self) -> str: - """Get the RootEntity's simplified name. + """Get the Entity's simplified name. :return: An string value. """ @@ -129,9 +129,9 @@ def get_fields(self, return_diff: bool = False) -> dict[str, Union[FieldDiff, An def from_difference(cls, a: Entity, b: Entity, action: Action = Action.UPDATE) -> Delta: """Build an ``Delta`` instance from the difference of two instances. - :param a: One ``RootEntity`` instance. - :param b: Another ``RootEntity`` instance. - :param action: The action that generates the ``RootEntity`` difference. + :param a: One ``Entity`` instance. + :param b: Another ``Entity`` instance. + :param action: The action that generates the ``Entity`` difference. :return: An ``Delta`` instance. """ logger.debug(f"Computing the {cls!r} between {a!r} and {b!r}...") @@ -156,9 +156,9 @@ def from_difference(cls, a: Entity, b: Entity, action: Action = Action.UPDATE) - @classmethod def from_entity(cls, instance: Entity, action: Action = Action.CREATE) -> Delta: - """Build an ``Delta`` from a ``RootEntity`` (considering all fields as differences). + """Build an ``Delta`` from a ``Entity`` (considering all fields as differences). - :param instance: A ``RootEntity`` instance. + :param instance: A ``Entity`` instance. :param action: The action that generates the delta. :return: An ``Delta`` instance. """ diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/abc.py index b457cb841..ce5b5b4a5 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/repositories/abc.py @@ -55,7 +55,7 @@ if TYPE_CHECKING: from ...entities import ( - RootEntity, + Entity, ) @@ -185,7 +185,7 @@ async def _submit(self, entry: DeltaEntry, **kwargs) -> DeltaEntry: async def select( self, uuid: Optional[UUID] = None, - name: Optional[Union[str, type[RootEntity]]] = None, + name: Optional[Union[str, type[Entity]]] = None, version: Optional[int] = None, version_lt: Optional[int] = None, version_gt: Optional[int] = None, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py index 8545dfe21..3a96b0e72 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py @@ -16,8 +16,10 @@ Inject, NotProvidedException, ) -from ..actions import Action +from ..actions import ( + Action, +) from ..deltas import ( Delta, DeltaEntry, @@ -71,7 +73,7 @@ async def get(self, type_: type[T], uuid: UUID, **kwargs) -> T: :param type_: The of the entity to be looked for. :param uuid: The identifier of the instance. - :return: A ``RootEntity`` instance. + :return: A ``Entity`` instance. """ # noinspection PyTypeChecker return await self._snapshot_repository.get(type_, uuid, **kwargs) @@ -90,7 +92,7 @@ def get_all( is to retrieve them without any order pattern. :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the instances that meet the given condition. - :return: A ``RootEntity`` instance. + :return: A ``Entity`` instance. """ # noinspection PyTypeChecker return self._snapshot_repository.get_all(type_, ordering, limit, **kwargs) @@ -111,19 +113,19 @@ def find( is to retrieve them without any order pattern. :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the instances that meet the given condition. - :return: An asynchronous iterator of ``RootEntity`` instances. + :return: An asynchronous iterator of ``Entity`` instances. """ # noinspection PyTypeChecker return self._snapshot_repository.find(type_, condition, ordering, limit, **kwargs) async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> tuple[T, Delta]: - """Create a new ``RootEntity`` instance. + """Create a new ``Entity`` instance. :param type_or_instance: The instance to be created. If it is a ``type`` then the instance is created internally using ``args`` and ``kwargs`` as parameters. :param args: Additional positional arguments. :param kwargs: Additional named arguments. - :return: A new ``RootEntity`` instance. + :return: A new ``Entity`` instance. """ if "uuid" in kwargs: raise DeltaRepositoryException( @@ -147,7 +149,7 @@ async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> instance = type_or_instance if len(args) or len(kwargs): raise DeltaRepositoryException( - f"Additional parameters are not provided when passing an already built {RootEntity!r} instance. " + f"Additional parameters are not provided when passing an already built {Entity!r} instance. " f"Obtained: args={args!r}, kwargs={kwargs!r}" ) @@ -160,11 +162,11 @@ async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> # noinspection PyMethodParameters,PyShadowingBuiltins async def update(self, instance: T, **kwargs) -> tuple[T, Optional[Delta]]: - """Update an existing ``RootEntity`` instance. + """Update an existing ``Entity`` instance. :param instance: The instance to be updated. :param kwargs: Additional named arguments. - :return: An updated ``RootEntity`` instance. + :return: An updated ``Entity`` instance. """ if "version" in kwargs: diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py b/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py index c0ab98e74..b4127f6ee 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/exceptions.py @@ -15,7 +15,7 @@ Delta, ) from .entities import ( - RootEntity, + Entity, ) @@ -42,7 +42,7 @@ class SnapshotRepositoryException(AggregateException): class SnapshotRepositoryConflictException(SnapshotRepositoryException): """Exception to be raised when current version is newer than the one to be processed.""" - def __init__(self, previous: RootEntity, delta: Delta): + def __init__(self, previous: Entity, delta: Delta): self.previous = previous self.delta = delta super().__init__( @@ -52,11 +52,11 @@ def __init__(self, previous: RootEntity, delta: Delta): class NotFoundException(SnapshotRepositoryException): - """Exception to be raised when a ``RootEntity`` is not found on the repository.""" + """Exception to be raised when a ``Entity`` is not found on the repository.""" class AlreadyDeletedException(SnapshotRepositoryException): - """Exception to be raised when a ``RootEntity`` is already deleted from the repository.""" + """Exception to be raised when a ``Entity`` is already deleted from the repository.""" class ValueObjectException(AggregateException): diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py index c0ebdef96..87633f903 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py @@ -32,7 +32,7 @@ if TYPE_CHECKING: from ..entities import ( - RootEntity, + Entity, ) @@ -75,10 +75,10 @@ def __init__( self.transaction_uuid = transaction_uuid @classmethod - def from_root_entity(cls, instance: RootEntity, **kwargs) -> SnapshotEntry: - """Build a new instance from a ``RootEntity``. + def from_root_entity(cls, instance: Entity, **kwargs) -> SnapshotEntry: + """Build a new instance from a ``Entity``. - :param instance: The ``RootEntity`` instance. + :param instance: The ``Entity`` instance. :return: A new ``SnapshotEntry`` instance. """ data = {k: v for k, v in instance.avro_data.items() if k not in {"uuid", "version", "created_at", "updated_at"}} @@ -149,14 +149,14 @@ def encoded_data(self) -> Optional[str]: return json.dumps(self.data) - def build(self, **kwargs) -> RootEntity: - """Rebuild the stored ``RootEntity`` object instance from the internal state. + def build(self, **kwargs) -> Entity: + """Rebuild the stored ``Entity`` object instance from the internal state. :param kwargs: Additional named arguments. - :return: A ``RootEntity`` instance. + :return: A ``Entity`` instance. """ from ..entities import ( - RootEntity, + Entity, ) if self.data is None: @@ -169,12 +169,12 @@ def build(self, **kwargs) -> RootEntity: "updated_at": self.updated_at, } data |= kwargs - instance = RootEntity.from_avro(self.schema, data) + instance = Entity.from_avro(self.schema, data) return instance @property - def type_(self) -> type[RootEntity]: - """Load the concrete ``RootEntity`` class. + def type_(self) -> type[Entity]: + """Load the concrete ``Entity`` class. :return: A ``Type`` object. """ diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py index 51ae15417..658f43bd0 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py @@ -42,7 +42,7 @@ if TYPE_CHECKING: from ...entities import ( - RootEntity, + Entity, ) @@ -50,26 +50,26 @@ class SnapshotRepository(ABC, SetupMixin): """Base Snapshot class. - The snapshot provides a direct accessor to the ``RootEntity`` instances stored as deltas by the delta repository + The snapshot provides a direct accessor to the ``Entity`` instances stored as deltas by the delta repository class. """ async def get( self, - name: Union[str, type[RootEntity]], + name: Union[str, type[Entity]], uuid: UUID, transaction: Optional[TransactionEntry] = None, **kwargs, - ) -> RootEntity: - """Get a ``RootEntity`` instance from its identifier. + ) -> Entity: + """Get a ``Entity`` instance from its identifier. - :param name: Class name of the ``RootEntity``. - :param uuid: Identifier of the ``RootEntity``. + :param name: Class name of the ``Entity``. + :param uuid: Identifier of the ``Entity``. :param transaction: The transaction within the operation is performed. If not any value is provided, then the transaction is extracted from the context var. If not any transaction is being scoped then the query is performed to the global snapshot. :param kwargs: Additional named arguments. - :return: The ``RootEntity`` instance. + :return: The ``Entity`` instance. """ snapshot_entry = await self.get_entry(name, uuid, transaction=transaction, **kwargs) instance = snapshot_entry.build(**kwargs) @@ -78,8 +78,8 @@ async def get( async def get_entry(self, name: str, uuid: UUID, **kwargs) -> SnapshotEntry: """Get a ``SnapshotEntry`` from its identifier. - :param name: Class name of the ``RootEntity``. - :param uuid: Identifier of the ``RootEntity``. + :param name: Class name of the ``Entity``. + :param uuid: Identifier of the ``Entity``. :param kwargs: Additional named arguments. :return: The ``SnapshotEntry`` instance. """ @@ -99,10 +99,10 @@ def get_all( streaming_mode: bool = False, transaction: Optional[TransactionEntry] = None, **kwargs, - ) -> AsyncIterator[RootEntity]: - """Get all ``RootEntity`` instances. + ) -> AsyncIterator[Entity]: + """Get all ``Entity`` instances. - :param name: Class name of the ``RootEntity``. + :param name: Class name of the ``Entity``. :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour is to retrieve them without any order pattern. :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the @@ -113,7 +113,7 @@ def get_all( transaction is extracted from the context var. If not any transaction is being scoped then the query is performed to the global snapshot. :param kwargs: Additional named arguments. - :return: An asynchronous iterator that containing the ``RootEntity`` instances. + :return: An asynchronous iterator that containing the ``Entity`` instances. """ return self.find( name, @@ -127,18 +127,18 @@ def get_all( async def find( self, - name: Union[str, type[RootEntity]], + name: Union[str, type[Entity]], condition: _Condition, ordering: Optional[_Ordering] = None, limit: Optional[int] = None, streaming_mode: bool = False, transaction: Optional[TransactionEntry] = None, **kwargs, - ) -> AsyncIterator[RootEntity]: - """Find a collection of ``RootEntity`` instances based on a ``Condition``. + ) -> AsyncIterator[Entity]: + """Find a collection of ``Entity`` instances based on a ``Condition``. - :param name: Class name of the ``RootEntity``. - :param condition: The condition that must be satisfied by the ``RootEntity`` instances. + :param name: Class name of the ``Entity``. + :param condition: The condition that must be satisfied by the ``Entity`` instances. :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour is to retrieve them without any order pattern. :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the @@ -149,7 +149,7 @@ async def find( transaction is extracted from the context var. If not any transaction is being scoped then the query is performed to the global snapshot. :param kwargs: Additional named arguments. - :return: An asynchronous iterator that containing the ``RootEntity`` instances. + :return: An asynchronous iterator that containing the ``Entity`` instances. """ iterable = self.find_entries( name=name, @@ -177,8 +177,8 @@ async def find_entries( ) -> AsyncIterator[SnapshotEntry]: """Find a collection of ``SnapshotEntry`` instances based on a ``Condition``. - :param name: Class name of the ``RootEntity``. - :param condition: The condition that must be satisfied by the ``RootEntity`` instances. + :param name: Class name of the ``Entity``. + :param condition: The condition that must be satisfied by the ``Entity`` instances. :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour is to retrieve them without any order pattern. :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the @@ -188,12 +188,12 @@ async def find_entries( :param transaction: The transaction within the operation is performed. If not any value is provided, then the transaction is extracted from the context var. If not any transaction is being scoped then the query is performed to the global snapshot. - :param exclude_deleted: If ``True``, deleted ``RootEntity`` entries are included, otherwise deleted - ``RootEntity`` entries are filtered. + :param exclude_deleted: If ``True``, deleted ``Entity`` entries are included, otherwise deleted + ``Entity`` entries are filtered. :param synchronize: If ``True`` a synchronization is performed before processing the query, otherwise the query is performed without any synchronization step. :param kwargs: Additional named arguments. - :return: An asynchronous iterator that containing the ``RootEntity`` instances. + :return: An asynchronous iterator that containing the ``Entity`` instances. """ if isinstance(name, type): name = classname(name) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/factories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/factories.py index fe0d06937..260538162 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/factories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/factories.py @@ -82,8 +82,8 @@ def build_query( ) -> DatabaseOperation: """Build the query database operation. - :param name: Class name of the ``RootEntity``. - :param condition: The condition that must be satisfied by the ``RootEntity`` instances. + :param name: Class name of the ``Entity``. + :param condition: The condition that must be satisfied by the ``Entity`` instances. :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour is to retrieve them without any order pattern. :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the @@ -91,8 +91,8 @@ def build_query( :param transaction_uuids: The transaction within the operation is performed. If not any value is provided, then the transaction is extracted from the context var. If not any transaction is being scoped then the query is performed to the global snapshot. - :param exclude_deleted: If ``True``, deleted ``RootEntity`` entries are included, otherwise deleted - ``RootEntity`` entries are filtered. + :param exclude_deleted: If ``True``, deleted ``Entity`` entries are included, otherwise deleted + ``Entity`` entries are filtered. :return: A ``DatabaseOperation`` instance. """ diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py index b5d9147e4..39094c76c 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py @@ -56,14 +56,14 @@ if TYPE_CHECKING: from ....entities import ( - RootEntity, + Entity, ) class DatabaseSnapshotRepository(SnapshotRepository, DatabaseMixin[SnapshotDatabaseOperationFactory]): """Database Snapshot Repository class. - The snapshot provides a direct accessor to the ``RootEntity`` instances stored as deltas by the delta repository + The snapshot provides a direct accessor to the ``Entity`` instances stored as deltas by the delta repository class. """ @@ -119,9 +119,9 @@ async def _find_entries( yield SnapshotEntry(*row) async def is_synced(self, name: str, **kwargs) -> bool: - """Check if the snapshot has the latest version of a ``RootEntity`` instance. + """Check if the snapshot has the latest version of a ``Entity`` instance. - :param name: Class name of the ``RootEntity`` to be checked. + :param name: Class name of the ``Entity`` to be checked. :return: ``True`` if it has the latest version for the identifier or ``False`` otherwise. """ offset = await self._load_offset() @@ -179,7 +179,7 @@ async def _submit_update_or_create(self, delta_entry: DeltaEntry, **kwargs) -> S snapshot_entry = await self._submit_entry(snapshot_entry) return snapshot_entry - async def _build_instance(self, delta_entry: DeltaEntry, **kwargs) -> RootEntity: + async def _build_instance(self, delta_entry: DeltaEntry, **kwargs) -> Entity: diff = delta_entry.delta try: @@ -190,7 +190,7 @@ async def _build_instance(self, delta_entry: DeltaEntry, **kwargs) -> RootEntity instance = await self._update_instance_if_exists(diff, transaction=transaction, **kwargs) return instance - async def _update_instance_if_exists(self, delta: Delta, **kwargs) -> RootEntity: + async def _update_instance_if_exists(self, delta: Delta, **kwargs) -> Entity: # noinspection PyBroadException try: # noinspection PyTypeChecker @@ -206,7 +206,7 @@ async def _update_instance_if_exists(self, delta: Delta, **kwargs) -> RootEntity previous.apply_diff(delta) return previous - async def _select_one_instance(self, name: str, uuid: UUID, **kwargs) -> RootEntity: + async def _select_one_instance(self, name: str, uuid: UUID, **kwargs) -> Entity: snapshot_entry = await self.get_entry(name, uuid, **kwargs) return snapshot_entry.build(**kwargs) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py index e1a5af915..9a08dd5c4 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py @@ -52,7 +52,7 @@ class InMemorySnapshotRepository(SnapshotRepository): """InMemory Snapshot class. - The snapshot provides a direct accessor to the ``RootEntity`` instances stored as deltas by the delta repository + The snapshot provides a direct accessor to the ``Entity`` instances stored as deltas by the delta repository class. """ diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/services.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/services.py index f8069ae5f..4222ac805 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/services.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/services.py @@ -36,7 +36,7 @@ if TYPE_CHECKING: from ..entities import ( - RootEntity, + Entity, ) logger = logging.getLogger(__name__) @@ -73,7 +73,7 @@ def __get_enroute__(cls, config: Config) -> dict[str, set[EnrouteDecorator]]: } async def __get_many__(self, request: Request) -> Response: - """Get many ``RootEntity`` instances. + """Get many ``Entity`` instances. :param request: The ``Request`` instance that contains the instance identifiers. :return: A ``Response`` instance containing the requested instances. @@ -92,8 +92,8 @@ async def __get_many__(self, request: Request) -> Response: return Response(instances) @cached_property - def type_(self) -> type[RootEntity]: - """Load the concrete ``RootEntity`` class. + def type_(self) -> type[Entity]: + """Load the concrete ``Entity`` class. :return: A ``Type`` object. """ diff --git a/packages/core/minos-microservice-transactions/minos/transactions/repositories/abc.py b/packages/core/minos-microservice-transactions/minos/transactions/repositories/abc.py index da029fc04..62cb5e193 100644 --- a/packages/core/minos-microservice-transactions/minos/transactions/repositories/abc.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/repositories/abc.py @@ -105,7 +105,7 @@ async def _submit(self, transaction: TransactionEntry) -> TransactionEntry: async def get(self, uuid: UUID, **kwargs) -> TransactionEntry: """Get a ``TransactionEntry`` from its identifier. - :param uuid: Identifier of the ``RootEntity``. + :param uuid: Identifier of the ``TransactionEntry``. :param kwargs: Additional named arguments. :return: The ``TransactionEntry`` instance. """ diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/snapshots/impl.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/snapshots/impl.py index acc3f9171..58fd2e87e 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/snapshots/impl.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/factories/aggregate/snapshots/impl.py @@ -35,7 +35,7 @@ ) -# noinspection SqlNoDataSourceInspection,SqlResolve +# noinspection SqlNoDataSourceInspection,SqlDialectInspection class AiopgSnapshotDatabaseOperationFactory(SnapshotDatabaseOperationFactory): """Aiopg Snapshot Database Operation Factory class.""" @@ -174,8 +174,8 @@ def build_query( ) -> DatabaseOperation: """Build the query database operation. - :param name: Class name of the ``RootEntity``. - :param condition: The condition that must be satisfied by the ``RootEntity`` instances. + :param name: Class name of the ``Entity``. + :param condition: The condition that must be satisfied by the ``Entity`` instances. :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour is to retrieve them without any order pattern. :param limit: Optional argument to return only a subset of instances. The default behaviour is to return all the @@ -183,8 +183,8 @@ def build_query( :param transaction_uuids: The transaction within the operation is performed. If not any value is provided, then the transaction is extracted from the context var. If not any transaction is being scoped then the query is performed to the global snapshot. - :param exclude_deleted: If ``True``, deleted ``RootEntity`` entries are included, otherwise deleted - ``RootEntity`` entries are filtered. + :param exclude_deleted: If ``True``, deleted ``Entity`` entries are included, otherwise deleted + ``Entity`` entries are filtered. :return: A ``DatabaseOperation`` instance. """ builder = AiopgSnapshotQueryDatabaseOperationBuilder( From f9b50c34c062ec61df11e742989862c17c9430b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Tue, 3 May 2022 15:35:49 +0200 Subject: [PATCH 53/75] ISSUE #175 * Now `Entity` instances are first-level-citizens. --- .../minos/aggregate/entities/collections.py | 39 ++++++++------ .../minos/aggregate/entities/models.py | 47 +++++++---------- .../minos/aggregate/impl.py | 12 ++--- .../snapshots/repositories/testcases.py | 6 +-- .../test_entities/test_collections.py | 52 +++++++++++-------- .../{test_root => test_entity}/__init__.py | 0 .../{ => test_entity}/test_base.py | 4 +- .../test_differences.py | 2 +- .../test_repositories/test_integration.py | 5 +- .../tests/utils.py | 7 ++- .../minos-microservice-cqrs/tests/utils.py | 4 +- 11 files changed, 95 insertions(+), 83 deletions(-) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/{test_root => test_entity}/__init__.py (100%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/{ => test_entity}/test_base.py (89%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/{test_root => test_entity}/test_differences.py (97%) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/collections.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/collections.py index 16c5392c0..f0adfe913 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/collections.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/collections.py @@ -19,6 +19,7 @@ ) from minos.common import ( + NULL_UUID, DataDecoder, DataEncoder, DeclarativeModel, @@ -41,11 +42,17 @@ class EntitySet(IncrementalSet[T]): data: dict[str, T] def __init__(self, data: Optional[Iterable[T]] = None, *args, **kwargs): - if data is None: - data = dict() - elif not isinstance(data, dict): - data = {str(entity.uuid): entity for entity in data} - DeclarativeModel.__init__(self, data, *args, **kwargs) + DeclarativeModel.__init__(self, dict(), *args, **kwargs) + + if isinstance(data, dict): + iterable = data.values() + elif data is not None: + iterable = data + else: + iterable = tuple() + + for entity in iterable: + self.add(entity) def add(self, entity: T) -> None: """Add an entity. @@ -53,17 +60,19 @@ def add(self, entity: T) -> None: :param entity: The entity to be added. :return: This method does not return anything. """ + if entity.uuid == NULL_UUID: + raise ValueError(f"The given entity must have a non-null uuid. Obtained entity: {entity!r}") self.data[str(entity.uuid)] = entity - def discard(self, entity: T) -> None: + def discard(self, uuid: Union[T, UUID]) -> None: """Discard an entity. - :param entity: The entity to be discarded. + :param uuid: The entity to be discarded. :return: This method does not return anything. """ - if not isinstance(entity, UUID): - entity = entity.uuid - self.data.pop(str(entity), None) + if not isinstance(uuid, UUID): + uuid = uuid.uuid + self.data.pop(str(uuid), None) def get(self, uuid: UUID) -> T: """Get an entity by identifier. @@ -73,12 +82,12 @@ def get(self, uuid: UUID) -> T: """ return self.data[str(uuid)] - def __contains__(self, entity: Union[T, UUID]) -> bool: - if not isinstance(entity, UUID): - if not hasattr(entity, "uuid"): + def __contains__(self, uuid: Union[T, UUID]) -> bool: + if not isinstance(uuid, UUID): + if not hasattr(uuid, "uuid"): return False - entity = entity.uuid - return str(entity) in self.data + uuid = uuid.uuid + return str(uuid) in self.data def __iter__(self) -> Iterator[T]: yield from self.data.values() diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py index 7333c5b8d..ea965480b 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py @@ -7,13 +7,11 @@ datetime, ) from typing import ( - Optional, Type, TypeVar, ) from uuid import ( UUID, - uuid4, ) from minos.common import ( @@ -35,27 +33,6 @@ class Entity(DeclarativeModel): uuid: UUID - def __init__(self, *args, uuid: Optional[UUID] = None, **kwargs): - if uuid is None: - uuid = uuid4() - super().__init__(uuid, *args, **kwargs) - - -class ExternalEntity(Entity): - """External Entity class.""" - - version: int - - def __init__(self, uuid: UUID, *args, **kwargs): - super().__init__(uuid=uuid, *args, **kwargs) - - -T = TypeVar("T", bound="RootEntity") - - -class RootEntity(Entity): - """Base Root Entity class.""" - version: int created_at: datetime updated_at: datetime @@ -70,14 +47,14 @@ def __init__( **kwargs, ): - super().__init__(version, created_at, updated_at, *args, uuid=uuid, **kwargs) + super().__init__(uuid, version, created_at, updated_at, *args, **kwargs) - def diff(self, another: RootEntity) -> Delta: + def diff(self, another: Entity) -> Delta: """Compute the difference with another instance. - Both ``RootEntity`` instances (``self`` and ``another``) must share the same ``uuid`` value. + Both ``Entity`` instances (``self`` and ``another``) must share the same ``uuid`` value. - :param another: Another ``RootEntity`` instance. + :param another: Another ``Entity`` instance. :return: An ``FieldDiffContainer`` instance. """ return Delta.from_difference(self, another) @@ -113,7 +90,7 @@ def from_diff(cls: Type[T], delta: Delta, *args, **kwargs) -> T: :param delta: The difference that contains the data. :param args: Additional positional arguments. :param kwargs: Additional named arguments. - :return: A new ``RootEntity`` instance. + :return: A new ``Entity`` instance. """ return cls( *args, @@ -124,3 +101,17 @@ def from_diff(cls: Type[T], delta: Delta, *args, **kwargs) -> T: **delta.get_fields(), **kwargs, ) + + +class ExternalEntity(DeclarativeModel): + """External Entity class.""" + + uuid: UUID + version: int + + +T = TypeVar("T", bound=Entity) + + +class RootEntity(Entity): + """Base Root Entity class.""" diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py index 753ca5251..93d509295 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/impl.py @@ -37,14 +37,14 @@ IncrementalFieldDiff, ) from .entities import ( + Entity, EntityRepository, - RootEntity, ) from .snapshots import ( SnapshotRepository, ) -RT = TypeVar("RT", bound=RootEntity) +RT = TypeVar("RT", bound=Entity) @Injectable("aggregate") @@ -119,16 +119,16 @@ def _check_root(self): self.root # If root is not valid it will raise an exception. @property - def root(self) -> type[RootEntity]: + def root(self) -> type[Entity]: """Get the root entity of the aggregate. - :return: A ``RootEntity`` type. + :return: A ``Entity`` type. """ # noinspection PyUnresolvedReferences bases = self.__orig_bases__ root = get_args(next((base for base in bases if len(get_args(base))), None))[0] - if not isinstance(root, type) or not issubclass(root, RootEntity): - raise TypeError(f"{type(self)!r} must contain a {RootEntity!r} as generic value.") + if not isinstance(root, type) or not issubclass(root, Entity): + raise TypeError(f"{type(self)!r} must contain a {Entity!r} as generic value.") return root async def publish_domain_event(self, delta: Optional[Delta]) -> None: diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py index ef01450bd..f447cffc2 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py @@ -25,12 +25,12 @@ AlreadyDeletedException, Condition, DeltaEntry, + Entity, FieldDiff, FieldDiffContainer, NotFoundException, Ordering, Ref, - RootEntity, SnapshotEntry, SnapshotRepository, ) @@ -52,14 +52,14 @@ class SnapshotRepositoryTestCase(MinosTestCase, ABC): snapshot_repository: SnapshotRepository - class Owner(RootEntity): + class Owner(Entity): """For testing purposes""" name: str surname: str age: Optional[int] - class Car(RootEntity): + class Car(Entity): """For testing purposes""" doors: int diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_collections.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_collections.py index e1acb1035..3033b14ca 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_collections.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_collections.py @@ -5,6 +5,9 @@ from unittest.mock import ( patch, ) +from uuid import ( + uuid4, +) from minos.aggregate import ( Action, @@ -27,65 +30,72 @@ class _NotHashable(Entity): class TestEntitySet(unittest.TestCase): def test_data(self): - raw = {OrderItem("John"), OrderItem("Michael")} + raw = {OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())} entities = EntitySet(raw) self.assertEqual({str(v.uuid): v for v in raw}, entities.data) def test_eq_true(self): - raw = {OrderItem("John"), OrderItem("Michael")} + raw = {OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())} observed = EntitySet(raw) self.assertEqual(EntitySet(raw), observed) self.assertEqual(raw, observed) self.assertEqual({str(v.uuid): v for v in raw}, observed) def test_eq_false(self): - raw = {OrderItem("John"), OrderItem("Michael")} + raw = {OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())} observed = EntitySet(raw) - other = {OrderItem("Charlie")} + other = {OrderItem("Charlie", uuid=uuid4())} self.assertNotEqual(EntitySet(other), observed) self.assertNotEqual(other, observed) self.assertNotEqual({str(v.uuid): v for v in other}, observed) self.assertNotEqual(list(raw), observed) def test_len(self): - raw = {OrderItem("John"), OrderItem("Michael")} + raw = {OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())} entities = EntitySet(raw) self.assertEqual(2, len(entities)) def test_iter(self): - raw = {OrderItem("John"), OrderItem("Michael")} + raw = {OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())} entities = EntitySet(raw) self.assertEqual(raw, set(entities)) def test_contains(self): - raw = [OrderItem("John")] + raw = [OrderItem("John", uuid=uuid4())] entities = EntitySet(raw) self.assertIn(raw[0], entities) - self.assertNotIn(OrderItem("Charlie"), entities) + self.assertNotIn(OrderItem("Charlie", uuid=uuid4()), entities) self.assertNotIn(1234, entities) def test_add(self): - raw = OrderItem("John") + raw = OrderItem("John", uuid=uuid4()) entities = EntitySet() entities.add(raw) self.assertEqual({raw}, entities) - def test_get(self): + def test_add_raises(self): raw = OrderItem("John") + entities = EntitySet() + with self.assertRaises(ValueError): + entities.add(raw) + + def test_get(self): + raw = OrderItem("John", uuid=uuid4()) + entities = EntitySet() entities.add(raw) self.assertEqual(raw, entities.get(raw.uuid)) def test_remove(self): - raw = [OrderItem("John"), OrderItem("Michael")] + raw = [OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())] entities = EntitySet(raw) entities.remove(raw[1]) @@ -93,7 +103,7 @@ def test_remove(self): self.assertEqual({raw[0]}, entities) def test_diff(self): - raw = [OrderItem("John"), OrderItem("Michael")] + raw = [OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())] entities = EntitySet(raw) observed = entities.diff(EntitySet([raw[0]])) @@ -102,12 +112,12 @@ def test_diff(self): self.assertEqual(observed, expected) def test_data_cls(self): - raw = [OrderItem("John"), OrderItem("Michael")] + raw = [OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())] entities = EntitySet(raw) self.assertEqual(OrderItem, entities.data_cls) def test_from_avro(self): - values = {OrderItem("John"), OrderItem("Michael")} + values = {OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())} expected = EntitySet(values) schema = [ { @@ -130,35 +140,35 @@ def test_avro_schema(self): "items": OrderItem.avro_schema[0], }, ] - observed = EntitySet({OrderItem("John"), OrderItem("Michael")}).avro_schema + observed = EntitySet({OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())}).avro_schema self.assertEqual(expected, observed) def test_avro_data(self): - values = {OrderItem("John"), OrderItem("Michael")} + values = {OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())} expected = sorted([v.avro_data for v in values], key=lambda v: v["uuid"]) observed = EntitySet(values).avro_data self.assertIsInstance(observed, list) self.assertEqual(expected, sorted([v.avro_data for v in values], key=lambda v: v["uuid"])) def test_avro_bytes(self): - expected = EntitySet({OrderItem("John"), OrderItem("Michael")}) + expected = EntitySet({OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())}) self.assertEqual(expected, Model.from_avro_bytes(expected.avro_bytes)) def test_avro_bytes_not_hashable(self): - expected = EntitySet([_NotHashable({1}), _NotHashable({2})]) + expected = EntitySet([_NotHashable({1}, uuid=uuid4()), _NotHashable({2}, uuid=uuid4())]) self.assertEqual(expected, Model.from_avro_bytes(expected.avro_bytes)) class TestEntitySetDiff(unittest.TestCase): def setUp(self) -> None: - self.raw = [OrderItem("John"), OrderItem("Michael")] + self.raw = [OrderItem("John", uuid=uuid4()), OrderItem("Michael", uuid=uuid4())] self.old = EntitySet(self.raw) self.clone = [OrderItem(name=entity.name, uuid=entity.uuid) for entity in self.raw] def test_from_difference_create(self): entities = EntitySet(self.clone) - new = OrderItem("Charlie") + new = OrderItem("Charlie", uuid=uuid4()) entities.add(new) observed = IncrementalSetDiff.from_difference(entities, self.old, get_fn=attrgetter("uuid")) @@ -185,7 +195,7 @@ def test_from_difference_update(self): def test_from_difference_combined(self): entities = EntitySet(self.clone) - new = OrderItem("Charlie") + new = OrderItem("Charlie", uuid=uuid4()) entities.add(new) removed = self.clone[1] diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/__init__.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/__init__.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/__init__.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/__init__.py diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_base.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/test_base.py similarity index 89% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_base.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/test_base.py index 69dafbb8b..eb4adf90c 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_base.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/test_base.py @@ -23,7 +23,7 @@ def test_subclass(self): def test_default(self): entity = OrderItem("foo") self.assertIsInstance(entity, DeclarativeModel) - self.assertIsNot(entity.uuid, NULL_UUID) + self.assertEqual(entity.uuid, NULL_UUID) self.assertIsInstance(entity.uuid, UUID) self.assertEqual("foo", entity.name) @@ -31,7 +31,7 @@ def test_uuid(self): uuid = uuid4() entity = OrderItem("foo", uuid=uuid) self.assertIsInstance(entity, DeclarativeModel) - self.assertIsNot(entity.uuid, NULL_UUID) + self.assertNotEqual(entity.uuid, NULL_UUID) self.assertEqual(uuid, entity.uuid) self.assertEqual("foo", entity.name) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_differences.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/test_differences.py similarity index 97% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_differences.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/test_differences.py index b365664d2..33295d927 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_differences.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/test_differences.py @@ -18,7 +18,7 @@ ) -class TestRootEntityDifferences(AggregateTestCase): +class TestEntityDifferences(AggregateTestCase): async def asyncSetUp(self) -> None: self.uuid = uuid4() self.uuid_another = uuid4() diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_integration.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_integration.py index c47506f6f..a0c805b92 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_integration.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_integration.py @@ -1,4 +1,7 @@ import unittest +from uuid import ( + uuid4, +) from minos.aggregate import ( AlreadyDeletedException, @@ -55,7 +58,7 @@ async def test_create_update_delete(self): async def test_entity_set_value_object_set(self): order, _ = await self.repository.create(Order, products=EntitySet(), reviews=ValueObjectSet()) - item = OrderItem("foo") + item = OrderItem("foo", uuid=uuid4()) order.products.add(item) await self.repository.save(order) diff --git a/packages/core/minos-microservice-aggregate/tests/utils.py b/packages/core/minos-microservice-aggregate/tests/utils.py index 377441f4f..b6dde9aa7 100644 --- a/packages/core/minos-microservice-aggregate/tests/utils.py +++ b/packages/core/minos-microservice-aggregate/tests/utils.py @@ -23,7 +23,6 @@ InMemoryDeltaRepository, InMemorySnapshotRepository, Ref, - RootEntity, ValueObject, ValueObjectSet, testing, @@ -127,7 +126,7 @@ async def _destroy_instance(self, instance) -> None: """For testing purposes.""" -class Owner(RootEntity): +class Owner(Entity): """For testing purposes""" name: str @@ -135,7 +134,7 @@ class Owner(RootEntity): age: Optional[int] -class Car(RootEntity): +class Car(Entity): """For testing purposes""" doors: int @@ -143,7 +142,7 @@ class Car(RootEntity): owner: Optional[Ref[Owner]] -class Order(RootEntity): +class Order(Entity): """For testing purposes""" products: EntitySet[OrderItem] diff --git a/packages/core/minos-microservice-cqrs/tests/utils.py b/packages/core/minos-microservice-cqrs/tests/utils.py index a70c6b4cf..99940d2bc 100644 --- a/packages/core/minos-microservice-cqrs/tests/utils.py +++ b/packages/core/minos-microservice-cqrs/tests/utils.py @@ -9,7 +9,7 @@ from minos.aggregate import ( ExternalEntity, Ref, - RootEntity, + Entity, ) from minos.cqrs import ( CommandService, @@ -45,7 +45,7 @@ async def create_foo(self, request: Request) -> Response: """For testing purpose""" -class Foo(RootEntity): +class Foo(Entity): """For testing purposes""" bar: Ref[Bar] From b4263a73ad19ca2687d4db9d3e161a0552251e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Tue, 3 May 2022 16:17:28 +0200 Subject: [PATCH 54/75] ISSUE #175 * Remove `RootEntity`. --- README.md | 47 +++++++++---------- .../minos/aggregate/__init__.py | 1 - .../minos/aggregate/entities/__init__.py | 1 - .../minos/aggregate/entities/models.py | 4 -- .../minos/aggregate/snapshots/entries.py | 2 +- .../snapshots/repositories/database/impl.py | 2 +- .../snapshots/repositories/memory.py | 2 +- .../snapshots/repositories/testcases.py | 14 +++--- .../test_snapshots/test_entries.py | 13 ++--- .../test_repositories/test_abc.py | 2 +- .../test_repositories/test_database.py | 40 ++++++++-------- .../minos-microservice-cqrs/tests/utils.py | 2 +- 12 files changed, 62 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 11d551960..c40838c6f 100644 --- a/README.md +++ b/README.md @@ -221,13 +221,13 @@ Create a `foo/main.py` file and add the following content: # foo/main.py from pathlib import Path -from minos.aggregate import Aggregate, RootEntity +from minos.aggregate import Aggregate, Entity from minos.common import EntrypointLauncher from minos.cqrs import CommandService, QueryService -class Foo(RootEntity): - """Foo RootEntity class.""" +class Foo(Entity): + """Foo Entity class.""" class FooAggregate(Aggregate[Foo]): @@ -259,13 +259,12 @@ The way to model data in `minos` is highly inspired by the [Event Sourcing](htt * `minos.aggregate.Entity`: A model that has an identifier that gives it a unique identity, in the sense that some values from which it is composed could change, but its identity will continue being the same. * `minos.aggregate.ExternalEntity`: A model that belongs to another microservice (or aggregate boundary) but needs to be used for some reason inside this microservice (or aggregate boundary). -* `minos.aggregate.RootEntity`: Is an `Entity` superset that provides global identity across the project compared to standard `Entity` models, that has only local identity (the `RootEntity` can be accessed from another microservices as `ExternalEntity` models, but standard `Entity` models can only be accessed within the microservice that define them). The `RootEntity` is also the one that interacts with the persistence layer (the `EventRepository` and `SnapshotRepository` instances). -* `minos.aggregate.Ref`: A wrapper class that provides the functionality to store a reference of other `RootEntity` or `ExternalEntity` instances. +* `minos.aggregate.Ref`: A wrapper class that provides the functionality to store a reference of other `Entity` or `ExternalEntity` instances. * `minos.aggregate.EntitySet`: A container of `Entity` instances that takes advantage of the incremental behaviour of the `EventRepository`. * `minos.aggregate.ValueObject`: A model that is only identified by the values that compose it, so that if some of them changes, then the model becomes completely different (for that reason, these models are immutable). * `minos.aggregate.ValueObjectSet`: A container of `ValueObject` instances that takes advantage of the incremental behaviour of the `EventRepository. -* `minos.aggregate.Aggregate`: A collection of `Entity` and/or `ValueObject` models that are related to each other through a `RootEntity`. -* `minos.aggregate.Event`: A model that contains the difference between the a `RootEntity` instance and its previous version (if any). +* `minos.aggregate.Aggregate`: A collection of `Entity` and/or `ValueObject` models that are related to each other through a special `Entity` known as the Root Entity of the Aggregate. +* `minos.aggregate.Event`: A model that contains the difference between the a `Entity` instance and its previous version (if any). Here is an example of the creation the `Foo` aggregate. In this case, it has two attributes, a `bar` being a `str`, and a `foobar` being an optional reference to the external `FooBar` aggregate, which it is assumed that it has a `something` attribute. @@ -275,11 +274,11 @@ Here is an example of the creation the `Foo` aggregate. In this case, it has two from __future__ import annotations from typing import Optional from uuid import UUID -from minos.aggregate import Aggregate, RootEntity, ExternalEntity, Ref +from minos.aggregate import Aggregate, Entity, ExternalEntity, Ref -class Foo(RootEntity): - """Foo RootEntity class.""" +class Foo(Entity): + """Foo Entity class.""" bar: str foobar: Optional[Ref[FooBar]] @@ -330,13 +329,13 @@ from pathlib import Path from typing import Optional from uuid import UUID -from minos.aggregate import Aggregate, RootEntity, ExternalEntity, Ref +from minos.aggregate import Aggregate, Entity, ExternalEntity, Ref from minos.common import EntrypointLauncher from minos.cqrs import CommandService, QueryService -class Foo(RootEntity): - """Foo RootEntity class.""" +class Foo(Entity): + """Foo Entity class.""" bar: str foobar: Optional[Ref[FooBar]] @@ -432,14 +431,14 @@ from pathlib import Path from typing import Optional from uuid import UUID -from minos.aggregate import Aggregate, RootEntity, ExternalEntity, Ref +from minos.aggregate import Aggregate, Entity, ExternalEntity, Ref from minos.common import EntrypointLauncher from minos.cqrs import CommandService, QueryService from minos.networks import Request, Response, enroute -class Foo(RootEntity): - """Foo RootEntity class.""" +class Foo(Entity): + """Foo Entity class.""" bar: str foobar: Optional[Ref[FooBar]] @@ -590,14 +589,14 @@ from pathlib import Path from typing import Optional from uuid import UUID -from minos.aggregate import Aggregate, RootEntity, ExternalEntity, Ref +from minos.aggregate import Aggregate, Entity, ExternalEntity, Ref from minos.common import EntrypointLauncher from minos.cqrs import CommandService, QueryService from minos.networks import Request, Response, enroute -class Foo(RootEntity): - """Foo RootEntity class.""" +class Foo(Entity): + """Foo Entity class.""" bar: str foobar: Optional[Ref[FooBar]] @@ -793,15 +792,15 @@ from pathlib import Path from typing import Optional from uuid import UUID -from minos.aggregate import Aggregate, RootEntity, ExternalEntity, Ref +from minos.aggregate import Aggregate, Entity, ExternalEntity, Ref from minos.common import ModelType, EntrypointLauncher from minos.cqrs import CommandService, QueryService from minos.networks import Request, Response, enroute from minos.saga import Saga, SagaContext, SagaRequest, SagaResponse -class Foo(RootEntity): - """Foo RootEntity class.""" +class Foo(Entity): + """Foo Entity class.""" bar: str foobar: Optional[Ref[FooBar]] @@ -1040,13 +1039,13 @@ from __future__ import annotations from pathlib import Path from uuid import UUID -from minos.aggregate import Aggregate, RootEntity +from minos.aggregate import Aggregate, Entity from minos.common import EntrypointLauncher from minos.cqrs import CommandService from minos.networks import Request, Response, enroute -class FooBar(RootEntity): +class FooBar(Entity): """FooBar Root Entity clas.""" something: str diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py index f31ab8dda..e5975d1bb 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py @@ -35,7 +35,6 @@ RefExtractor, RefInjector, RefResolver, - RootEntity, ) from .exceptions import ( AggregateException, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py index f565aabe7..6f55a70f4 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py @@ -4,7 +4,6 @@ from .models import ( Entity, ExternalEntity, - RootEntity, ) from .refs import ( Ref, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py index ea965480b..d63458817 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py @@ -111,7 +111,3 @@ class ExternalEntity(DeclarativeModel): T = TypeVar("T", bound=Entity) - - -class RootEntity(Entity): - """Base Root Entity class.""" diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py index 87633f903..2a116c0e2 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/entries.py @@ -75,7 +75,7 @@ def __init__( self.transaction_uuid = transaction_uuid @classmethod - def from_root_entity(cls, instance: Entity, **kwargs) -> SnapshotEntry: + def from_entity(cls, instance: Entity, **kwargs) -> SnapshotEntry: """Build a new instance from a ``Entity``. :param instance: The ``Entity`` instance. diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py index 39094c76c..ccd35dceb 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/database/impl.py @@ -175,7 +175,7 @@ async def _submit_delete(self, delta_entry: DeltaEntry) -> SnapshotEntry: async def _submit_update_or_create(self, delta_entry: DeltaEntry, **kwargs) -> SnapshotEntry: instance = await self._build_instance(delta_entry, **kwargs) - snapshot_entry = SnapshotEntry.from_root_entity(instance, transaction_uuid=delta_entry.transaction_uuid) + snapshot_entry = SnapshotEntry.from_entity(instance, transaction_uuid=delta_entry.transaction_uuid) snapshot_entry = await self._submit_entry(snapshot_entry) return snapshot_entry diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py index 9a08dd5c4..21b7efff0 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/memory.py @@ -178,7 +178,7 @@ def _build_instance(entries: list[DeltaEntry], **kwargs) -> SnapshotEntry: for entry in entries[1:]: instance.apply_diff(entry.delta) - snapshot = SnapshotEntry.from_root_entity(instance) + snapshot = SnapshotEntry.from_entity(instance) return snapshot diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py index f447cffc2..3c83229a1 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py @@ -155,7 +155,7 @@ async def test_dispatch(self): # noinspection PyTypeChecker expected = [ SnapshotEntry(self.uuid_1, self.Car.classname, 4), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( self.Car( 3, "blue", @@ -165,7 +165,7 @@ async def test_dispatch(self): updated_at=observed[1].updated_at, ) ), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( self.Car( 3, "blue", @@ -194,7 +194,7 @@ async def test_dispatch_first_transaction(self): # noinspection PyTypeChecker expected = [ SnapshotEntry(self.uuid_1, self.Car.classname, 4), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( self.Car( 3, "blue", @@ -204,7 +204,7 @@ async def test_dispatch_first_transaction(self): updated_at=observed[1].updated_at, ) ), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( self.Car( 3, "blue", @@ -234,7 +234,7 @@ async def test_dispatch_second_transaction(self): expected = [ SnapshotEntry(self.uuid_1, self.Car.classname, 4), SnapshotEntry(self.uuid_2, self.Car.classname, 4), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( self.Car( 3, "blue", @@ -263,7 +263,7 @@ async def test_dispatch_third_transaction(self): # noinspection PyTypeChecker expected = [ SnapshotEntry(self.uuid_1, self.Car.classname, 4), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( self.Car( 3, "blue", @@ -273,7 +273,7 @@ async def test_dispatch_third_transaction(self): updated_at=observed[1].updated_at, ) ), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( self.Car( 3, "blue", diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py index b4f5f2bb3..054c62316 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_entries.py @@ -17,6 +17,7 @@ SnapshotEntry, ) from minos.common import ( + AvroSchemaEncoder, MinosJsonBinaryProtocol, ) from tests.utils import ( @@ -77,10 +78,10 @@ def test_constructor_extended(self): self.assertEqual(datetime(2020, 1, 10, 4, 23), entry.created_at) self.assertEqual(datetime(2020, 1, 10, 4, 25), entry.updated_at) - def test_from_root_entity(self): + def test_from_entity(self): car = Car(3, "blue", uuid=self.uuid, version=1) - with patch("minos.common.AvroSchemaEncoder.generate_random_str", return_value="hello"): - entry = SnapshotEntry.from_root_entity(car) + with patch.object(AvroSchemaEncoder, "generate_random_str", return_value="hello"): + entry = SnapshotEntry.from_entity(car) self.assertEqual(car.uuid, entry.uuid) self.assertEqual(car.classname, entry.name) self.assertEqual(car.version, entry.version) @@ -92,7 +93,7 @@ def test_from_root_entity(self): def test_from_delta_entry(self): car = Car(3, "blue", uuid=self.uuid, version=1) delta_entry = DeltaEntry.from_delta(Delta.from_entity(car), version=1) - with patch("minos.common.AvroSchemaEncoder.generate_random_str", return_value="hello"): + with patch.object(AvroSchemaEncoder, "generate_random_str", return_value="hello"): snapshot_entry = SnapshotEntry.from_delta_entry(delta_entry) self.assertEqual(delta_entry.uuid, snapshot_entry.uuid) self.assertEqual(delta_entry.name, snapshot_entry.name) @@ -108,12 +109,12 @@ def test_equals(self): def test_type_(self): car = Car(3, "blue", uuid=self.uuid, version=1) - entry = SnapshotEntry.from_root_entity(car) + entry = SnapshotEntry.from_entity(car) self.assertEqual(Car, entry.type_) def test_build(self): car = Car(3, "blue", uuid=self.uuid, version=1) - entry = SnapshotEntry.from_root_entity(car) + entry = SnapshotEntry.from_entity(car) self.assertEqual(car, entry.build()) def test_build_raises(self): diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py index 0ea408447..693c2bf56 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py @@ -52,7 +52,7 @@ def setUp(self) -> None: super().setUp() self.snapshot_repository = _SnapshotRepository() - self.entries = [SnapshotEntry.from_root_entity(Car(3, "red"))] * 5 + self.entries = [SnapshotEntry.from_entity(Car(3, "red"))] * 5 self.synchronize_mock = AsyncMock() self.find_mock = MagicMock(return_value=FakeAsyncIterator(self.entries)) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py index 21d9be392..1b660436c 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py @@ -79,7 +79,7 @@ async def synchronize(self): FakeAsyncIterator( [ tuple( - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_1, version=1) ) .as_raw() @@ -106,7 +106,7 @@ async def test_dispatch(self): created_at=current_datetime(), updated_at=current_datetime(), ), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( SnapshotRepositoryTestCase.Car( 3, "blue", @@ -116,7 +116,7 @@ async def test_dispatch(self): updated_at=current_datetime(), ) ), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( SnapshotRepositoryTestCase.Car( 3, "blue", @@ -144,7 +144,7 @@ async def test_dispatch_first_transaction(self): created_at=current_datetime(), updated_at=current_datetime(), ), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( SnapshotRepositoryTestCase.Car( 3, "blue", @@ -154,7 +154,7 @@ async def test_dispatch_first_transaction(self): updated_at=current_datetime(), ) ), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( SnapshotRepositoryTestCase.Car( 3, "blue", @@ -189,7 +189,7 @@ async def test_dispatch_second_transaction(self): created_at=current_datetime(), updated_at=current_datetime(), ), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( SnapshotRepositoryTestCase.Car( 3, "blue", @@ -217,7 +217,7 @@ async def test_dispatch_third_transaction(self): created_at=current_datetime(), updated_at=current_datetime(), ), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( SnapshotRepositoryTestCase.Car( 3, "blue", @@ -227,7 +227,7 @@ async def test_dispatch_third_transaction(self): updated_at=current_datetime(), ) ), - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( SnapshotRepositoryTestCase.Car( 3, "blue", @@ -276,7 +276,7 @@ async def test_dispatch_ignore_previous_version(self): FakeAsyncIterator( [ tuple( - SnapshotEntry.from_root_entity( + SnapshotEntry.from_entity( SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_1, version=5) ) .as_raw() @@ -325,7 +325,7 @@ async def test_find_by_uuid(self): DatabaseClient, "fetch_all", return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_root_entity(entity).as_raw().values()) for entity in entities] + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] ), ): await super().test_find_by_uuid() @@ -340,7 +340,7 @@ async def test_find_with_transaction(self): DatabaseClient, "fetch_all", return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_root_entity(entity).as_raw().values()) for entity in entities] + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] ), ): await super().test_find_with_transaction() @@ -352,7 +352,7 @@ async def test_find_with_transaction_delete(self): DatabaseClient, "fetch_all", return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_root_entity(entity).as_raw().values()) for entity in entities] + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] ), ): await super().test_find_with_transaction_delete() @@ -367,7 +367,7 @@ async def test_find_with_transaction_reverted(self): DatabaseClient, "fetch_all", return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_root_entity(entity).as_raw().values()) for entity in entities] + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] ), ): await super().test_find_with_transaction_reverted() @@ -382,7 +382,7 @@ async def test_find_streaming_true(self): DatabaseClient, "fetch_all", return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_root_entity(entity).as_raw().values()) for entity in entities] + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] ), ): await super().test_find_streaming_true() @@ -397,7 +397,7 @@ async def test_find_with_duplicates(self): DatabaseClient, "fetch_all", return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_root_entity(entity).as_raw().values()) for entity in entities] + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] ), ): await super().test_find_with_duplicates() @@ -409,7 +409,7 @@ async def test_find_empty(self): DatabaseClient, "fetch_all", return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_root_entity(entity).as_raw().values()) for entity in entities] + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] ), ): await super().test_find_empty() @@ -423,7 +423,7 @@ async def test_get(self): DatabaseClient, "fetch_all", return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_root_entity(entity).as_raw().values()) for entity in entities] + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] ), ): await super().test_get() @@ -435,7 +435,7 @@ async def test_get_with_transaction(self): DatabaseClient, "fetch_all", return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_root_entity(entity).as_raw().values()) for entity in entities] + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] ), ): await super().test_get_with_transaction() @@ -481,7 +481,7 @@ async def test_find(self): DatabaseClient, "fetch_all", return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_root_entity(entity).as_raw().values()) for entity in entities] + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] ), ): await super().test_find() @@ -496,7 +496,7 @@ async def test_find_all(self): DatabaseClient, "fetch_all", return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_root_entity(entity).as_raw().values()) for entity in entities] + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] ), ): await super().test_find_all() diff --git a/packages/core/minos-microservice-cqrs/tests/utils.py b/packages/core/minos-microservice-cqrs/tests/utils.py index 99940d2bc..46c50a43d 100644 --- a/packages/core/minos-microservice-cqrs/tests/utils.py +++ b/packages/core/minos-microservice-cqrs/tests/utils.py @@ -7,9 +7,9 @@ ) from minos.aggregate import ( + Entity, ExternalEntity, Ref, - Entity, ) from minos.cqrs import ( CommandService, From 8422307d9d2904a801c346961f737e0ecd994f2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 4 May 2022 10:29:26 +0200 Subject: [PATCH 55/75] ISSUE #175 * Fix minor bug related with `Injectable` decorator and type hinting. --- .../minos/common/injections/decorators.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/core/minos-microservice-common/minos/common/injections/decorators.py b/packages/core/minos-microservice-common/minos/common/injections/decorators.py index b052e968f..b2dc1eb14 100644 --- a/packages/core/minos-microservice-common/minos/common/injections/decorators.py +++ b/packages/core/minos-microservice-common/minos/common/injections/decorators.py @@ -47,8 +47,6 @@ InputType = TypeVar("InputType", bound=type) -OutputType = Union[InputType, Type[InjectableMixin]] - class Injectable: """Injectable decorator.""" @@ -66,13 +64,13 @@ def name(self) -> str: """ return self._name - def __call__(self, input_type: InputType) -> OutputType: + def __call__(self, input_type: InputType): bases = (input_type, InjectableMixin) if (generic := self._build_generic(input_type)) is not None: bases = (*bases, generic) # noinspection PyTypeChecker - output_type: OutputType = types.new_class(input_type.__name__, bases, {}) + output_type = types.new_class(input_type.__name__, bases, {}) output_type.__module__ = input_type.__module__ # noinspection PyProtectedMember From d1fd342a438b9d704143821e25a1ccc0b9c355e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 4 May 2022 10:29:41 +0200 Subject: [PATCH 56/75] ISSUE #175 * Improve performance related with type hints. --- .../minos/common/model/declarative.py | 37 ++++++++++++------- .../minos/common/model/types/model_types.py | 8 +++- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/packages/core/minos-microservice-common/minos/common/model/declarative.py b/packages/core/minos-microservice-common/minos/common/model/declarative.py index 5cdff5be9..851332e9d 100644 --- a/packages/core/minos-microservice-common/minos/common/model/declarative.py +++ b/packages/core/minos-microservice-common/minos/common/model/declarative.py @@ -3,6 +3,9 @@ ) import logging +from collections import ( + ChainMap, +) from functools import ( lru_cache, ) @@ -56,9 +59,8 @@ def from_model_type(cls: type[T], model_type: ModelType, *args, **kwargs) -> T: return cls(*args, **kwargs) def _build_fields(self, *args, additional_type_hints: Optional[dict[str, type]] = None, **kwargs) -> None: - for (name, type_val), value in zip_longest( - self._type_hints(additional_type_hints), args, fillvalue=MissingSentinel - ): + iterable = zip_longest(self._type_hints(additional_type_hints), args, fillvalue=MissingSentinel) + for (name, type_val), value in iterable: if name in kwargs and value is not MissingSentinel: raise TypeError(f"got multiple values for argument {repr(name)}") @@ -72,28 +74,35 @@ def _build_fields(self, *args, additional_type_hints: Optional[dict[str, type]] # noinspection PyMethodParameters @self_or_classmethod def _type_hints(self_or_cls, additional_type_hints: Optional[dict[str, type]] = None) -> Iterator[tuple[str, Any]]: - type_hints = dict() if isinstance(self_or_cls, type): cls = self_or_cls else: cls = type(self_or_cls) - for b in cls.__mro__[::-1]: - list_fields = _get_class_type_hints(b) - type_hints |= list_fields - logger.debug(f"The obtained type hints are: {type_hints!r}") + base = _get_class_type_hints(cls) + + additional = dict() if additional_type_hints: for name, hint in additional_type_hints.items(): - if name not in type_hints or TypeHintComparator(hint, type_hints[name]).match(): - type_hints[name] = hint + if name not in base or TypeHintComparator(hint, base[name]).match(): + additional[name] = hint + + real = dict(super()._type_hints()) + + full = ChainMap(real, additional, base) - type_hints |= super()._type_hints() - yield from type_hints.items() + yield from full.items() @lru_cache() -def _get_class_type_hints(b: type) -> dict[str, type]: - return {k: v for k, v in get_type_hints(b).items() if not k.startswith("_")} +def _get_class_type_hints(cls: type) -> dict[str, type]: + type_hints = dict() + for b in cls.__mro__[::-1]: + list_fields = {k: v for k, v in get_type_hints(b).items() if not k.startswith("_")} + type_hints |= list_fields + + logger.debug(f"The obtained type hints for {cls!r} are: {type_hints!r}") + return type_hints T = TypeVar("T", bound=DeclarativeModel) diff --git a/packages/core/minos-microservice-common/minos/common/model/types/model_types.py b/packages/core/minos-microservice-common/minos/common/model/types/model_types.py index e13812a83..0484f717a 100644 --- a/packages/core/minos-microservice-common/minos/common/model/types/model_types.py +++ b/packages/core/minos-microservice-common/minos/common/model/types/model_types.py @@ -229,11 +229,15 @@ def _equal_with_bucket_model(self, other: Any) -> bool: ) def __hash__(cls) -> int: - return hash(tuple(cls)) + if not hasattr(cls, "_hash"): + cls._hash = hash(tuple(cls)) + return cls._hash def __iter__(cls) -> Iterable: # noinspection PyRedundantParentheses - yield from (cls.name, cls.namespace, tuple(cls.type_hints.items())) + yield cls.name + yield cls.namespace + yield frozenset(cls.type_hints.items()) def __repr__(cls): return f"{type(cls).__name__}(name={cls.name!r}, namespace={cls.namespace!r}, type_hints={cls.type_hints!r})" From 448fcaec7ce98e98c49ca291a7237cb6989d7956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 4 May 2022 10:31:23 +0200 Subject: [PATCH 57/75] ISSUE #175 * Fix lint. --- .../minos/common/injections/decorators.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/minos-microservice-common/minos/common/injections/decorators.py b/packages/core/minos-microservice-common/minos/common/injections/decorators.py index b2dc1eb14..26fdd30fc 100644 --- a/packages/core/minos-microservice-common/minos/common/injections/decorators.py +++ b/packages/core/minos-microservice-common/minos/common/injections/decorators.py @@ -19,7 +19,6 @@ from typing import ( Any, Generic, - Type, TypeVar, Union, get_args, From 4e90b7789ee6c494540304e4042d5c37556be9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 4 May 2022 12:26:58 +0200 Subject: [PATCH 58/75] ISSUE #175 * Improve `ModelType` comparisons. * Minos improvements. --- .../model/serializers/avro/data/decoder.py | 6 +- .../minos/common/model/types/comparators.py | 4 +- .../minos/common/model/types/model_types.py | 71 ++++++++----------- 3 files changed, 33 insertions(+), 48 deletions(-) diff --git a/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py b/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py index 5134f4613..d4b8c75b2 100644 --- a/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py +++ b/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py @@ -45,6 +45,7 @@ NoneType, TypeHintBuilder, is_model_subclass, + is_model_type, is_type_subclass, unpack_typevar, ) @@ -247,9 +248,8 @@ def _build_model(self, type_: Type[Model], data: Any, **kwargs) -> Any: return self._build_model_type(ModelType.from_model(type_), data, **kwargs) def _build_model_type(self, type_: ModelType, data: Any, **kwargs) -> Any: - if hasattr(data, "model_type"): - if ModelType.from_model(data) >= type_: - return data + if is_model_type(data) and ModelType.from_model(data) >= type_: + return data if (ans := type_.model_cls.decode_data(self, data, type_, **kwargs)) is not MissingSentinel: return ans diff --git a/packages/core/minos-microservice-common/minos/common/model/types/comparators.py b/packages/core/minos-microservice-common/minos/common/model/types/comparators.py index 81582fc6e..6d5922a63 100644 --- a/packages/core/minos-microservice-common/minos/common/model/types/comparators.py +++ b/packages/core/minos-microservice-common/minos/common/model/types/comparators.py @@ -38,13 +38,13 @@ def is_type_subclass(type_: type) -> bool: return issubclass(type(type_), type(type)) -def is_model_type(value_: type): +def is_model_type(value: Any): """Check if the given type is a model instance.""" from ..abc import ( Model, ) - return isinstance(value_, Model) + return isinstance(value, Model) logger = logging.getLogger(__name__) diff --git a/packages/core/minos-microservice-common/minos/common/model/types/model_types.py b/packages/core/minos-microservice-common/minos/common/model/types/model_types.py index 0484f717a..184a67340 100644 --- a/packages/core/minos-microservice-common/minos/common/model/types/model_types.py +++ b/packages/core/minos-microservice-common/minos/common/model/types/model_types.py @@ -37,6 +37,7 @@ class ModelType(type): name: str namespace: str type_hints: dict[str, Type] + _computed_hash: Optional[int] @classmethod def build( @@ -69,7 +70,7 @@ def build( @classmethod @lru_cache() def _build(mcs, name_: str, type_hints_: tuple[tuple[str, type], ...], namespace_: Optional[str]): - return mcs(name_, tuple(), {"type_hints": dict(type_hints_), "namespace": namespace_}) + return mcs(name_, tuple(), {"type_hints": dict(type_hints_), "namespace": namespace_, "_computed_hash": None}) @classmethod def from_typed_dict(mcs, typed_dict) -> ModelType: @@ -135,17 +136,7 @@ def classname(cls) -> str: return f"{cls.namespace}.{cls.name}" def __le__(cls, other: Any) -> bool: - from .comparators import ( - TypeHintComparator, - ) - - return type(cls).__eq__(cls, other) or ( - type(cls) == type(other) - and cls.name == other.name - and cls.namespace == other.namespace - and set(cls.type_hints.keys()) <= set(other.type_hints.keys()) - and all(TypeHintComparator(v, other.type_hints[k]).match() for k, v in cls.type_hints.items()) - ) + return (cls == other) or (cls < other) def __lt__(cls, other: Any) -> bool: from .comparators import ( @@ -153,25 +144,13 @@ def __lt__(cls, other: Any) -> bool: ) return ( - type(cls) == type(other) - and cls.name == other.name - and cls.namespace == other.namespace - and set(cls.type_hints.keys()) < set(other.type_hints.keys()) + cls._equal_without_types(other) + and cls.type_hints.keys() < other.type_hints.keys() and all(TypeHintComparator(v, other.type_hints[k]).match() for k, v in cls.type_hints.items()) ) def __ge__(cls, other: Any) -> bool: - from .comparators import ( - TypeHintComparator, - ) - - return type(cls).__eq__(cls, other) or ( - type(cls) == type(other) - and cls.name == other.name - and cls.namespace == other.namespace - and set(cls.type_hints.keys()) >= set(other.type_hints.keys()) - and all(TypeHintComparator(v, cls.type_hints[k]).match() for k, v in other.type_hints.items()) - ) + return (cls == other) or (cls > other) def __gt__(cls, other: Any) -> bool: from .comparators import ( @@ -179,10 +158,8 @@ def __gt__(cls, other: Any) -> bool: ) return ( - type(cls) == type(other) - and cls.name == other.name - and cls.namespace == other.namespace - and set(cls.type_hints.keys()) > set(other.type_hints.keys()) + cls._equal_without_types(other) + and cls.type_hints.keys() > other.type_hints.keys() and all(TypeHintComparator(v, cls.type_hints[k]).match() for k, v in other.type_hints.items()) ) @@ -202,19 +179,27 @@ def _equal_with_model_type(cls, other: ModelType) -> bool: ) return ( - type(cls) == type(other) - and cls.name == other.name - and cls.namespace == other.namespace - and set(cls.type_hints.keys()) == set(other.type_hints.keys()) + cls._equal_without_types(other) + and cls.type_hints.keys() == other.type_hints.keys() and all(TypeHintComparator(v, other.type_hints[k]).match() for k, v in cls.type_hints.items()) ) + def _equal_without_types(cls, other: Any): + return isinstance(other, ModelType) and cls.name == other.name and cls.namespace == other.namespace + def _equal_with_model(cls, other: Any) -> bool: - return hasattr(other, "model_type") and cls == ModelType.from_model(other) + from .comparators import ( + is_model_subclass, + is_model_type, + ) + + return (is_model_type(other) or is_model_subclass(other)) and cls == ModelType.from_model(other) - def _equal_with_inherited_model(cls, other: ModelType) -> bool: + def _equal_with_inherited_model(cls, other: Any) -> bool: return ( - type(cls) == type(other) and cls.model_cls != other.model_cls and issubclass(cls.model_cls, other.model_cls) + isinstance(other, ModelType) + and cls.model_cls != other.model_cls + and issubclass(cls.model_cls, other.model_cls) ) def _equal_with_bucket_model(self, other: Any) -> bool: @@ -223,15 +208,15 @@ def _equal_with_bucket_model(self, other: Any) -> bool: ) return ( - hasattr(other, "model_cls") - and issubclass(self.model_cls, other.model_cls) + isinstance(other, ModelType) and issubclass(other.model_cls, BucketModel) + and issubclass(self.model_cls, other.model_cls) ) def __hash__(cls) -> int: - if not hasattr(cls, "_hash"): - cls._hash = hash(tuple(cls)) - return cls._hash + if cls._computed_hash is None: + cls._computed_hash = hash(tuple(cls)) + return cls._computed_hash def __iter__(cls) -> Iterable: # noinspection PyRedundantParentheses From 4ab6b9752a3bf2762bf35e8c9fa581d78937fb90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 4 May 2022 13:08:36 +0200 Subject: [PATCH 59/75] ISSUE #175 * Fix bug. --- .../minos/common/model/types/model_types.py | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/core/minos-microservice-common/minos/common/model/types/model_types.py b/packages/core/minos-microservice-common/minos/common/model/types/model_types.py index 184a67340..6fe456b47 100644 --- a/packages/core/minos-microservice-common/minos/common/model/types/model_types.py +++ b/packages/core/minos-microservice-common/minos/common/model/types/model_types.py @@ -136,7 +136,15 @@ def classname(cls) -> str: return f"{cls.namespace}.{cls.name}" def __le__(cls, other: Any) -> bool: - return (cls == other) or (cls < other) + from .comparators import ( + TypeHintComparator, + ) + + return (cls == other) or ( + cls._equal_without_types(other) + and cls.type_hints.keys() < other.type_hints.keys() + and all(TypeHintComparator(v, other.type_hints[k]).match() for k, v in cls.type_hints.items()) + ) def __lt__(cls, other: Any) -> bool: from .comparators import ( @@ -150,7 +158,15 @@ def __lt__(cls, other: Any) -> bool: ) def __ge__(cls, other: Any) -> bool: - return (cls == other) or (cls > other) + from .comparators import ( + TypeHintComparator, + ) + + return (cls == other) or ( + cls._equal_without_types(other) + and cls.type_hints.keys() >= other.type_hints.keys() + and all(TypeHintComparator(v, cls.type_hints[k]).match() for k, v in other.type_hints.items()) + ) def __gt__(cls, other: Any) -> bool: from .comparators import ( From 3039492d49833aacf071eea2f34fc04f7305277f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 4 May 2022 14:47:02 +0200 Subject: [PATCH 60/75] ISSUE #175 * Minor improvements on `AvroDataDecoder`. --- .../common/model/serializers/avro/data/decoder.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py b/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py index d4b8c75b2..2f1ca70af 100644 --- a/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py +++ b/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py @@ -101,10 +101,10 @@ def _build_union(self, type_: type, data: Any, **kwargs) -> Any: def _build_single(self, type_: type, data: Any, **kwargs) -> Any: if type_ is Any: - type_ = TypeHintBuilder(data).build() + return self._build_any(data, **kwargs) + if isinstance(type_, TypeVar): - unpacked_type = unpack_typevar(type_) - return self._build(unpacked_type, data, **kwargs) + return self._build_typevar(type_, data, **kwargs) if type_ is NoneType: return self._build_none(type_, data, **kwargs) @@ -155,6 +155,15 @@ def _build_single(self, type_: type, data: Any, **kwargs) -> Any: return self._build_collection(type_, data, **kwargs) + def _build_any(self, data: Any, **kwargs) -> Any: + type_ = TypeHintBuilder(data).build() + return self._build(type_, data, **kwargs) + + # noinspection SpellCheckingInspection + def _build_typevar(self, type_: TypeVar, data: Any, **kwargs) -> Any: + unpacked_type = unpack_typevar(type_) + return self._build(unpacked_type, data, **kwargs) + @staticmethod def _build_none(type_: type, data: Any, **kwargs) -> Any: if data is None or data is MissingSentinel: From c1d63d4986e92c8f65f5a3219c250445cc3c179e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 4 May 2022 15:09:23 +0200 Subject: [PATCH 61/75] ISSUE #175 * Add cache to `is_model_subclass`. --- .../minos/common/model/types/comparators.py | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/packages/core/minos-microservice-common/minos/common/model/types/comparators.py b/packages/core/minos-microservice-common/minos/common/model/types/comparators.py index 6d5922a63..9a6e08517 100644 --- a/packages/core/minos-microservice-common/minos/common/model/types/comparators.py +++ b/packages/core/minos-microservice-common/minos/common/model/types/comparators.py @@ -21,32 +21,6 @@ ModelType, ) - -def is_model_subclass(type_: type) -> bool: - """Check if the given type field is subclass of ``Model``.""" - from ..abc import ( - Model, - ) - - if not is_type_subclass(type_): - type_ = get_origin(type_) - return is_type_subclass(type_) and issubclass(type_, Model) - - -def is_type_subclass(type_: type) -> bool: - """Check if the given type field is subclass of ``type``.""" - return issubclass(type(type_), type(type)) - - -def is_model_type(value: Any): - """Check if the given type is a model instance.""" - from ..abc import ( - Model, - ) - - return isinstance(value, Model) - - logger = logging.getLogger(__name__) T = TypeVar("T", bound=type) @@ -114,3 +88,25 @@ def _compare_args(cls, first: T, second: K) -> bool: if len(first_args) != len(second_args): return False return all(cls._compare(fi, si) for fi, si in zip(first_args, second_args)) + + +def is_model_type(value: Any): + """Check if the given type is a model instance.""" + return is_model_subclass(type(value)) + + +@lru_cache() +def is_model_subclass(type_: type) -> bool: + """Check if the given type field is subclass of ``Model``.""" + from ..abc import ( + Model, + ) + + if not is_type_subclass(type_): + type_ = get_origin(type_) + return is_type_subclass(type_) and issubclass(type_, Model) + + +def is_type_subclass(type_: type) -> bool: + """Check if the given type field is subclass of ``type``.""" + return issubclass(type(type_), type(type)) From 584e3672bf8ef60d495f31b684212d14d8b03a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Wed, 4 May 2022 15:21:32 +0200 Subject: [PATCH 62/75] ISSUE #175 * Minor change. --- .../model/serializers/avro/data/decoder.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py b/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py index 2f1ca70af..79d61f730 100644 --- a/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py +++ b/packages/core/minos-microservice-common/minos/common/model/serializers/avro/data/decoder.py @@ -80,9 +80,9 @@ def build(self, data: Any, type_: Any = MissingSentinel, **kwargs) -> Any: def _build(self, type_: type, data: Any, **kwargs) -> Any: origin = get_origin(type_) - if origin is not Union: - return self._build_single(type_, data, **kwargs) - return self._build_union(type_, data, **kwargs) + if origin is Union: + return self._build_union(type_, data, **kwargs) + return self._build_single(type_, data, **kwargs) def _build_union(self, type_: type, data: Any, **kwargs) -> Any: alternatives = get_args(type_) @@ -103,9 +103,6 @@ def _build_single(self, type_: type, data: Any, **kwargs) -> Any: if type_ is Any: return self._build_any(data, **kwargs) - if isinstance(type_, TypeVar): - return self._build_typevar(type_, data, **kwargs) - if type_ is NoneType: return self._build_none(type_, data, **kwargs) @@ -115,6 +112,12 @@ def _build_single(self, type_: type, data: Any, **kwargs) -> Any: if data is MissingSentinel: raise DataDecoderRequiredValueException("Value is missing.") + if isinstance(type_, TypeVar): + return self._build_typevar(type_, data, **kwargs) + + if isinstance(type_, ModelType): + return self._build_model_type(type_, data, **kwargs) + if is_model_subclass(type_): # noinspection PyTypeChecker return self._build_model(type_, data, **kwargs) @@ -150,9 +153,6 @@ def _build_single(self, type_: type, data: Any, **kwargs) -> Any: if issubclass(type_, UUID): return self._build_uuid(data, **kwargs) - if isinstance(type_, ModelType): - return self._build_model_type(type_, data, **kwargs) - return self._build_collection(type_, data, **kwargs) def _build_any(self, data: Any, **kwargs) -> Any: From 724d1f29950f4e1529b0165266ef44cce5679b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 5 May 2022 09:19:51 +0200 Subject: [PATCH 63/75] ISSUE #450 * Add support for `str` generic types on `Ref`. --- .../minos/aggregate/entities/refs/models.py | 14 +++ .../test_entities/test_refs/test_models.py | 88 +++++++++++-------- 2 files changed, 65 insertions(+), 37 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/models.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/models.py index ca3b21b3c..b2b4a7835 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/models.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/models.py @@ -39,6 +39,20 @@ class Ref(DeclarativeModel, UUID, Generic[MT]): data: Union[MT, UUID] + @classmethod + def __class_getitem__(cls, params: Union[type, TypeVar, str]): + if not isinstance(params, tuple): + params = (params,) + + def _parse(param: Union[type, TypeVar, str]) -> Union[type, TypeVar]: + if isinstance(param, str): + param = ModelType.build(param, uuid=UUID, version=int) + return param + + params = tuple(_parse(param) for param in params) + + return super().__class_getitem__(params) + def __init__(self, data: Union[MT, UUID], *args, **kwargs): if not isinstance(data, UUID) and not hasattr(data, "uuid"): raise ValueError(f"data must be an {UUID!r} instance or have 'uuid' as one of its fields") diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_models.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_models.py index c82b06229..3a8db8f8c 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_models.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_models.py @@ -3,6 +3,7 @@ Any, Generic, Union, + get_args, ) from unittest.mock import ( patch, @@ -30,8 +31,8 @@ FakeMessage = ModelType.build("FakeMessage", {"content": Any}) -Bar = ModelType.build("Bar", {"uuid": UUID, "age": int}) -Foo = ModelType.build("Foo", {"another": Ref[Bar]}) +Bar = ModelType.build("Bar", {"uuid": UUID, "version": int, "text": str}) +Foo = ModelType.build("Foo", {"another": Ref["Bar"]}) class TestRef(AggregateTestCase): @@ -39,6 +40,18 @@ def test_subclass(self): # noinspection PyTypeHints self.assertTrue(issubclass(Ref, (DeclarativeModel, UUID, Generic))) + def test_generic_type(self): + # noinspection PyPep8Naming + User = ModelType.build("User", uuid=UUID, version=int) + typed = Ref[User] + args = get_args(typed) + self.assertEqual((User,), args) + + def test_generic_str(self): + typed = Ref["User"] + args = get_args(typed) + self.assertEqual((ModelType.build("User", uuid=UUID, version=int),), args) + def test_raises(self): with self.assertRaises(ValueError): # noinspection PyTypeChecker @@ -107,38 +120,38 @@ def test_uuid_setitem(self): self.assertEqual(uuid_2, value.data) def test_model(self): - another = Bar(uuid4(), 1) + another = Bar(uuid4(), 1, "foobar") value = Foo(another=another) self.assertEqual(another, value.another) def test_model_uuid(self): uuid = uuid4() - value = Ref(Bar(uuid, 1)) + value = Ref(Bar(uuid, 1, "foobar")) self.assertEqual(uuid, value.uuid) def test_model_getattr(self): - value = Ref(Bar(uuid4(), 1)) + value = Ref(Bar(uuid4(), 1, "foobar")) - self.assertEqual(1, value.age) + self.assertEqual("foobar", value.text) def test_model_getattr_raises(self): - value = Ref(Bar(uuid4(), 1)) + value = Ref(Bar(uuid4(), 1, "foobar")) with self.assertRaises(AttributeError): value.year def test_model_setattr(self): - value = Ref(Bar(uuid4(), 1)) + value = Ref(Bar(uuid4(), 1, "foobar")) - value.age = 2 + value.text = "hello" - self.assertEqual(2, value.data.age) + self.assertEqual("hello", value.data.text) def test_model_setattr_uuid(self): uuid_2 = uuid4() - value = Ref(Bar(uuid4(), 1)) + value = Ref(Bar(uuid4(), 1, "foobar")) value.uuid = uuid_2 @@ -146,32 +159,32 @@ def test_model_setattr_uuid(self): def test_model_setattr_raises(self): uuid_2 = uuid4() - value = Ref(Bar(uuid4(), 1)) + value = Ref(Bar(uuid4(), 1, "foobar")) with self.assertRaises(AttributeError): value.something = uuid_2 def test_model_getitem(self): - value = Ref(Bar(uuid4(), 1)) + value = Ref(Bar(uuid4(), 1, "foobar")) - self.assertEqual(1, value["age"]) + self.assertEqual("foobar", value["text"]) def test_model_getitem_raises(self): - value = Ref(Bar(uuid4(), 1)) + value = Ref(Bar(uuid4(), 1, "foobar")) with self.assertRaises(KeyError): value["year"] def test_model_setitem(self): - value = Ref(Bar(uuid4(), 1)) + value = Ref(Bar(uuid4(), 1, "foobar")) - value["age"] = 2 + value["text"] = "hello" - self.assertEqual(2, value.data.age) + self.assertEqual("hello", value.data.text) def test_model_setitem_uuid(self): uuid_2 = uuid4() - value = Ref(Bar(uuid4(), 1)) + value = Ref(Bar(uuid4(), 1, "foobar")) value["uuid"] = uuid_2 @@ -179,18 +192,18 @@ def test_model_setitem_uuid(self): def test_model_setitem_raises(self): uuid_2 = uuid4() - value = Ref(Bar(uuid4(), 1)) + value = Ref(Bar(uuid4(), 1, "foobar")) with self.assertRaises(KeyError): value["something"] = uuid_2 def test_fields(self): - value = Ref(Bar(uuid4(), 1)) + value = Ref(Bar(uuid4(), 1, "foobar")) self.assertEqual({"data": Field("data", Union[Bar, UUID], value)}, value.fields) def test_model_avro_data(self): - value = Bar(uuid4(), 1) + value = Bar(uuid4(), 1, "foobar") self.assertEqual(value.avro_data, Ref(value).avro_data) @@ -200,7 +213,7 @@ def test_uuid_avro_data(self): async def test_model_avro_data_submitting(self): uuid = uuid4() - value = Bar(uuid, 1) + value = Bar(uuid, 1, "foobar") IS_REPOSITORY_SERIALIZATION_CONTEXT_VAR.set(True) self.assertEqual(str(uuid), Ref(value).avro_data) @@ -211,14 +224,15 @@ async def test_uuid_avro_data_submitting(self): self.assertEqual(str(value), Ref(value).avro_data) def test_model_avro_schema(self): - another = Bar(uuid4(), 1) + another = Bar(uuid4(), 1, "foobar") expected = [ [ { "fields": [ {"name": "uuid", "type": {"logicalType": "uuid", "type": "string"}}, - {"name": "age", "type": "int"}, + {"name": "version", "type": "int"}, + {"name": "text", "type": "string"}, ], "name": "Bar", "namespace": "", @@ -240,7 +254,7 @@ def test_uuid_avro_schema(self): { "fields": [ {"name": "uuid", "type": {"logicalType": "uuid", "type": "string"}}, - {"name": "age", "type": "int"}, + {"name": "version", "type": "int"}, ], "logicalType": "minos.aggregate.entities.refs.models.Ref", "name": "Bar", @@ -253,7 +267,7 @@ def test_uuid_avro_schema(self): self.assertEqual(expected, ref.avro_schema) def test_model_from_avro(self): - another = Bar(uuid4(), 1) + another = Bar(uuid4(), 1, "foobar") expected = Foo(another).another # FIXME: This should not be needed to set the type hint properly schema = [ @@ -261,7 +275,7 @@ def test_model_from_avro(self): { "fields": [ {"name": "uuid", "type": {"logicalType": "uuid", "type": "string"}}, - {"name": "age", "type": "int"}, + {"name": "text", "type": "string"}, ], "logicalType": "minos.aggregate.entities.refs.models.Ref", "name": "Bar", @@ -282,7 +296,7 @@ def test_uuid_from_avro(self): { "fields": [ {"name": "uuid", "type": {"logicalType": "uuid", "type": "string"}}, - {"name": "age", "type": "int"}, + {"name": "text", "type": "int"}, ], "logicalType": "minos.aggregate.entities.refs.models.Ref", "name": "Bar", @@ -298,16 +312,16 @@ def test_uuid_from_avro(self): async def test_resolve(self): another = uuid4() - resolved_another = Bar(another, 1) + resolved_another = Bar(another, 1, "foobar") ref = Foo(another).another # FIXME: This should not be needed to set the type hint properly - self.assertEqual(ref.data, another) + self.assertEqual(another, ref.data) with patch.object(RefResolver, "resolve", return_value=resolved_another): await ref.resolve() - self.assertEqual(ref.data, Bar(another, 1)) + self.assertEqual(Bar(another, 1, "foobar"), ref.data) async def test_resolve_raises(self): another = uuid4() @@ -321,7 +335,7 @@ async def test_resolve_raises(self): async def test_resolve_already(self): uuid = uuid4() - ref = Ref(Bar(uuid, 1)) + ref = Ref(Bar(uuid, 1, "foobar")) await ref.resolve() @@ -330,10 +344,10 @@ async def test_resolve_already(self): async def test_resolved(self): self.assertFalse(Ref(uuid4()).resolved) - self.assertTrue(Ref(Bar(uuid4(), 4)).resolved) + self.assertTrue(Ref(Bar(uuid4(), 1, "foobar")).resolved) def test_avro_model(self): - another = Bar(uuid4(), 1) + another = Bar(uuid4(), 1, "foobar") ref = Foo(another).another # FIXME: This should not be needed to set the type hint properly self.assertEqual(ref, Ref.from_avro_bytes(ref.avro_bytes)) @@ -352,7 +366,7 @@ def test_repr_uuid(self): def test_repr_model(self): another_uuid = uuid4() - another = Bar(another_uuid, 1) + another = Bar(another_uuid, 1, "foobar") ref = Foo(another).another # FIXME: This should not be needed to set the type hint properly self.assertEqual(f"Ref({another!r})", repr(ref)) @@ -365,7 +379,7 @@ def test_str_uuid(self): def test_str_model(self): another_uuid = uuid4() - another = Bar(another_uuid, 1) + another = Bar(another_uuid, 1, "foobar") ref = Foo(another).another # FIXME: This should not be needed to set the type hint properly self.assertEqual(str(another_uuid), str(ref)) From eefb35bc0b8d995b0a6ad64ae72b7dc5693d64f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 5 May 2022 09:58:20 +0200 Subject: [PATCH 64/75] ISSUE #450 * Remove `ExternalEntity`. --- README.md | 53 ++++--------------- .../minos/aggregate/__init__.py | 1 - .../minos/aggregate/entities/__init__.py | 1 - .../minos/aggregate/entities/models.py | 7 --- .../test_entities/test_models/__init__.py | 1 + .../{test_entity => }/test_base.py | 0 .../{test_entity => }/test_differences.py | 0 .../test_models/test_entity/__init__.py | 1 - .../test_models/test_external.py | 23 -------- .../tests/utils.py | 8 --- .../tests/test_cqrs/test_handlers.py | 7 +-- .../minos-microservice-cqrs/tests/utils.py | 9 +--- 12 files changed, 17 insertions(+), 94 deletions(-) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/{test_entity => }/test_base.py (100%) rename packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/{test_entity => }/test_differences.py (100%) delete mode 100644 packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/__init__.py delete mode 100644 packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_external.py diff --git a/README.md b/README.md index c40838c6f..ac634bfe1 100644 --- a/README.md +++ b/README.md @@ -258,8 +258,7 @@ python foo/main.py The way to model data in `minos` is highly inspired by the [Event Sourcing](https://microservices.io/patterns/data/event-sourcing.html) ideas. For this reason, the classes to be used to model data are: * `minos.aggregate.Entity`: A model that has an identifier that gives it a unique identity, in the sense that some values from which it is composed could change, but its identity will continue being the same. -* `minos.aggregate.ExternalEntity`: A model that belongs to another microservice (or aggregate boundary) but needs to be used for some reason inside this microservice (or aggregate boundary). -* `minos.aggregate.Ref`: A wrapper class that provides the functionality to store a reference of other `Entity` or `ExternalEntity` instances. +* `minos.aggregate.Ref`: A wrapper class that provides the functionality to store a reference of other `Entity` instances. * `minos.aggregate.EntitySet`: A container of `Entity` instances that takes advantage of the incremental behaviour of the `EventRepository`. * `minos.aggregate.ValueObject`: A model that is only identified by the values that compose it, so that if some of them changes, then the model becomes completely different (for that reason, these models are immutable). * `minos.aggregate.ValueObjectSet`: A container of `ValueObject` instances that takes advantage of the incremental behaviour of the `EventRepository. @@ -274,20 +273,14 @@ Here is an example of the creation the `Foo` aggregate. In this case, it has two from __future__ import annotations from typing import Optional from uuid import UUID -from minos.aggregate import Aggregate, Entity, ExternalEntity, Ref +from minos.aggregate import Aggregate, Entity, Ref class Foo(Entity): """Foo Entity class.""" bar: str - foobar: Optional[Ref[FooBar]] - - -class FooBar(ExternalEntity): - """FooBar ExternalEntity clas.""" - - something: str + foobar: Optional[Ref["FooBar"]] class FooAggregate(Aggregate[Foo]): @@ -329,7 +322,7 @@ from pathlib import Path from typing import Optional from uuid import UUID -from minos.aggregate import Aggregate, Entity, ExternalEntity, Ref +from minos.aggregate import Aggregate, Entity, Ref from minos.common import EntrypointLauncher from minos.cqrs import CommandService, QueryService @@ -338,13 +331,7 @@ class Foo(Entity): """Foo Entity class.""" bar: str - foobar: Optional[Ref[FooBar]] - - -class FooBar(ExternalEntity): - """FooBar ExternalEntity clas.""" - - something: str + foobar: Optional[Ref["FooBar"]] class FooAggregate(Aggregate[Foo]): @@ -431,7 +418,7 @@ from pathlib import Path from typing import Optional from uuid import UUID -from minos.aggregate import Aggregate, Entity, ExternalEntity, Ref +from minos.aggregate import Aggregate, Entity, Ref from minos.common import EntrypointLauncher from minos.cqrs import CommandService, QueryService from minos.networks import Request, Response, enroute @@ -441,13 +428,7 @@ class Foo(Entity): """Foo Entity class.""" bar: str - foobar: Optional[Ref[FooBar]] - - -class FooBar(ExternalEntity): - """FooBar ExternalEntity clas.""" - - something: str + foobar: Optional[Ref["FooBar"]] class FooAggregate(Aggregate[Foo]): @@ -589,7 +570,7 @@ from pathlib import Path from typing import Optional from uuid import UUID -from minos.aggregate import Aggregate, Entity, ExternalEntity, Ref +from minos.aggregate import Aggregate, Entity, Ref from minos.common import EntrypointLauncher from minos.cqrs import CommandService, QueryService from minos.networks import Request, Response, enroute @@ -599,13 +580,7 @@ class Foo(Entity): """Foo Entity class.""" bar: str - foobar: Optional[Ref[FooBar]] - - -class FooBar(ExternalEntity): - """FooBar ExternalEntity clas.""" - - something: str + foobar: Optional[Ref["FooBar"]] class FooAggregate(Aggregate[Foo]): @@ -792,7 +767,7 @@ from pathlib import Path from typing import Optional from uuid import UUID -from minos.aggregate import Aggregate, Entity, ExternalEntity, Ref +from minos.aggregate import Aggregate, Entity, Ref from minos.common import ModelType, EntrypointLauncher from minos.cqrs import CommandService, QueryService from minos.networks import Request, Response, enroute @@ -803,13 +778,7 @@ class Foo(Entity): """Foo Entity class.""" bar: str - foobar: Optional[Ref[FooBar]] - - -class FooBar(ExternalEntity): - """FooBar ExternalEntity clas.""" - - something: str + foobar: Optional[Ref["FooBar"]] class FooAggregate(Aggregate[Foo]): diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py index e5975d1bb..6e9e03873 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py @@ -30,7 +30,6 @@ Entity, EntityRepository, EntitySet, - ExternalEntity, Ref, RefExtractor, RefInjector, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py index 6f55a70f4..3c40ac822 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/__init__.py @@ -3,7 +3,6 @@ ) from .models import ( Entity, - ExternalEntity, ) from .refs import ( Ref, diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py index d63458817..5fdd52103 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/models.py @@ -103,11 +103,4 @@ def from_diff(cls: Type[T], delta: Delta, *args, **kwargs) -> T: ) -class ExternalEntity(DeclarativeModel): - """External Entity class.""" - - uuid: UUID - version: int - - T = TypeVar("T", bound=Entity) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/__init__.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/__init__.py index e69de29bb..8b1378917 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/__init__.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/__init__.py @@ -0,0 +1 @@ + diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/test_base.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_base.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/test_base.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_base.py diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/test_differences.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_differences.py similarity index 100% rename from packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/test_differences.py rename to packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_differences.py diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/__init__.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/__init__.py deleted file mode 100644 index 8b1378917..000000000 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_entity/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_external.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_external.py deleted file mode 100644 index 74eb0180d..000000000 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_external.py +++ /dev/null @@ -1,23 +0,0 @@ -import unittest -from uuid import ( - uuid4, -) - -from tests.utils import ( - Product, -) - - -class TestExternalEntity(unittest.TestCase): - def test_values(self): - uuid = uuid4() - product = Product(uuid, 3, "apple", 3028) - - self.assertEqual(uuid, product.uuid) - self.assertEqual(3, product.version) - self.assertEqual("apple", product.title) - self.assertEqual(3028, product.quantity) - - -if __name__ == "__main__": - unittest.main() diff --git a/packages/core/minos-microservice-aggregate/tests/utils.py b/packages/core/minos-microservice-aggregate/tests/utils.py index b6dde9aa7..1a546f727 100644 --- a/packages/core/minos-microservice-aggregate/tests/utils.py +++ b/packages/core/minos-microservice-aggregate/tests/utils.py @@ -19,7 +19,6 @@ Aggregate, Entity, EntitySet, - ExternalEntity, InMemoryDeltaRepository, InMemorySnapshotRepository, Ref, @@ -161,13 +160,6 @@ class Review(ValueObject): message: str -class Product(ExternalEntity): - """For testing purposes.""" - - title: str - quantity: int - - class OrderAggregate(Aggregate[Order]): """For testing purposes.""" diff --git a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py index 0b6b401e0..b681a849d 100644 --- a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py +++ b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py @@ -3,6 +3,7 @@ patch, ) from uuid import ( + UUID, uuid4, ) @@ -14,6 +15,7 @@ Ref, ) from minos.common import ( + ModelType, current_datetime, ) from minos.cqrs import ( @@ -22,9 +24,8 @@ from minos.networks import ( BrokerClientPool, ) -from tests.utils import ( - Bar, -) + +Bar = ModelType.build("Bar", uuid=UUID, version=int, name=str) class TestPreEventHandler(unittest.IsolatedAsyncioTestCase): diff --git a/packages/core/minos-microservice-cqrs/tests/utils.py b/packages/core/minos-microservice-cqrs/tests/utils.py index 46c50a43d..0a11a1fe2 100644 --- a/packages/core/minos-microservice-cqrs/tests/utils.py +++ b/packages/core/minos-microservice-cqrs/tests/utils.py @@ -8,7 +8,6 @@ from minos.aggregate import ( Entity, - ExternalEntity, Ref, ) from minos.cqrs import ( @@ -48,10 +47,4 @@ async def create_foo(self, request: Request) -> Response: class Foo(Entity): """For testing purposes""" - bar: Ref[Bar] - - -class Bar(ExternalEntity): - """For testing purposes""" - - name: str + bar: Ref["Bar"] From c3956041f9e8e2b7e1423c40a2dfa18cb6140438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Fri, 6 May 2022 12:32:26 +0200 Subject: [PATCH 65/75] ISSUE #450 * Add gather. --- .../minos/transactions/entries.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/core/minos-microservice-transactions/minos/transactions/entries.py b/packages/core/minos-microservice-transactions/minos/transactions/entries.py index 68c7af08e..0ea7a7009 100644 --- a/packages/core/minos-microservice-transactions/minos/transactions/entries.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/entries.py @@ -3,6 +3,9 @@ ) import logging +from asyncio import ( + gather, +) from contextlib import ( suppress, ) @@ -145,11 +148,14 @@ async def commit(self) -> None: await self.save(status=TransactionStatus.COMMITTED) async def _commit(self) -> None: - for subscriber in self._repository.observers: - await subscriber.commit_transaction( + futures = ( + subscriber.commit_transaction( transaction_uuid=self.uuid, destination_transaction_uuid=self.destination_uuid, ) + for subscriber in self._repository.observers + ) + await gather(*futures) async def reserve(self) -> None: """Reserve transaction changes to be ensured that they can be applied. @@ -234,8 +240,10 @@ async def reject(self) -> None: ) async with self._repository.write_lock(): - for subscriber in self._repository.observers: - await subscriber.reject_transaction(transaction_uuid=self.uuid) + futures = ( + subscriber.reject_transaction(transaction_uuid=self.uuid) for subscriber in self._repository.observers + ) + await gather(*futures) await self.save(status=TransactionStatus.REJECTED) From 56b57a10dc58245cebfb1ca879bb029ddc97b712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Fri, 6 May 2022 12:50:01 +0200 Subject: [PATCH 66/75] ISSUE #450 * Add support for direct `SnapshotRepository` accessing from `RefResolver`. --- .../aggregate/entities/refs/extractors.py | 12 ++--- .../aggregate/entities/refs/resolvers.py | 50 ++++++++++++++++-- .../aggregate/snapshots/repositories/abc.py | 13 +++-- .../test_refs/test_extractors.py | 51 ++++++++++--------- .../test_entities/test_refs/test_resolvers.py | 21 +++++++- .../test_repositories/test_abc.py | 24 +++++---- 6 files changed, 120 insertions(+), 51 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/extractors.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/extractors.py index 96d22da41..5838175ae 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/extractors.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/extractors.py @@ -17,6 +17,7 @@ ) from minos.common import ( + Model, TypeHintBuilder, is_model_type, ) @@ -36,7 +37,7 @@ def __init__(self, value: Any, type_: Optional[type] = None, as_uuids: bool = Tr self.type_ = type_ self.as_uuids = as_uuids - def build(self) -> dict[str, set[UUID]]: + def build(self) -> dict[type[Model], set[UUID]]: """Run the model reference extractor. :return: A dictionary in which the keys are the class names and the values are the identifiers. @@ -49,7 +50,7 @@ def build(self) -> dict[str, set[UUID]]: return ans - def _build(self, value: Any, type_: type, ans: dict[str, set[Ref]]) -> None: + def _build(self, value: Any, type_: type, ans: dict[type[Model], set[Ref]]) -> None: if get_origin(type_) is Union: type_ = next((t for t in get_args(type_) if get_origin(t) is Ref), type_) @@ -66,14 +67,13 @@ def _build(self, value: Any, type_: type, ans: dict[str, set[Ref]]) -> None: cls = args[0] if cls is None and len(args := get_args(type_.type_hints["data"])): cls = args[0] - name = cls.__name__ - ans[name].add(value) + ans[cls].add(value) elif is_model_type(value): # noinspection PyUnresolvedReferences for field in value.fields.values(): self._build(field.value, field.type, ans) - def _build_iterable(self, value: Iterable, value_: type, ans: dict[str, set[Ref]]) -> None: + def _build_iterable(self, value: Iterable, type_: type, ans: dict[type[Model], set[Ref]]) -> None: for sub_value in value: - self._build(sub_value, value_, ans) + self._build(sub_value, type_, ans) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/resolvers.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/resolvers.py index cdfb86b7f..3e9b91ca1 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/resolvers.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/resolvers.py @@ -5,9 +5,15 @@ from collections.abc import ( Iterable, ) +from functools import ( + reduce, +) from itertools import ( chain, ) +from operator import ( + or_, +) from typing import ( Any, Optional, @@ -20,6 +26,7 @@ from minos.common import ( Inject, Model, + ModelType, NotProvidedException, PoolFactory, ) @@ -30,9 +37,15 @@ BrokerMessageV1Payload, ) +from ...entities import ( + Entity, +) from ...exceptions import ( RefException, ) +from ...snapshots import ( + SnapshotRepository, +) from .extractors import ( RefExtractor, ) @@ -50,6 +63,7 @@ class RefResolver: @Inject() def __init__( self, + snapshot_repository: SnapshotRepository, broker_pool: Optional[BrokerClientPool] = None, pool_factory: Optional[PoolFactory] = None, **kwargs, @@ -60,6 +74,10 @@ def __init__( if not isinstance(broker_pool, BrokerClientPool): raise NotProvidedException(f"A {BrokerClientPool!r} instance is required. Obtained: {broker_pool}") + if snapshot_repository is None: + raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") + + self._snapshot_repository = snapshot_repository self.broker_pool = broker_pool # noinspection PyUnusedLocal @@ -79,10 +97,25 @@ async def resolve(self, data: Any, **kwargs) -> Any: return RefInjector(data, recovered).build() - async def _query(self, references: dict[str, set[UUID]]) -> dict[UUID, Model]: + async def _query(self, references: dict[type, set[UUID]]) -> dict[UUID, Model]: + snapshot, broker = dict(), dict() + for type_, uuids in references.items(): + if issubclass(type_, Entity) or (isinstance(type_, ModelType) and issubclass(type_.model_cls, Entity)): + snapshot[type_] = uuids + else: + broker[type_] = uuids + + parts = await gather(self._query_broker(broker), self._query_snapshot(snapshot)) + ans = reduce(or_, parts) + return ans + + async def _query_broker(self, references: dict[type, set[UUID]]) -> dict[UUID, Model]: + if not len(references): + return dict() + messages = ( - BrokerMessageV1(self.build_topic_name(name), BrokerMessageV1Payload({"uuids": uuids})) - for name, uuids in references.items() + BrokerMessageV1(self.build_topic_name(type_), BrokerMessageV1Payload({"uuids": refs})) + for type_, refs in references.items() ) async with self.broker_pool.acquire() as broker: futures = (broker.send(message) for message in messages) @@ -90,6 +123,17 @@ async def _query(self, references: dict[str, set[UUID]]) -> dict[UUID, Model]: return {model.uuid: model for model in await self._get_response(broker, len(references))} + async def _query_snapshot(self, references: dict[type, set[UUID]]) -> dict[UUID, Model]: + if not len(references): + return dict() + + futures = list() + for type_, uuids in references.items(): + for uuid in uuids: + # noinspection PyTypeChecker + futures.append(self._snapshot_repository.get(type_, uuid)) + return {model.uuid: model for model in await gather(*futures)} + @staticmethod async def _get_response(broker: BrokerClient, count: int, **kwargs) -> Iterable[Model]: messages = list() diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py index 658f43bd0..56bd6a60c 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py @@ -19,6 +19,7 @@ from minos.common import ( Injectable, + ModelType, SetupMixin, classname, ) @@ -56,7 +57,7 @@ class SnapshotRepository(ABC, SetupMixin): async def get( self, - name: Union[str, type[Entity]], + name: Union[str, type[Entity], ModelType], uuid: UUID, transaction: Optional[TransactionEntry] = None, **kwargs, @@ -75,7 +76,7 @@ async def get( instance = snapshot_entry.build(**kwargs) return instance - async def get_entry(self, name: str, uuid: UUID, **kwargs) -> SnapshotEntry: + async def get_entry(self, name: Union[str, type[Entity], ModelType], uuid: UUID, **kwargs) -> SnapshotEntry: """Get a ``SnapshotEntry`` from its identifier. :param name: Class name of the ``Entity``. @@ -93,7 +94,7 @@ async def get_entry(self, name: str, uuid: UUID, **kwargs) -> SnapshotEntry: def get_all( self, - name: str, + name: Union[str, type[Entity], ModelType], ordering: Optional[_Ordering] = None, limit: Optional[int] = None, streaming_mode: bool = False, @@ -127,7 +128,7 @@ def get_all( async def find( self, - name: Union[str, type[Entity]], + name: Union[str, type[Entity], ModelType], condition: _Condition, ordering: Optional[_Ordering] = None, limit: Optional[int] = None, @@ -165,7 +166,7 @@ async def find( async def find_entries( self, - name: str, + name: Union[str, type[Entity], ModelType], condition: _Condition, ordering: Optional[_Ordering] = None, limit: Optional[int] = None, @@ -195,6 +196,8 @@ async def find_entries( :param kwargs: Additional named arguments. :return: An asynchronous iterator that containing the ``Entity`` instances. """ + if isinstance(name, ModelType): + name = name.model_cls if isinstance(name, type): name = classname(name) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_extractors.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_extractors.py index 5de4171fb..34a9077f1 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_extractors.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_extractors.py @@ -16,71 +16,72 @@ ) +# noinspection PyPep8Naming class TestRefExtractor(unittest.TestCase): def test_simple(self): - mt_foo = ModelType.build("Foo", {"uuid": UUID, "version": int}) + Foo = ModelType.build("Foo", {"uuid": UUID, "version": int}) value = Ref(uuid4()) - expected = {"Foo": {value}} - observed = RefExtractor(value, Ref[mt_foo]).build() + expected = {Foo: {value}} + observed = RefExtractor(value, Ref[Foo]).build() self.assertEqual(expected, observed) def test_list(self): - mt_foo = ModelType.build("Foo", {"uuid": UUID, "version": int}) + Foo = ModelType.build("Foo", {"uuid": UUID, "version": int}) value = [Ref(uuid4()), Ref(uuid4())] - expected = {"Foo": set(value)} - observed = RefExtractor(value, list[Ref[mt_foo]]).build() + expected = {Foo: set(value)} + observed = RefExtractor(value, list[Ref[Foo]]).build() self.assertEqual(expected, observed) def test_dict(self): - mt_key = ModelType.build("Key", {"uuid": UUID, "version": int}) - mt_value = ModelType.build("Value", {"uuid": UUID, "version": int}) + Key = ModelType.build("Key", {"uuid": UUID, "version": int}) + Value = ModelType.build("Value", {"uuid": UUID, "version": int}) value = {Ref(uuid4()): Ref(uuid4()), Ref(uuid4()): Ref(uuid4())} - expected = {"Key": set(value.keys()), "Value": set(value.values())} - observed = RefExtractor(value, dict[Ref[mt_key], Ref[mt_value]]).build() + expected = {Key: set(value.keys()), Value: set(value.values())} + observed = RefExtractor(value, dict[Ref[Key], Ref[Value]]).build() self.assertEqual(expected, observed) def test_model(self): - mt_bar = ModelType.build("Bar", {"uuid": UUID, "version": int}) - mt_foo = ModelType.build("Foo", {"uuid": UUID, "version": int, "another": Ref[mt_bar]}) + Bar = ModelType.build("Bar", {"uuid": UUID, "version": int}) + Foo = ModelType.build("Foo", {"uuid": UUID, "version": int, "another": Ref[Bar]}) - value = mt_foo(uuid=uuid4(), version=1, another=Ref(uuid4())) + value = Foo(uuid=uuid4(), version=1, another=Ref(uuid4())) - expected = {"Bar": {value.another}} - observed = RefExtractor(value, mt_foo).build() + expected = {Bar: {value.another}} + observed = RefExtractor(value, Foo).build() self.assertEqual(expected, observed) def test_model_without_kind(self): - mt_bar = ModelType.build("Bar", {"uuid": UUID, "version": int}) - mt_foo = ModelType.build("Foo", {"uuid": UUID, "version": int, "another": Ref[mt_bar]}) + Bar = ModelType.build("Bar", {"uuid": UUID, "version": int}) + Foo = ModelType.build("Foo", {"uuid": UUID, "version": int, "another": Ref[Bar]}) - value = mt_foo(uuid=uuid4(), version=1, another=Ref(uuid4())) + value = Foo(uuid=uuid4(), version=1, another=Ref(uuid4())) - expected = RefExtractor(value, mt_foo).build() + expected = RefExtractor(value, Foo).build() observed = RefExtractor(value).build() self.assertEqual(expected, observed) def test_optional(self): - mt_foo = ModelType.build("Foo", {"uuid": UUID, "version": int}) + Foo = ModelType.build("Foo", {"uuid": UUID, "version": int}) value = Ref(uuid4()) - expected = {"Foo": {value}} - observed = RefExtractor(value, Optional[Ref[mt_foo]]).build() + expected = {Foo: {value}} + observed = RefExtractor(value, Optional[Ref[Foo]]).build() self.assertEqual(expected, observed) def test_model_cls_by_type_hints(self): - mt_foo = ModelType.build("Foo", {"uuid": UUID, "version": int}) + Foo = ModelType.build("Foo", {"uuid": UUID, "version": int}) - value = Ref(mt_foo(uuid4(), 1)) - self.assertEqual(mt_foo, value.data_cls) + value = Ref(Foo(uuid4(), 1)) + self.assertEqual(Foo, value.data_cls) def test_model_cls_none(self): value = Ref(uuid4()) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_resolvers.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_resolvers.py index f19bfcc8b..99c6c4d6c 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_resolvers.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_resolvers.py @@ -1,4 +1,7 @@ import unittest +from unittest.mock import ( + patch, +) from uuid import ( UUID, uuid4, @@ -8,6 +11,7 @@ Ref, RefException, RefResolver, + SnapshotRepository, ) from minos.common import ( ModelType, @@ -20,10 +24,12 @@ ) from tests.utils import ( AggregateTestCase, + Car, ) Bar = ModelType.build("Bar", {"uuid": UUID, "version": int}) Foo = ModelType.build("Foo", {"uuid": UUID, "version": int, "another": Ref[Bar]}) +FooBar = ModelType.build("FooBar", {"uuid": UUID, "version": int, "car": Ref[Car]}) class TestRefResolver(AggregateTestCase): @@ -40,7 +46,12 @@ def test_broker_pool_not_provided(self): # noinspection PyArgumentEqualDefault RefResolver(broker_pool=None, pool_factory=None) - async def test_resolve(self): + def test_snapshot_not_provided(self): + with self.assertRaises(NotProvidedException): + # noinspection PyTypeChecker + RefResolver(snapshot_repository=None) + + async def test_resolve_from_broker(self): self.broker_subscriber_builder.with_messages( [BrokerMessageV1("", BrokerMessageV1Payload([Bar(self.value.another.uuid, 1)]))] ) @@ -56,6 +67,14 @@ async def test_resolve(self): self.assertEqual(Foo(self.uuid, 1, another=Ref(Bar(self.another_uuid, 1))), resolved) + async def test_resolve_from_snapshot(self): + value = FooBar(self.uuid, 1, Ref(self.another_uuid)) + + with patch.object(SnapshotRepository, "get", return_value=Car(3, "blue", uuid=self.another_uuid)): + resolved = await self.resolver.resolve(value) + + self.assertEqual(FooBar(self.uuid, 1, Ref(Car(3, "blue", uuid=self.another_uuid))), resolved) + async def test_resolve_already(self): self.assertEqual(34, await self.resolver.resolve(34)) observed = self.broker_publisher.messages diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py index 693c2bf56..cc40cc529 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_abc.py @@ -24,7 +24,9 @@ _EqualCondition, ) from minos.common import ( + ModelType, SetupMixin, + classname, ) from minos.transactions import ( TRANSACTION_CONTEXT_VAR, @@ -59,7 +61,7 @@ def setUp(self) -> None: self.snapshot_repository._find_entries = self.find_mock self.snapshot_repository._synchronize = self.synchronize_mock - self.classname = "path.to.Product" + self.type_ = ModelType.from_model(Car) def test_subclass(self): self.assertTrue(issubclass(SnapshotRepository, (ABC, SetupMixin))) @@ -71,7 +73,7 @@ def test_abstract(self): async def test_get(self): transaction = TransactionEntry() uuid = uuid4() - observed = await self.snapshot_repository.get(self.classname, uuid, transaction) + observed = await self.snapshot_repository.get(self.type_, uuid, transaction) self.assertEqual(self.entries[0].build(), observed) self.assertEqual(1, self.synchronize_mock.call_count) @@ -79,7 +81,7 @@ async def test_get(self): self.assertEqual(1, self.find_mock.call_count) args = call( - name=self.classname, + name=classname(Car), condition=_EqualCondition("uuid", uuid), ordering=None, limit=None, @@ -90,7 +92,7 @@ async def test_get(self): self.assertEqual(args, self.find_mock.call_args) async def test_get_transaction_null(self): - await self.snapshot_repository.get(self.classname, uuid4()) + await self.snapshot_repository.get(self.type_, uuid4()) self.assertEqual(1, self.find_mock.call_count) self.assertEqual(None, self.find_mock.call_args.kwargs["transaction"]) @@ -98,7 +100,7 @@ async def test_get_transaction_null(self): async def test_get_transaction_context(self): transaction = TransactionEntry() TRANSACTION_CONTEXT_VAR.set(transaction) - await self.snapshot_repository.get(self.classname, uuid4()) + await self.snapshot_repository.get(self.type_, uuid4()) self.assertEqual(1, self.find_mock.call_count) self.assertEqual(transaction, self.find_mock.call_args.kwargs["transaction"]) @@ -106,14 +108,14 @@ async def test_get_transaction_context(self): async def test_get_all(self): transaction = TransactionEntry() - iterable = self.snapshot_repository.get_all(self.classname, Ordering.ASC("name"), 10, True, transaction) + iterable = self.snapshot_repository.get_all(self.type_, Ordering.ASC("name"), 10, True, transaction) observed = [a async for a in iterable] self.assertEqual([e.build() for e in self.entries], observed) self.assertEqual( [ call( - name=self.classname, + name=classname(Car), condition=Condition.TRUE, ordering=Ordering.ASC("name"), limit=10, @@ -128,7 +130,7 @@ async def test_get_all(self): async def test_find(self): transaction = TransactionEntry() iterable = self.snapshot_repository.find( - self.classname, Condition.TRUE, Ordering.ASC("name"), 10, True, transaction + self.type_, Condition.TRUE, Ordering.ASC("name"), 10, True, transaction ) observed = [a async for a in iterable] self.assertEqual([e.build() for e in self.entries], observed) @@ -138,7 +140,7 @@ async def test_find(self): self.assertEqual(1, self.find_mock.call_count) args = call( - name=self.classname, + name=classname(Car), condition=Condition.TRUE, ordering=Ordering.ASC("name"), limit=10, @@ -149,7 +151,7 @@ async def test_find(self): self.assertEqual(args, self.find_mock.call_args) async def test_find_transaction_null(self): - [a async for a in self.snapshot_repository.find(self.classname, Condition.TRUE)] + [a async for a in self.snapshot_repository.find(self.type_, Condition.TRUE)] self.assertEqual(1, self.find_mock.call_count) self.assertEqual(None, self.find_mock.call_args.kwargs["transaction"]) @@ -157,7 +159,7 @@ async def test_find_transaction_null(self): async def test_find_transaction_context(self): transaction = TransactionEntry() TRANSACTION_CONTEXT_VAR.set(transaction) - [a async for a in self.snapshot_repository.find(self.classname, Condition.TRUE)] + [a async for a in self.snapshot_repository.find(self.type_, Condition.TRUE)] self.assertEqual(1, self.find_mock.call_count) self.assertEqual(transaction, self.find_mock.call_args.kwargs["transaction"]) From dd8ef06c4ee03a74a029acf42fee68d2c9356278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Fri, 6 May 2022 13:17:58 +0200 Subject: [PATCH 67/75] ISSUE #450 * Fix broken tests. --- .../aggregate/entities/refs/resolvers.py | 24 +++++++++++++++---- .../test_entities/test_refs/test_resolvers.py | 9 +++++++ .../tests/test_cqrs/test_handlers.py | 18 +++++++------- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/resolvers.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/resolvers.py index 3e9b91ca1..38eb3fdbf 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/resolvers.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/refs/resolvers.py @@ -71,14 +71,30 @@ def __init__( if broker_pool is None and pool_factory is not None: broker_pool = pool_factory.get_pool("broker") - if not isinstance(broker_pool, BrokerClientPool): - raise NotProvidedException(f"A {BrokerClientPool!r} instance is required. Obtained: {broker_pool}") + if broker_pool is None: + raise NotProvidedException(f"A {BrokerClientPool!r} instance is required.") if snapshot_repository is None: raise NotProvidedException(f"A {SnapshotRepository!r} instance is required.") + self._broker_pool = broker_pool self._snapshot_repository = snapshot_repository - self.broker_pool = broker_pool + + @property + def broker_pool(self) -> BrokerClientPool: + """Get the broker pool. + + :return: A ``BrokerClientPool`` instance. + """ + return self._broker_pool + + @property + def snapshot_repository(self) -> SnapshotRepository: + """Get the snapshot repository. + + :return: A ``SnapshotRepository`` instance. + """ + return self._snapshot_repository # noinspection PyUnusedLocal async def resolve(self, data: Any, **kwargs) -> Any: @@ -117,7 +133,7 @@ async def _query_broker(self, references: dict[type, set[UUID]]) -> dict[UUID, M BrokerMessageV1(self.build_topic_name(type_), BrokerMessageV1Payload({"uuids": refs})) for type_, refs in references.items() ) - async with self.broker_pool.acquire() as broker: + async with self._broker_pool.acquire() as broker: futures = (broker.send(message) for message in messages) await gather(*futures) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_resolvers.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_resolvers.py index 99c6c4d6c..b6fe2182b 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_resolvers.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_refs/test_resolvers.py @@ -18,6 +18,7 @@ NotProvidedException, ) from minos.networks import ( + BrokerClientPool, BrokerMessageV1, BrokerMessageV1Payload, BrokerMessageV1Status, @@ -41,6 +42,14 @@ def setUp(self) -> None: self.another_uuid = uuid4() self.value = Foo(self.uuid, 1, another=Ref(self.another_uuid)) + def test_broker_pool(self): + resolver = RefResolver() + self.assertIsInstance(resolver.broker_pool, BrokerClientPool) + + def test_snapshot_repository(self): + resolver = RefResolver() + self.assertIsInstance(resolver.snapshot_repository, SnapshotRepository) + def test_broker_pool_not_provided(self): with self.assertRaises(NotProvidedException): # noinspection PyArgumentEqualDefault diff --git a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py index b681a849d..d1f8de9ba 100644 --- a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py +++ b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_handlers.py @@ -13,6 +13,7 @@ FieldDiff, FieldDiffContainer, Ref, + RefResolver, ) from minos.common import ( ModelType, @@ -21,9 +22,6 @@ from minos.cqrs import ( PreEventHandler, ) -from minos.networks import ( - BrokerClientPool, -) Bar = ModelType.build("Bar", uuid=UUID, version=int, name=str) @@ -42,8 +40,6 @@ def setUp(self) -> None: FieldDiffContainer([FieldDiff("bars", list[Ref[Bar]], [b.uuid for b in self.bars])]), ) - self.broker_pool = BrokerClientPool({}) - async def test_handle_resolving_dependencies(self): value = Delta( self.uuid, @@ -54,8 +50,10 @@ async def test_handle_resolving_dependencies(self): FieldDiffContainer([FieldDiff("bars", list[Ref[Bar]], self.bars)]), ) - with patch("minos.aggregate.RefResolver.resolve", return_value=value): - observed = await PreEventHandler.handle(self.diff, resolve_references=True, broker_pool=self.broker_pool) + with patch.object(RefResolver, "resolve", return_value=value): + observed = await PreEventHandler.handle( + self.diff, resolve_references=True, broker_pool=object(), snapshot_repository=object() + ) self.assertEqual(value, observed) self.assertEqual(self.bars, [b.data for b in observed["bars"]]) @@ -69,8 +67,10 @@ async def test_handle_without_resolving_references(self): self.assertEqual(self.diff, observed) async def test_handle_raises(self): - with patch("minos.aggregate.RefResolver.resolve", side_effect=ValueError): - observed = await PreEventHandler.handle(self.diff, resolve_references=True, broker_pool=self.broker_pool) + with patch.object(RefResolver, "resolve", side_effect=ValueError): + observed = await PreEventHandler.handle( + self.diff, resolve_references=True, broker_pool=object(), snapshot_repository=object() + ) expected = Delta( self.uuid, From 27c400cc91306a67a17fa68bf3fc5d0e3b90fb9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 9 May 2022 09:27:12 +0200 Subject: [PATCH 68/75] ISSUE #410 * Add `has_one` method to `FieldDiffContainer`. * Add `has_field` method to `Delta`. --- .../minos/aggregate/deltas/fields.py | 8 ++++++++ .../minos/aggregate/deltas/models.py | 8 ++++++++ .../tests/test_aggregate/test_deltas/test_fields.py | 4 ++++ .../tests/test_aggregate/test_deltas/test_models.py | 4 ++++ .../test_models/test_root/test_differences.py | 2 ++ 5 files changed, 26 insertions(+) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/fields.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/fields.py index 62317cbdd..b0ed21212 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/fields.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/fields.py @@ -116,6 +116,14 @@ def __iter__(self) -> Iterable[str]: """ yield from self._mapper.keys() + def has_one(self, name: str) -> bool: + """Check if the field identified is present in the container. + + :param name: The name of the field. + :return: ``True`` if the field is present or ``False`` otherwise. + """ + return name in self._mapper + def get_one(self, name: str, return_diff: bool = True) -> Union[FieldDiff, Any, list[FieldDiff], list[Any]]: """Get first field diff with given name. diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py index ccdea14c2..c26144190 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/deltas/models.py @@ -96,6 +96,14 @@ def get_one(self, name: str, return_diff: bool = False) -> Union[FieldDiff, Any, warnings.warn("get_one() method is deprecated by get_field() and will be removed soon.", DeprecationWarning) return self.get_field(name, return_diff) + def has_field(self, name: str) -> bool: + """Check if the field identified is present. + + :param name: The name of the field. + :return: ``True`` if the field is present or ``False`` otherwise. + """ + return self.fields_diff.has_one(name) + def get_field(self, name: str, return_diff: bool = False) -> Union[FieldDiff, Any, list[FieldDiff], list[Any]]: """Get first field diff with given name. diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_fields.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_fields.py index 562a941f5..4fa93ee32 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_fields.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_fields.py @@ -230,6 +230,10 @@ def test_get_item_raises(self): with self.assertRaises(KeyError): self.fields_diff["something"] + def test_has_one(self): + self.assertTrue(self.fields_diff.has_one("color")) + self.assertFalse(self.fields_diff.has_one("something")) + def test_get_one_single(self): observed = self.fields_diff.get_one("color") expected = FieldDiff("color", str, "red") diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_models.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_models.py index 581579584..5bed7fa10 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_models.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_deltas/test_models.py @@ -212,6 +212,10 @@ def test_get_one_multiple_diff(self): observed = self.diff.get_one("doors", return_diff=True) self.assertEqual(expected, observed) + def test_has_field(self): + self.assertTrue(self.diff.has_field("color")) + self.assertFalse(self.diff.has_field("something")) + def test_get_field_single(self): observed = self.diff.get_field("color") expected = "red" diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_differences.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_differences.py index b365664d2..cb52f0cfc 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_differences.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_models/test_root/test_differences.py @@ -20,6 +20,8 @@ class TestRootEntityDifferences(AggregateTestCase): async def asyncSetUp(self) -> None: + await super().asyncSetUp() + self.uuid = uuid4() self.uuid_another = uuid4() From 973b25fb89583a21d2ebfd23724342e8637ea3b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 9 May 2022 12:35:36 +0200 Subject: [PATCH 69/75] ISSUE #50 * Add `find_one` method to `SnapshotRepository`. --- .../minos/aggregate/entities/repositories.py | 13 ++++++- .../aggregate/snapshots/repositories/abc.py | 22 +++++++++++ .../snapshots/repositories/testcases.py | 33 ++++++++++++++++ .../test_repositories/test_base.py | 17 ++++++++ .../test_repositories/test_database.py | 39 +++++++++++++++++++ 5 files changed, 122 insertions(+), 2 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py index 3a96b0e72..c3ea797d6 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py @@ -97,6 +97,16 @@ def get_all( # noinspection PyTypeChecker return self._snapshot_repository.get_all(type_, ordering, limit, **kwargs) + async def find_one(self, type_: type[T], condition: _Condition, **kwargs) -> T: + """Find a ``Entity`` instance based on a ``Condition``. + + :param type_: The type of the entity to be looked for. + :param condition: The condition that must be satisfied by the ``Entity`` instances. + :param kwargs: Additional named arguments. + :return: An asynchronous iterator that containing the ``Entity`` instances. + """ + return await self._snapshot_repository.find_one(type_, condition, **kwargs) + def find( self, type_: type[T], @@ -107,7 +117,7 @@ def find( ) -> AsyncIterator[T]: """Find a collection of instances based on a given ``Condition``. - :param type_: The of the entity to be looked for. + :param type_: The type of the entity to be looked for. :param condition: The ``Condition`` that must be satisfied by all the instances. :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour is to retrieve them without any order pattern. @@ -115,7 +125,6 @@ def find( instances that meet the given condition. :return: An asynchronous iterator of ``Entity`` instances. """ - # noinspection PyTypeChecker return self._snapshot_repository.find(type_, condition, ordering, limit, **kwargs) async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> tuple[T, Delta]: diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py index 56bd6a60c..89c2dbd69 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py @@ -126,6 +126,28 @@ def get_all( **kwargs, ) + async def find_one( + self, + name: Union[str, type[Entity]], + condition: _Condition, + transaction: Optional[TransactionEntry] = None, + **kwargs, + ) -> Entity: + """Find a ``Entity`` instance based on a ``Condition``. + + :param name: Class name of the ``Entity``. + :param condition: The condition that must be satisfied by the ``Entity`` instances. + :param transaction: The transaction within the operation is performed. If not any value is provided, then the + transaction is extracted from the context var. If not any transaction is being scoped then the query is + performed to the global snapshot. + :param kwargs: Additional named arguments. + :return: An asynchronous iterator that containing the ``Entity`` instances. + """ + try: + return await self.find(name, condition=condition, limit=1, transaction=transaction, **kwargs).__anext__() + except StopAsyncIteration: + raise NotFoundException(f"There are not any instance matching the given condition: {condition}") + async def find( self, name: Union[str, type[Entity], ModelType], diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py index 3c83229a1..9e925ed3d 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py @@ -532,6 +532,39 @@ async def test_find_empty(self): expected = set() self.assertEqual(expected, observed) + async def test_find_one(self): + await self.populate_and_synchronize() + condition = Condition.IN("uuid", {self.uuid_2}) + + observed = await self.snapshot_repository.find_one(self.Car, condition) + + expected = self.Car( + 3, + "blue", + uuid=self.uuid_2, + version=2, + created_at=observed.created_at, + updated_at=observed.updated_at, + ) + self.assertEqual(expected, observed) + + async def test_find_one_raises(self): + await self.populate_and_synchronize() + condition = Condition.FALSE + + with self.assertRaises(NotFoundException): + await self.snapshot_repository.find_one(self.Car, condition) + + async def test_get_all(self): + await self.populate_and_synchronize() + iterable = self.snapshot_repository.find(self.Car, Condition.TRUE, ordering=Ordering.ASC("updated_at")) + expected = [v async for v in iterable] + + iterable = self.snapshot_repository.get_all(self.Car, ordering=Ordering.ASC("updated_at")) + observed = [v async for v in iterable] + + self.assertEqual(expected, observed) + async def test_get(self): await self.populate_and_synchronize() observed = await self.snapshot_repository.get(self.Car, self.uuid_2) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py index 267b890f1..0429d30dc 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py @@ -110,6 +110,23 @@ async def test_find(self): self.assertEqual(originals, recovered) + async def test_find_one(self): + originals = list( + map( + itemgetter(0), + await gather( + self.repository.create(Car, doors=3, color="blue"), + self.repository.create(Car, doors=3, color="red"), + self.repository.create(Car, doors=5, color="blue"), + ), + ) + ) + condition = Condition.IN("uuid", {originals[0].uuid}) + observed = await self.repository.find_one(Car, condition) + expected = originals[0] + + self.assertEqual(expected, observed) + async def test_get(self): original, _ = await self.repository.create(Car, doors=3, color="blue") recovered = await self.repository.get(Car, original.uuid) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py index 1b660436c..95b328354 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py @@ -414,6 +414,45 @@ async def test_find_empty(self): ): await super().test_find_empty() + async def test_find_one(self): + entities = [ + SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_2, version=2), + ] + with patch.object(DatabaseClient, "fetch_one", return_value=(9999,)): + with patch.object( + DatabaseClient, + "fetch_all", + return_value=FakeAsyncIterator( + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] + ), + ): + await super().test_find_one() + + async def test_find_one_raises(self): + with patch.object(DatabaseClient, "fetch_one", return_value=(9999,)): + with patch.object( + DatabaseClient, + "fetch_all", + return_value=FakeAsyncIterator([]), + ): + await super().test_find_one_raises() + + async def test_get_all(self): + entities = [ + SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_1, version=1), + SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_2, version=2), + SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_3, version=1), + ] + with patch.object(DatabaseClient, "fetch_one", return_value=(9999,)): + with patch.object( + DatabaseClient, + "fetch_all", + side_effect=lambda: FakeAsyncIterator( + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] + ), + ): + await super().test_get_all() + async def test_get(self): entities = [ SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_2, version=2), From 1306214abda94eae42b6b349f8cce70d6cc47488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 9 May 2022 12:42:57 +0200 Subject: [PATCH 70/75] Revert "ISSUE #50" This reverts commit 973b25fb89583a21d2ebfd23724342e8637ea3b9. --- .../minos/aggregate/entities/repositories.py | 13 +------ .../aggregate/snapshots/repositories/abc.py | 22 ----------- .../snapshots/repositories/testcases.py | 33 ---------------- .../test_repositories/test_base.py | 17 -------- .../test_repositories/test_database.py | 39 ------------------- 5 files changed, 2 insertions(+), 122 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py index c3ea797d6..3a96b0e72 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py @@ -97,16 +97,6 @@ def get_all( # noinspection PyTypeChecker return self._snapshot_repository.get_all(type_, ordering, limit, **kwargs) - async def find_one(self, type_: type[T], condition: _Condition, **kwargs) -> T: - """Find a ``Entity`` instance based on a ``Condition``. - - :param type_: The type of the entity to be looked for. - :param condition: The condition that must be satisfied by the ``Entity`` instances. - :param kwargs: Additional named arguments. - :return: An asynchronous iterator that containing the ``Entity`` instances. - """ - return await self._snapshot_repository.find_one(type_, condition, **kwargs) - def find( self, type_: type[T], @@ -117,7 +107,7 @@ def find( ) -> AsyncIterator[T]: """Find a collection of instances based on a given ``Condition``. - :param type_: The type of the entity to be looked for. + :param type_: The of the entity to be looked for. :param condition: The ``Condition`` that must be satisfied by all the instances. :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour is to retrieve them without any order pattern. @@ -125,6 +115,7 @@ def find( instances that meet the given condition. :return: An asynchronous iterator of ``Entity`` instances. """ + # noinspection PyTypeChecker return self._snapshot_repository.find(type_, condition, ordering, limit, **kwargs) async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> tuple[T, Delta]: diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py index 89c2dbd69..56bd6a60c 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py @@ -126,28 +126,6 @@ def get_all( **kwargs, ) - async def find_one( - self, - name: Union[str, type[Entity]], - condition: _Condition, - transaction: Optional[TransactionEntry] = None, - **kwargs, - ) -> Entity: - """Find a ``Entity`` instance based on a ``Condition``. - - :param name: Class name of the ``Entity``. - :param condition: The condition that must be satisfied by the ``Entity`` instances. - :param transaction: The transaction within the operation is performed. If not any value is provided, then the - transaction is extracted from the context var. If not any transaction is being scoped then the query is - performed to the global snapshot. - :param kwargs: Additional named arguments. - :return: An asynchronous iterator that containing the ``Entity`` instances. - """ - try: - return await self.find(name, condition=condition, limit=1, transaction=transaction, **kwargs).__anext__() - except StopAsyncIteration: - raise NotFoundException(f"There are not any instance matching the given condition: {condition}") - async def find( self, name: Union[str, type[Entity], ModelType], diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py index 9e925ed3d..3c83229a1 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py @@ -532,39 +532,6 @@ async def test_find_empty(self): expected = set() self.assertEqual(expected, observed) - async def test_find_one(self): - await self.populate_and_synchronize() - condition = Condition.IN("uuid", {self.uuid_2}) - - observed = await self.snapshot_repository.find_one(self.Car, condition) - - expected = self.Car( - 3, - "blue", - uuid=self.uuid_2, - version=2, - created_at=observed.created_at, - updated_at=observed.updated_at, - ) - self.assertEqual(expected, observed) - - async def test_find_one_raises(self): - await self.populate_and_synchronize() - condition = Condition.FALSE - - with self.assertRaises(NotFoundException): - await self.snapshot_repository.find_one(self.Car, condition) - - async def test_get_all(self): - await self.populate_and_synchronize() - iterable = self.snapshot_repository.find(self.Car, Condition.TRUE, ordering=Ordering.ASC("updated_at")) - expected = [v async for v in iterable] - - iterable = self.snapshot_repository.get_all(self.Car, ordering=Ordering.ASC("updated_at")) - observed = [v async for v in iterable] - - self.assertEqual(expected, observed) - async def test_get(self): await self.populate_and_synchronize() observed = await self.snapshot_repository.get(self.Car, self.uuid_2) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py index 0429d30dc..267b890f1 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py @@ -110,23 +110,6 @@ async def test_find(self): self.assertEqual(originals, recovered) - async def test_find_one(self): - originals = list( - map( - itemgetter(0), - await gather( - self.repository.create(Car, doors=3, color="blue"), - self.repository.create(Car, doors=3, color="red"), - self.repository.create(Car, doors=5, color="blue"), - ), - ) - ) - condition = Condition.IN("uuid", {originals[0].uuid}) - observed = await self.repository.find_one(Car, condition) - expected = originals[0] - - self.assertEqual(expected, observed) - async def test_get(self): original, _ = await self.repository.create(Car, doors=3, color="blue") recovered = await self.repository.get(Car, original.uuid) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py index 95b328354..1b660436c 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py @@ -414,45 +414,6 @@ async def test_find_empty(self): ): await super().test_find_empty() - async def test_find_one(self): - entities = [ - SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_2, version=2), - ] - with patch.object(DatabaseClient, "fetch_one", return_value=(9999,)): - with patch.object( - DatabaseClient, - "fetch_all", - return_value=FakeAsyncIterator( - [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] - ), - ): - await super().test_find_one() - - async def test_find_one_raises(self): - with patch.object(DatabaseClient, "fetch_one", return_value=(9999,)): - with patch.object( - DatabaseClient, - "fetch_all", - return_value=FakeAsyncIterator([]), - ): - await super().test_find_one_raises() - - async def test_get_all(self): - entities = [ - SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_1, version=1), - SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_2, version=2), - SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_3, version=1), - ] - with patch.object(DatabaseClient, "fetch_one", return_value=(9999,)): - with patch.object( - DatabaseClient, - "fetch_all", - side_effect=lambda: FakeAsyncIterator( - [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] - ), - ): - await super().test_get_all() - async def test_get(self): entities = [ SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_2, version=2), From f7ae22e1f576df069204008cea47de076a127317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Mon, 9 May 2022 12:35:36 +0200 Subject: [PATCH 71/75] ISSUE #453 * Add `find_one` method to `SnapshotRepository`. --- .../minos/aggregate/entities/repositories.py | 13 ++++++- .../aggregate/snapshots/repositories/abc.py | 22 +++++++++++ .../snapshots/repositories/testcases.py | 33 ++++++++++++++++ .../test_repositories/test_base.py | 17 ++++++++ .../test_repositories/test_database.py | 39 +++++++++++++++++++ 5 files changed, 122 insertions(+), 2 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py index 3a96b0e72..c3ea797d6 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/entities/repositories.py @@ -97,6 +97,16 @@ def get_all( # noinspection PyTypeChecker return self._snapshot_repository.get_all(type_, ordering, limit, **kwargs) + async def find_one(self, type_: type[T], condition: _Condition, **kwargs) -> T: + """Find a ``Entity`` instance based on a ``Condition``. + + :param type_: The type of the entity to be looked for. + :param condition: The condition that must be satisfied by the ``Entity`` instances. + :param kwargs: Additional named arguments. + :return: An asynchronous iterator that containing the ``Entity`` instances. + """ + return await self._snapshot_repository.find_one(type_, condition, **kwargs) + def find( self, type_: type[T], @@ -107,7 +117,7 @@ def find( ) -> AsyncIterator[T]: """Find a collection of instances based on a given ``Condition``. - :param type_: The of the entity to be looked for. + :param type_: The type of the entity to be looked for. :param condition: The ``Condition`` that must be satisfied by all the instances. :param ordering: Optional argument to return the instance with specific ordering strategy. The default behaviour is to retrieve them without any order pattern. @@ -115,7 +125,6 @@ def find( instances that meet the given condition. :return: An asynchronous iterator of ``Entity`` instances. """ - # noinspection PyTypeChecker return self._snapshot_repository.find(type_, condition, ordering, limit, **kwargs) async def create(self, type_or_instance: Union[T, type[T]], *args, **kwargs) -> tuple[T, Delta]: diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py index 56bd6a60c..89c2dbd69 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/snapshots/repositories/abc.py @@ -126,6 +126,28 @@ def get_all( **kwargs, ) + async def find_one( + self, + name: Union[str, type[Entity]], + condition: _Condition, + transaction: Optional[TransactionEntry] = None, + **kwargs, + ) -> Entity: + """Find a ``Entity`` instance based on a ``Condition``. + + :param name: Class name of the ``Entity``. + :param condition: The condition that must be satisfied by the ``Entity`` instances. + :param transaction: The transaction within the operation is performed. If not any value is provided, then the + transaction is extracted from the context var. If not any transaction is being scoped then the query is + performed to the global snapshot. + :param kwargs: Additional named arguments. + :return: An asynchronous iterator that containing the ``Entity`` instances. + """ + try: + return await self.find(name, condition=condition, limit=1, transaction=transaction, **kwargs).__anext__() + except StopAsyncIteration: + raise NotFoundException(f"There are not any instance matching the given condition: {condition}") + async def find( self, name: Union[str, type[Entity], ModelType], diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py index 3c83229a1..9e925ed3d 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/testing/snapshots/repositories/testcases.py @@ -532,6 +532,39 @@ async def test_find_empty(self): expected = set() self.assertEqual(expected, observed) + async def test_find_one(self): + await self.populate_and_synchronize() + condition = Condition.IN("uuid", {self.uuid_2}) + + observed = await self.snapshot_repository.find_one(self.Car, condition) + + expected = self.Car( + 3, + "blue", + uuid=self.uuid_2, + version=2, + created_at=observed.created_at, + updated_at=observed.updated_at, + ) + self.assertEqual(expected, observed) + + async def test_find_one_raises(self): + await self.populate_and_synchronize() + condition = Condition.FALSE + + with self.assertRaises(NotFoundException): + await self.snapshot_repository.find_one(self.Car, condition) + + async def test_get_all(self): + await self.populate_and_synchronize() + iterable = self.snapshot_repository.find(self.Car, Condition.TRUE, ordering=Ordering.ASC("updated_at")) + expected = [v async for v in iterable] + + iterable = self.snapshot_repository.get_all(self.Car, ordering=Ordering.ASC("updated_at")) + observed = [v async for v in iterable] + + self.assertEqual(expected, observed) + async def test_get(self): await self.populate_and_synchronize() observed = await self.snapshot_repository.get(self.Car, self.uuid_2) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py index 267b890f1..0429d30dc 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_entities/test_repositories/test_base.py @@ -110,6 +110,23 @@ async def test_find(self): self.assertEqual(originals, recovered) + async def test_find_one(self): + originals = list( + map( + itemgetter(0), + await gather( + self.repository.create(Car, doors=3, color="blue"), + self.repository.create(Car, doors=3, color="red"), + self.repository.create(Car, doors=5, color="blue"), + ), + ) + ) + condition = Condition.IN("uuid", {originals[0].uuid}) + observed = await self.repository.find_one(Car, condition) + expected = originals[0] + + self.assertEqual(expected, observed) + async def test_get(self): original, _ = await self.repository.create(Car, doors=3, color="blue") recovered = await self.repository.get(Car, original.uuid) diff --git a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py index 1b660436c..95b328354 100644 --- a/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py +++ b/packages/core/minos-microservice-aggregate/tests/test_aggregate/test_snapshots/test_repositories/test_database.py @@ -414,6 +414,45 @@ async def test_find_empty(self): ): await super().test_find_empty() + async def test_find_one(self): + entities = [ + SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_2, version=2), + ] + with patch.object(DatabaseClient, "fetch_one", return_value=(9999,)): + with patch.object( + DatabaseClient, + "fetch_all", + return_value=FakeAsyncIterator( + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] + ), + ): + await super().test_find_one() + + async def test_find_one_raises(self): + with patch.object(DatabaseClient, "fetch_one", return_value=(9999,)): + with patch.object( + DatabaseClient, + "fetch_all", + return_value=FakeAsyncIterator([]), + ): + await super().test_find_one_raises() + + async def test_get_all(self): + entities = [ + SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_1, version=1), + SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_2, version=2), + SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_3, version=1), + ] + with patch.object(DatabaseClient, "fetch_one", return_value=(9999,)): + with patch.object( + DatabaseClient, + "fetch_all", + side_effect=lambda: FakeAsyncIterator( + [tuple(SnapshotEntry.from_entity(entity).as_raw().values()) for entity in entities] + ), + ): + await super().test_get_all() + async def test_get(self): entities = [ SnapshotRepositoryTestCase.Car(3, "blue", uuid=self.uuid_2, version=2), From 22b07fc2e21ef7d8d42582e73518d51ea93a5f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Tue, 10 May 2022 11:25:22 +0200 Subject: [PATCH 72/75] ISSUE #65 * Remove `minos-microservice-networks` from `minos-microservice-transactions` test triggers. --- .github/workflows/minos-microservice-transactions-tests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/minos-microservice-transactions-tests.yml b/.github/workflows/minos-microservice-transactions-tests.yml index 8b9751bd9..883c729ab 100644 --- a/.github/workflows/minos-microservice-transactions-tests.yml +++ b/.github/workflows/minos-microservice-transactions-tests.yml @@ -8,7 +8,6 @@ on: pull_request: paths: - 'packages/core/minos-microservice-transactions/**' - - 'packages/core/minos-microservice-networks/**' - 'packages/core/minos-microservice-common/**' jobs: From 8153427d9d062bd416313e75187bc0281b8dda47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Tue, 10 May 2022 12:16:35 +0200 Subject: [PATCH 73/75] ISSUE #? * Minor improvement. --- .../minos-microservice-cqrs/tests/test_cqrs/test_services.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py index 2f4ad0331..b38854666 100644 --- a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py +++ b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py @@ -16,6 +16,7 @@ ) from minos.cqrs import ( MinosIllegalHandlingException, + PreEventHandler, Service, ) from minos.networks import ( @@ -47,6 +48,7 @@ def setUp(self) -> None: def tearDown(self) -> None: self.injector.unwire_injections() + super().tearDown() async def test_constructor(self): self.assertEqual(self.config, self.service.config) @@ -57,7 +59,7 @@ async def test_constructor(self): self.service.delta_repository async def test_pre_event(self): - with patch("minos.cqrs.PreEventHandler.handle") as mock: + with patch.object(PreEventHandler, "handle") as mock: mock.return_value = "bar" observed = self.service._pre_event_handle(InMemoryRequest("foo")) self.assertIsInstance(observed, WrappedRequest) From 4a85647f146c81d67c3cb3c07726cad4ed34dfe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Tue, 10 May 2022 12:47:58 +0200 Subject: [PATCH 74/75] ISSUE #? * Fix warnings. --- .../test_common/test_database/test_mixins.py | 30 +++++++++---------- .../test_common/test_database/test_pools.py | 20 ++++++------- .../tests/test_common/test_pools.py | 15 ++++++---- .../tests/test_cqrs/test_services.py | 8 +++++ .../tests/utils.py | 14 ++++++++- 5 files changed, 56 insertions(+), 31 deletions(-) diff --git a/packages/core/minos-microservice-common/tests/test_common/test_database/test_mixins.py b/packages/core/minos-microservice-common/tests/test_common/test_database/test_mixins.py index a0433e187..d41af1910 100644 --- a/packages/core/minos-microservice-common/tests/test_common/test_database/test_mixins.py +++ b/packages/core/minos-microservice-common/tests/test_common/test_database/test_mixins.py @@ -20,25 +20,25 @@ # noinspection SqlNoDataSourceInspection,SqlResolve class TestDatabaseMixin(CommonTestCase, DatabaseMinosTestCase): - def test_constructor(self): - pool = DatabaseClientPool.from_config(self.config) - # noinspection PyTypeChecker - database = DatabaseMixin(pool) - self.assertEqual(pool, database.database_pool) + async def test_constructor(self): + async with DatabaseClientPool.from_config(self.config) as pool: + # noinspection PyTypeChecker + database = DatabaseMixin(pool) + self.assertEqual(pool, database.database_pool) async def test_constructor_with_pool_factory(self): - pool_factory = PoolFactory(self.config, {"database": DatabaseClientPool}) - # noinspection PyTypeChecker - database = DatabaseMixin(pool_factory=pool_factory) - # noinspection PyUnresolvedReferences - self.assertEqual(pool_factory.get_pool("database"), database.database_pool) + async with PoolFactory(self.config, {"database": DatabaseClientPool}) as pool_factory: + # noinspection PyTypeChecker + database = DatabaseMixin(pool_factory=pool_factory) + # noinspection PyUnresolvedReferences + self.assertEqual(pool_factory.get_pool("database"), database.database_pool) async def test_constructor_with_pool_factory_and_database_key(self): - pool_factory = PoolFactory(self.config, {"database": DatabaseClientPool}) - # noinspection PyTypeChecker - database = DatabaseMixin(pool_factory=pool_factory, database_key=("query", "unknown")) - # noinspection PyUnresolvedReferences - self.assertEqual(pool_factory.get_pool("database", "query"), database.database_pool) + async with PoolFactory(self.config, {"database": DatabaseClientPool}) as pool_factory: + # noinspection PyTypeChecker + database = DatabaseMixin(pool_factory=pool_factory, database_key=("query", "unknown")) + # noinspection PyUnresolvedReferences + self.assertEqual(pool_factory.get_pool("database", "query"), database.database_pool) async def test_constructor_raises(self): with self.assertRaises(NotProvidedException): diff --git a/packages/core/minos-microservice-common/tests/test_common/test_database/test_pools.py b/packages/core/minos-microservice-common/tests/test_common/test_database/test_pools.py index bfe2d53b8..bf4b73bc1 100644 --- a/packages/core/minos-microservice-common/tests/test_common/test_database/test_pools.py +++ b/packages/core/minos-microservice-common/tests/test_common/test_database/test_pools.py @@ -28,10 +28,10 @@ def setUp(self) -> None: super().setUp() self.pool = DatabaseClientPool.from_config(self.config) - def test_constructor(self): + async def test_constructor(self): builder = DatabaseClientBuilder() - pool = DatabaseClientPool(builder) - self.assertEqual(builder, pool.client_builder) + async with DatabaseClientPool(builder) as pool: + self.assertEqual(builder, pool.client_builder) async def asyncSetUp(self): await super().asyncSetUp() @@ -41,15 +41,15 @@ async def asyncTearDown(self): await self.pool.destroy() await super().asyncTearDown() - def test_from_config(self): - pool = DatabaseClientPool.from_config(self.config, key="event") - self.assertIsInstance(pool.client_builder, DatabaseClientBuilder) - self.assertEqual(MockedDatabaseClient, pool.client_builder.instance_cls) + async def test_from_config(self): + async with DatabaseClientPool.from_config(self.config, key="event") as pool: + self.assertIsInstance(pool.client_builder, DatabaseClientBuilder) + self.assertEqual(MockedDatabaseClient, pool.client_builder.instance_cls) - def test_from_config_client_builder(self): + async def test_from_config_client_builder(self): config = Config(CONFIG_FILE_PATH, databases_default_client=classname(DatabaseClientBuilder)) - pool = DatabaseClientPool.from_config(config) - self.assertIsInstance(pool.client_builder, DatabaseClientBuilder) + async with DatabaseClientPool.from_config(config) as pool: + self.assertIsInstance(pool.client_builder, DatabaseClientBuilder) def test_from_config_client_none(self): config = Config(CONFIG_FILE_PATH, databases_default_client=None) diff --git a/packages/core/minos-microservice-common/tests/test_common/test_pools.py b/packages/core/minos-microservice-common/tests/test_common/test_pools.py index f0607679f..db22aa6e6 100644 --- a/packages/core/minos-microservice-common/tests/test_common/test_pools.py +++ b/packages/core/minos-microservice-common/tests/test_common/test_pools.py @@ -36,13 +36,18 @@ def setUp(self): super().setUp() self.factory = PoolFactory(self.config, {"lock": FakeLockPool}) - def test_from_config(self): - self.assertIsInstance(PoolFactory.from_config(self.config), PoolFactory) + async def asyncSetUp(self): + await super().asyncSetUp() + await self.factory.setup() async def asyncTearDown(self): await self.factory.destroy() await super().asyncTearDown() + async def test_from_config(self): + async with PoolFactory.from_config(self.config) as pool_factory: + self.assertIsInstance(pool_factory, PoolFactory) + def test_get_pool(self): lock = self.factory.get_pool("lock") self.assertIsInstance(lock, FakeLockPool) @@ -119,11 +124,11 @@ class TestMinosPool(unittest.IsolatedAsyncioTestCase): def test_is_subclass(self): self.assertTrue(issubclass(MinosPool, SetupMixin)) - def test_warnings(self): + async def test_warnings(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) - setup = _MinosPool() - self.assertIsInstance(setup, SetupMixin) + async with _MinosPool() as setup: + self.assertIsInstance(setup, SetupMixin) class _MinosPool(MinosPool): diff --git a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py index b38854666..f30916b2c 100644 --- a/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py +++ b/packages/core/minos-microservice-cqrs/tests/test_cqrs/test_services.py @@ -46,6 +46,14 @@ def setUp(self) -> None: self.service = FakeService(config=self.config, lock_pool=self.lock_pool) + async def asyncSetUp(self): + await super().asyncSetUp() + await self.lock_pool.setup() + + async def asyncTearDown(self) -> None: + await self.lock_pool.destroy() + await super().asyncTearDown() + def tearDown(self) -> None: self.injector.unwire_injections() super().tearDown() diff --git a/packages/core/minos-microservice-networks/tests/utils.py b/packages/core/minos-microservice-networks/tests/utils.py index d22e08ee5..ad94bc687 100644 --- a/packages/core/minos-microservice-networks/tests/utils.py +++ b/packages/core/minos-microservice-networks/tests/utils.py @@ -50,12 +50,24 @@ class NetworksTestCase(MinosTestCase, ABC): testing_module = testing + def setUp(self) -> None: + self.lock_pool = FakeLockPool() + super().setUp() + + async def asyncSetUp(self) -> None: + await self.lock_pool.setup() + await super().asyncSetUp() + + async def asyncTearDown(self) -> None: + await super().asyncTearDown() + await self.lock_pool.destroy() + def get_config_file_path(self): return CONFIG_FILE_PATH def get_injections(self) -> list[Union[InjectableMixin, type[InjectableMixin], str]]: injections = [ - InMemoryTransactionRepository(lock_pool=FakeLockPool()), + InMemoryTransactionRepository(lock_pool=self.lock_pool), ] # noinspection PyTypeChecker return super().get_injections() + injections From fc8baa01f00361013c673b7b1baf2cd469907f40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Garc=C3=ADa=20Prado?= Date: Thu, 12 May 2022 10:53:32 +0200 Subject: [PATCH 75/75] v0.8.0.dev1 --- .../minos/aggregate/__init__.py | 2 +- .../minos-microservice-aggregate/poetry.lock | 12 +++++------ .../pyproject.toml | 8 ++++---- .../minos/common/__init__.py | 2 +- .../minos-microservice-common/pyproject.toml | 2 +- .../minos/cqrs/__init__.py | 2 +- .../core/minos-microservice-cqrs/poetry.lock | 20 +++++++++---------- .../minos-microservice-cqrs/pyproject.toml | 8 ++++---- .../minos/networks/__init__.py | 2 +- .../minos-microservice-networks/poetry.lock | 6 +++--- .../pyproject.toml | 6 +++--- .../minos/saga/__init__.py | 2 +- .../core/minos-microservice-saga/poetry.lock | 12 +++++------ .../minos-microservice-saga/pyproject.toml | 8 ++++---- .../minos/transactions/__init__.py | 2 +- .../poetry.lock | 4 ++-- .../pyproject.toml | 2 +- .../minos/plugins/kafka/__init__.py | 2 +- .../plugins/minos-broker-kafka/poetry.lock | 12 +++++------ .../plugins/minos-broker-kafka/pyproject.toml | 6 +++--- .../minos/plugins/rabbitmq/__init__.py | 2 +- .../plugins/minos-broker-rabbitmq/poetry.lock | 12 +++++------ .../minos-broker-rabbitmq/pyproject.toml | 6 +++--- .../minos/plugins/aiopg/__init__.py | 2 +- .../plugins/minos-database-aiopg/poetry.lock | 20 +++++++++---------- .../minos-database-aiopg/pyproject.toml | 10 +++++----- .../minos/plugins/lmdb/__init__.py | 2 +- .../plugins/minos-database-lmdb/poetry.lock | 20 +++++++++---------- .../minos-database-lmdb/pyproject.toml | 6 +++--- .../minos/plugins/kong/__init__.py | 2 +- .../plugins/minos-discovery-kong/poetry.lock | 12 +++++------ .../minos-discovery-kong/pyproject.toml | 6 +++--- .../minos/plugins/minos_discovery/__init__.py | 2 +- .../plugins/minos-discovery-minos/poetry.lock | 12 +++++------ .../minos-discovery-minos/pyproject.toml | 6 +++--- .../minos/plugins/aiohttp/__init__.py | 2 +- .../plugins/minos-http-aiohttp/poetry.lock | 12 +++++------ .../plugins/minos-http-aiohttp/pyproject.toml | 6 +++--- .../minos/plugins/graphql/__init__.py | 2 +- .../plugins/minos-router-graphql/poetry.lock | 12 +++++------ .../minos-router-graphql/pyproject.toml | 6 +++--- pyproject.toml | 2 +- 42 files changed, 141 insertions(+), 141 deletions(-) diff --git a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py index a2a5f287b..b8138a7f3 100644 --- a/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py +++ b/packages/core/minos-microservice-aggregate/minos/aggregate/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .actions import ( Action, diff --git a/packages/core/minos-microservice-aggregate/poetry.lock b/packages/core/minos-microservice-aggregate/poetry.lock index 85a43b3ab..557220800 100644 --- a/packages/core/minos-microservice-aggregate/poetry.lock +++ b/packages/core/minos-microservice-aggregate/poetry.lock @@ -199,7 +199,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -221,7 +221,7 @@ url = "../minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -230,8 +230,8 @@ develop = true [package.dependencies] crontab = "^0.23.0" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -248,7 +248,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -417,7 +417,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "8e5823a430704d126e8e03fdd6ae24fc681776028184dab4f46d26fc335b10dc" +content-hash = "2ce62921d65edb5baf072ee298dcc0dc4ec0f27331411fa18422f17c5e696633" [metadata.files] aiomisc = [ diff --git a/packages/core/minos-microservice-aggregate/pyproject.toml b/packages/core/minos-microservice-aggregate/pyproject.toml index be7d0568a..9f05bad6c 100644 --- a/packages/core/minos-microservice-aggregate/pyproject.toml +++ b/packages/core/minos-microservice-aggregate/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-microservice-aggregate" -version = "0.7.0" +version = "0.8.0.dev1" description = "The Aggregate pattern of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -31,9 +31,9 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-networks = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-transactions = { version ="^0.8.0*", allow-prereleases = true } cached-property = "^1.5.2" [tool.poetry.dev-dependencies] diff --git a/packages/core/minos-microservice-common/minos/common/__init__.py b/packages/core/minos-microservice-common/minos/common/__init__.py index c0dc48674..fa59517b6 100644 --- a/packages/core/minos-microservice-common/minos/common/__init__.py +++ b/packages/core/minos-microservice-common/minos/common/__init__.py @@ -1,7 +1,7 @@ """The common core of the Minos Framework.""" __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .builders import ( BuildableMixin, diff --git a/packages/core/minos-microservice-common/pyproject.toml b/packages/core/minos-microservice-common/pyproject.toml index b98ed8919..3626903ac 100644 --- a/packages/core/minos-microservice-common/pyproject.toml +++ b/packages/core/minos-microservice-common/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" diff --git a/packages/core/minos-microservice-cqrs/minos/cqrs/__init__.py b/packages/core/minos-microservice-cqrs/minos/cqrs/__init__.py index 131612889..85ff2905f 100644 --- a/packages/core/minos-microservice-cqrs/minos/cqrs/__init__.py +++ b/packages/core/minos-microservice-cqrs/minos/cqrs/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .exceptions import ( MinosCqrsException, diff --git a/packages/core/minos-microservice-cqrs/poetry.lock b/packages/core/minos-microservice-cqrs/poetry.lock index 6bb20257b..897c18a37 100644 --- a/packages/core/minos-microservice-cqrs/poetry.lock +++ b/packages/core/minos-microservice-cqrs/poetry.lock @@ -199,7 +199,7 @@ python-versions = "*" [[package]] name = "minos-microservice-aggregate" -version = "0.7.0" +version = "0.8.0.dev1" description = "The Aggregate pattern of the Minos Framework" category = "main" optional = false @@ -208,9 +208,9 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-networks = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -218,7 +218,7 @@ url = "../minos-microservice-aggregate" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -240,7 +240,7 @@ url = "../minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -249,8 +249,8 @@ develop = true [package.dependencies] crontab = "^0.23.0" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -267,7 +267,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -436,7 +436,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "5c62e55678cac23b9ebbe1708c1693934aa83e0dbf77f2dfa0b9ff314cce9ea8" +content-hash = "9109e6567ec901704470235385fc42dfefe9342a45e23bcd2a84fbdf13df9572" [metadata.files] aiomisc = [ diff --git a/packages/core/minos-microservice-cqrs/pyproject.toml b/packages/core/minos-microservice-cqrs/pyproject.toml index 0d36d3873..b0f81b54b 100644 --- a/packages/core/minos-microservice-cqrs/pyproject.toml +++ b/packages/core/minos-microservice-cqrs/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-microservice-cqrs" -version = "0.7.0" +version = "0.8.0.dev1" description = "The CQRS pattern of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -31,9 +31,9 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-aggregate = "^0.7.0" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" +minos-microservice-aggregate = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-networks = { version ="^0.8.0*", allow-prereleases = true } [tool.poetry.dev-dependencies] minos-microservice-common = { path = "../minos-microservice-common", develop = true } diff --git a/packages/core/minos-microservice-networks/minos/networks/__init__.py b/packages/core/minos-microservice-networks/minos/networks/__init__.py index f83971e67..053bffed3 100644 --- a/packages/core/minos-microservice-networks/minos/networks/__init__.py +++ b/packages/core/minos-microservice-networks/minos/networks/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .brokers import ( REQUEST_HEADERS_CONTEXT_VAR, diff --git a/packages/core/minos-microservice-networks/poetry.lock b/packages/core/minos-microservice-networks/poetry.lock index 5da7b9525..336936445 100644 --- a/packages/core/minos-microservice-networks/poetry.lock +++ b/packages/core/minos-microservice-networks/poetry.lock @@ -199,7 +199,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -230,7 +230,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -399,7 +399,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "8512f795e0f9feca319f7751747c70047cf8521efe6c67e9eecfaf273826bdcc" +content-hash = "5b8799b6717b5f7b1f3512bfb3730b9e13d5c1eff2f4afbdb7c69eee503b2506" [metadata.files] aiomisc = [ diff --git a/packages/core/minos-microservice-networks/pyproject.toml b/packages/core/minos-microservice-networks/pyproject.toml index 96c84340a..a4d4579fd 100644 --- a/packages/core/minos-microservice-networks/pyproject.toml +++ b/packages/core/minos-microservice-networks/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -31,8 +31,8 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-transactions = { version ="^0.8.0*", allow-prereleases = true } crontab = "^0.23.0" [tool.poetry.dev-dependencies] diff --git a/packages/core/minos-microservice-saga/minos/saga/__init__.py b/packages/core/minos-microservice-saga/minos/saga/__init__.py index eec096ef9..439bf45d7 100644 --- a/packages/core/minos-microservice-saga/minos/saga/__init__.py +++ b/packages/core/minos-microservice-saga/minos/saga/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .context import ( SagaContext, diff --git a/packages/core/minos-microservice-saga/poetry.lock b/packages/core/minos-microservice-saga/poetry.lock index 85a43b3ab..557220800 100644 --- a/packages/core/minos-microservice-saga/poetry.lock +++ b/packages/core/minos-microservice-saga/poetry.lock @@ -199,7 +199,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -221,7 +221,7 @@ url = "../minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -230,8 +230,8 @@ develop = true [package.dependencies] crontab = "^0.23.0" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -248,7 +248,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -417,7 +417,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "8e5823a430704d126e8e03fdd6ae24fc681776028184dab4f46d26fc335b10dc" +content-hash = "2ce62921d65edb5baf072ee298dcc0dc4ec0f27331411fa18422f17c5e696633" [metadata.files] aiomisc = [ diff --git a/packages/core/minos-microservice-saga/pyproject.toml b/packages/core/minos-microservice-saga/pyproject.toml index e626ee563..b6c05af7b 100644 --- a/packages/core/minos-microservice-saga/pyproject.toml +++ b/packages/core/minos-microservice-saga/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-microservice-saga" -version = "0.7.0" +version = "0.8.0.dev1" description = "The SAGA pattern of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -31,9 +31,9 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-transactions = "^0.0.0" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" +minos-microservice-transactions = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-networks = { version ="^0.8.0*", allow-prereleases = true } cached-property = "^1.5.2" [tool.poetry.dev-dependencies] diff --git a/packages/core/minos-microservice-transactions/minos/transactions/__init__.py b/packages/core/minos-microservice-transactions/minos/transactions/__init__.py index 8a0ff6dcc..df6ae6ad1 100644 --- a/packages/core/minos-microservice-transactions/minos/transactions/__init__.py +++ b/packages/core/minos-microservice-transactions/minos/transactions/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0.dev1" +__version__ = "0.8.0.dev1" from .contextvars import ( TRANSACTION_CONTEXT_VAR, diff --git a/packages/core/minos-microservice-transactions/poetry.lock b/packages/core/minos-microservice-transactions/poetry.lock index 53b8b8179..0a260a881 100644 --- a/packages/core/minos-microservice-transactions/poetry.lock +++ b/packages/core/minos-microservice-transactions/poetry.lock @@ -191,7 +191,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -374,7 +374,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "4c34a5eab6efb983f4ab2f609f54e5a8475bad1de65c75cce36989757379ea2d" +content-hash = "03c42023f7d79eb7d5fd2b4b27ed86502790dfcf40be4a4656817ea203e2bd48" [metadata.files] aiomisc = [ diff --git a/packages/core/minos-microservice-transactions/pyproject.toml b/packages/core/minos-microservice-transactions/pyproject.toml index b1937eff1..a86a4bc93 100644 --- a/packages/core/minos-microservice-transactions/pyproject.toml +++ b/packages/core/minos-microservice-transactions/pyproject.toml @@ -31,7 +31,7 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true } +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } cached-property = "^1.5.2" [tool.poetry.dev-dependencies] diff --git a/packages/plugins/minos-broker-kafka/minos/plugins/kafka/__init__.py b/packages/plugins/minos-broker-kafka/minos/plugins/kafka/__init__.py index d55a2580b..189c34e81 100644 --- a/packages/plugins/minos-broker-kafka/minos/plugins/kafka/__init__.py +++ b/packages/plugins/minos-broker-kafka/minos/plugins/kafka/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .common import ( KafkaBrokerBuilderMixin, diff --git a/packages/plugins/minos-broker-kafka/poetry.lock b/packages/plugins/minos-broker-kafka/poetry.lock index 19b464717..ffc26713d 100644 --- a/packages/plugins/minos-broker-kafka/poetry.lock +++ b/packages/plugins/minos-broker-kafka/poetry.lock @@ -224,7 +224,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -246,7 +246,7 @@ url = "../../core/minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -255,8 +255,8 @@ develop = true [package.dependencies] crontab = "^0.23.0" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -273,7 +273,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -450,7 +450,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "80731a4e4a5e44c96d2c4ebf84400c9384fe6e1e8f4ef737938cb9139d14df45" +content-hash = "bad0e5e84c890ee8a2158a5a648f2461ea4a593343f19801ca481f9632471c4b" [metadata.files] aiokafka = [ diff --git a/packages/plugins/minos-broker-kafka/pyproject.toml b/packages/plugins/minos-broker-kafka/pyproject.toml index 78f14e298..2b02074cd 100644 --- a/packages/plugins/minos-broker-kafka/pyproject.toml +++ b/packages/plugins/minos-broker-kafka/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-broker-kafka" -version = "0.7.0" +version = "0.8.0.dev1" description = "The kafka plugin of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -31,8 +31,8 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-networks = { version ="^0.8.0*", allow-prereleases = true } aiokafka = "^0.7.0" cached-property = "^1.5.2" kafka-python = "^2.0.2" diff --git a/packages/plugins/minos-broker-rabbitmq/minos/plugins/rabbitmq/__init__.py b/packages/plugins/minos-broker-rabbitmq/minos/plugins/rabbitmq/__init__.py index 6c068bac7..f6a72ed6a 100644 --- a/packages/plugins/minos-broker-rabbitmq/minos/plugins/rabbitmq/__init__.py +++ b/packages/plugins/minos-broker-rabbitmq/minos/plugins/rabbitmq/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .common import ( RabbitMQBrokerBuilderMixin, diff --git a/packages/plugins/minos-broker-rabbitmq/poetry.lock b/packages/plugins/minos-broker-rabbitmq/poetry.lock index 9753477c1..523b4a64a 100644 --- a/packages/plugins/minos-broker-rabbitmq/poetry.lock +++ b/packages/plugins/minos-broker-rabbitmq/poetry.lock @@ -237,7 +237,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -259,7 +259,7 @@ url = "../../core/minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -268,8 +268,8 @@ develop = true [package.dependencies] crontab = "^0.23.0" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -286,7 +286,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -495,7 +495,7 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "273609d0cf7bd4345776c0d9b5c47d93e65c5371cd4d62fa7814673776a2ebfd" +content-hash = "ddff0c03ebde3f5a2340ae101cdb144dd47a3d5503891919d3f9a1e349212b96" [metadata.files] aio-pika = [ diff --git a/packages/plugins/minos-broker-rabbitmq/pyproject.toml b/packages/plugins/minos-broker-rabbitmq/pyproject.toml index 82fc3e60d..4da37d9fa 100644 --- a/packages/plugins/minos-broker-rabbitmq/pyproject.toml +++ b/packages/plugins/minos-broker-rabbitmq/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-broker-rabbitmq" -version = "0.7.0" +version = "0.8.0.dev1" description = "The rabbitmq plugin of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -31,8 +31,8 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-networks = { version ="^0.8.0*", allow-prereleases = true } aio-pika = "^7.1.0" [tool.poetry.dev-dependencies] diff --git a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py index ee2e6bddf..65659ca18 100644 --- a/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py +++ b/packages/plugins/minos-database-aiopg/minos/plugins/aiopg/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .clients import ( AiopgDatabaseClient, diff --git a/packages/plugins/minos-database-aiopg/poetry.lock b/packages/plugins/minos-database-aiopg/poetry.lock index 957a14237..a90b4d97e 100644 --- a/packages/plugins/minos-database-aiopg/poetry.lock +++ b/packages/plugins/minos-database-aiopg/poetry.lock @@ -222,7 +222,7 @@ python-versions = "*" [[package]] name = "minos-microservice-aggregate" -version = "0.7.0" +version = "0.8.0.dev1" description = "The Aggregate pattern of the Minos Framework" category = "main" optional = false @@ -231,9 +231,9 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-networks = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -241,7 +241,7 @@ url = "../../core/minos-microservice-aggregate" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -263,7 +263,7 @@ url = "../../core/minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -272,8 +272,8 @@ develop = true [package.dependencies] crontab = "^0.23.0" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -290,7 +290,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -467,7 +467,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "b6c6241a7b3752a3c4f8418cf5a76ae72082c76567f5b546b40fe560b2a8d7bf" +content-hash = "bfb4c5c3999d91aa5f062cf64bdda7d2906dda026cd25979473632afea1882e3" [metadata.files] aiomisc = [ diff --git a/packages/plugins/minos-database-aiopg/pyproject.toml b/packages/plugins/minos-database-aiopg/pyproject.toml index a87a0aed9..4a442b92e 100644 --- a/packages/plugins/minos-database-aiopg/pyproject.toml +++ b/packages/plugins/minos-database-aiopg/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-database-aiopg" -version = "0.7.0" +version = "0.8.0.dev1" description = "The aiopg plugin of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -31,10 +31,10 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" -minos-microservice-aggregate = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-networks = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-aggregate = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-transactions = { version ="^0.8.0*", allow-prereleases = true } aiopg = "^1.2.1" psycopg2-binary = "^2.9.3" diff --git a/packages/plugins/minos-database-lmdb/minos/plugins/lmdb/__init__.py b/packages/plugins/minos-database-lmdb/minos/plugins/lmdb/__init__.py index 9995ff1b2..ada08cd65 100644 --- a/packages/plugins/minos-database-lmdb/minos/plugins/lmdb/__init__.py +++ b/packages/plugins/minos-database-lmdb/minos/plugins/lmdb/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .clients import ( LmdbDatabaseClient, diff --git a/packages/plugins/minos-database-lmdb/poetry.lock b/packages/plugins/minos-database-lmdb/poetry.lock index 3b3747a68..95658c47b 100644 --- a/packages/plugins/minos-database-lmdb/poetry.lock +++ b/packages/plugins/minos-database-lmdb/poetry.lock @@ -207,7 +207,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -229,7 +229,7 @@ url = "../../core/minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -238,8 +238,8 @@ develop = true [package.dependencies] crontab = "^0.23.0" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -247,7 +247,7 @@ url = "../../core/minos-microservice-networks" [[package]] name = "minos-microservice-saga" -version = "0.7.0" +version = "0.8.0.dev1" description = "The SAGA pattern of the Minos Framework" category = "main" optional = false @@ -256,9 +256,9 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-networks = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -275,7 +275,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -444,7 +444,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "45f9aa2039be7f4fd22a1cb508009009e0cf0302d049e1d5201b389b56a3cbd2" +content-hash = "5443774a06b2b096d30da4dd51b8364bec46045ae9bf7612e3649cfcd865f46e" [metadata.files] aiomisc = [ diff --git a/packages/plugins/minos-database-lmdb/pyproject.toml b/packages/plugins/minos-database-lmdb/pyproject.toml index 1711db152..fd4352e4b 100644 --- a/packages/plugins/minos-database-lmdb/pyproject.toml +++ b/packages/plugins/minos-database-lmdb/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-database-lmdb" -version = "0.7.0" +version = "0.8.0.dev1" description = "The lmdb plugin of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -31,8 +31,8 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-common = "^0.7.0" -minos-microservice-saga = "^0.7.0" +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-saga = { version ="^0.8.0*", allow-prereleases = true } lmdb = "^1.2.1" [tool.poetry.dev-dependencies] diff --git a/packages/plugins/minos-discovery-kong/minos/plugins/kong/__init__.py b/packages/plugins/minos-discovery-kong/minos/plugins/kong/__init__.py index 3bbf4686d..bf907677c 100644 --- a/packages/plugins/minos-discovery-kong/minos/plugins/kong/__init__.py +++ b/packages/plugins/minos-discovery-kong/minos/plugins/kong/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .client import ( KongClient, diff --git a/packages/plugins/minos-discovery-kong/poetry.lock b/packages/plugins/minos-discovery-kong/poetry.lock index 35700283e..7c58a1f82 100644 --- a/packages/plugins/minos-discovery-kong/poetry.lock +++ b/packages/plugins/minos-discovery-kong/poetry.lock @@ -290,7 +290,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -312,7 +312,7 @@ url = "../../core/minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -321,8 +321,8 @@ develop = true [package.dependencies] crontab = "^0.23.0" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -339,7 +339,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -560,7 +560,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "1fd1295ddd1a2ed7f4f281aee37d6f3e626d45b9b2ed0f16741c0bcbb6bffec2" +content-hash = "b945cdb7e55696aec3c23d9ffaba0a1a2b85cb1522c696df1d0bae4f4c6c804c" [metadata.files] aiomisc = [ diff --git a/packages/plugins/minos-discovery-kong/pyproject.toml b/packages/plugins/minos-discovery-kong/pyproject.toml index 2bb41bfd3..d6ffec37a 100644 --- a/packages/plugins/minos-discovery-kong/pyproject.toml +++ b/packages/plugins/minos-discovery-kong/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-discovery-kong" -version = "0.7.0" +version = "0.8.0.dev1" description = "The minos-kong plugin offer an interface that permit integrate Minos Microservice with Kong API Gateway" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -32,8 +32,8 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-networks = { version ="^0.8.0*", allow-prereleases = true } httpx = "^0.22.0" pytz = "^2022.1" PyJWT = "^2.3.0" diff --git a/packages/plugins/minos-discovery-minos/minos/plugins/minos_discovery/__init__.py b/packages/plugins/minos-discovery-minos/minos/plugins/minos_discovery/__init__.py index 92662cc7c..976025a6a 100644 --- a/packages/plugins/minos-discovery-minos/minos/plugins/minos_discovery/__init__.py +++ b/packages/plugins/minos-discovery-minos/minos/plugins/minos_discovery/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .client import ( MinosDiscoveryClient, diff --git a/packages/plugins/minos-discovery-minos/poetry.lock b/packages/plugins/minos-discovery-minos/poetry.lock index f36f94e67..af929e968 100644 --- a/packages/plugins/minos-discovery-minos/poetry.lock +++ b/packages/plugins/minos-discovery-minos/poetry.lock @@ -265,7 +265,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -287,7 +287,7 @@ url = "../../core/minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -296,8 +296,8 @@ develop = true [package.dependencies] crontab = "^0.23.0" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -314,7 +314,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -511,7 +511,7 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "30dbbcc70f76be45d86eccaf18c7d459be68d8ae8c5db2a0094652f9543109d6" +content-hash = "8a823245a2af11e180acbca4de4d6a33cad657fd817f0a6f16d4c191785066e5" [metadata.files] aiohttp = [ diff --git a/packages/plugins/minos-discovery-minos/pyproject.toml b/packages/plugins/minos-discovery-minos/pyproject.toml index 6eff8678a..f8d212d44 100644 --- a/packages/plugins/minos-discovery-minos/pyproject.toml +++ b/packages/plugins/minos-discovery-minos/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-discovery-minos" -version = "0.7.0" +version = "0.8.0.dev1" description = "The minos-discovery plugin of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -31,8 +31,8 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-networks = { version ="^0.8.0*", allow-prereleases = true } aiohttp = "^3.8.1" [tool.poetry.dev-dependencies] diff --git a/packages/plugins/minos-http-aiohttp/minos/plugins/aiohttp/__init__.py b/packages/plugins/minos-http-aiohttp/minos/plugins/aiohttp/__init__.py index b4de6d65d..751a1115b 100644 --- a/packages/plugins/minos-http-aiohttp/minos/plugins/aiohttp/__init__.py +++ b/packages/plugins/minos-http-aiohttp/minos/plugins/aiohttp/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .connectors import ( AioHttpConnector, diff --git a/packages/plugins/minos-http-aiohttp/poetry.lock b/packages/plugins/minos-http-aiohttp/poetry.lock index 2055b0bd1..59428eda0 100644 --- a/packages/plugins/minos-http-aiohttp/poetry.lock +++ b/packages/plugins/minos-http-aiohttp/poetry.lock @@ -265,7 +265,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -287,7 +287,7 @@ url = "../../core/minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -296,8 +296,8 @@ develop = true [package.dependencies] crontab = "^0.23.0" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -314,7 +314,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -511,7 +511,7 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "515f6ec6af989267aeacb0d09677bd8e2fe2c7a5d885684bd999cc6b5fdb2cfc" +content-hash = "692b5f0d168d6994a0aa52062a73b19d9561d32ad84e7594c9395f0da4f0517c" [metadata.files] aiohttp = [ diff --git a/packages/plugins/minos-http-aiohttp/pyproject.toml b/packages/plugins/minos-http-aiohttp/pyproject.toml index b0914a06b..d04ebcb57 100644 --- a/packages/plugins/minos-http-aiohttp/pyproject.toml +++ b/packages/plugins/minos-http-aiohttp/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-http-aiohttp" -version = "0.7.0" +version = "0.8.0.dev1" description = "The aiohttp plugin of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -31,8 +31,8 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-networks = { version ="^0.8.0*", allow-prereleases = true } aiohttp = "^3.8.1" orjson = "^3.6.7" cached-property = "^1.5.2" diff --git a/packages/plugins/minos-router-graphql/minos/plugins/graphql/__init__.py b/packages/plugins/minos-router-graphql/minos/plugins/graphql/__init__.py index c1d9b3c4f..5333c0c54 100644 --- a/packages/plugins/minos-router-graphql/minos/plugins/graphql/__init__.py +++ b/packages/plugins/minos-router-graphql/minos/plugins/graphql/__init__.py @@ -2,7 +2,7 @@ __author__ = "Minos Framework Devs" __email__ = "hey@minos.run" -__version__ = "0.7.0" +__version__ = "0.8.0.dev1" from .builders import ( GraphQLSchemaBuilder, diff --git a/packages/plugins/minos-router-graphql/poetry.lock b/packages/plugins/minos-router-graphql/poetry.lock index fd94f92ca..bed733465 100644 --- a/packages/plugins/minos-router-graphql/poetry.lock +++ b/packages/plugins/minos-router-graphql/poetry.lock @@ -207,7 +207,7 @@ python-versions = "*" [[package]] name = "minos-microservice-common" -version = "0.7.0" +version = "0.8.0.dev1" description = "The common core of the Minos Framework" category = "main" optional = false @@ -229,7 +229,7 @@ url = "../../core/minos-microservice-common" [[package]] name = "minos-microservice-networks" -version = "0.7.0" +version = "0.8.0.dev1" description = "The networks core of the Minos Framework" category = "main" optional = false @@ -238,8 +238,8 @@ develop = true [package.dependencies] crontab = "^0.23.0" -minos-microservice-common = "^0.7.0" -minos-microservice-transactions = "^0.0.0" +minos-microservice-common = "^0.8.0*" +minos-microservice-transactions = "^0.8.0*" [package.source] type = "directory" @@ -256,7 +256,7 @@ develop = true [package.dependencies] cached-property = "^1.5.2" -minos-microservice-common = "^0.7.0*" +minos-microservice-common = "^0.8.0*" [package.source] type = "directory" @@ -433,7 +433,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,< [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "7cac9df03c35070679132bc6e26f84b73c30fedcffcd31d4caaf8c5f351a6a1f" +content-hash = "548e08209b9d3de4f60e18ba48bc94fd4ffd27671316183f897f2e53574297e9" [metadata.files] aiomisc = [ diff --git a/packages/plugins/minos-router-graphql/pyproject.toml b/packages/plugins/minos-router-graphql/pyproject.toml index 665bbecfa..3cf230555 100644 --- a/packages/plugins/minos-router-graphql/pyproject.toml +++ b/packages/plugins/minos-router-graphql/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-router-graphql" -version = "0.7.0" +version = "0.8.0.dev1" description = "The graphql plugin of the Minos Framework" readme = "README.md" repository = "https://github.com/minos-framework/minos-python" @@ -31,8 +31,8 @@ include = [ [tool.poetry.dependencies] python = "^3.9" -minos-microservice-common = "^0.7.0" -minos-microservice-networks = "^0.7.0" +minos-microservice-common = { version ="^0.8.0*", allow-prereleases = true } +minos-microservice-networks = { version ="^0.8.0*", allow-prereleases = true } graphql-core = "^3.2.0" [tool.poetry.dev-dependencies] diff --git a/pyproject.toml b/pyproject.toml index dc9684dbb..fc7de6421 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "minos-python" -version = "0.7.0" +version = "0.8.0.dev1" description = "" authors = ["Minos Framework Devs "] license = "MIT"