eventsourcing 9.3.3__py3-none-any.whl → 9.3.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of eventsourcing might be problematic. Click here for more details.
- {eventsourcing-9.3.3.dist-info → eventsourcing-9.3.4.dist-info}/METADATA +1 -1
- eventsourcing-9.3.4.dist-info/RECORD +24 -0
- eventsourcing/examples/__init__.py +0 -0
- eventsourcing/examples/aggregate1/__init__.py +0 -0
- eventsourcing/examples/aggregate1/application.py +0 -27
- eventsourcing/examples/aggregate1/domainmodel.py +0 -16
- eventsourcing/examples/aggregate1/test_application.py +0 -37
- eventsourcing/examples/aggregate2/__init__.py +0 -0
- eventsourcing/examples/aggregate2/application.py +0 -27
- eventsourcing/examples/aggregate2/domainmodel.py +0 -22
- eventsourcing/examples/aggregate2/test_application.py +0 -37
- eventsourcing/examples/aggregate3/__init__.py +0 -0
- eventsourcing/examples/aggregate3/application.py +0 -27
- eventsourcing/examples/aggregate3/domainmodel.py +0 -38
- eventsourcing/examples/aggregate3/test_application.py +0 -37
- eventsourcing/examples/aggregate4/__init__.py +0 -0
- eventsourcing/examples/aggregate4/application.py +0 -27
- eventsourcing/examples/aggregate4/domainmodel.py +0 -114
- eventsourcing/examples/aggregate4/test_application.py +0 -38
- eventsourcing/examples/aggregate5/__init__.py +0 -0
- eventsourcing/examples/aggregate5/application.py +0 -27
- eventsourcing/examples/aggregate5/domainmodel.py +0 -131
- eventsourcing/examples/aggregate5/test_application.py +0 -38
- eventsourcing/examples/aggregate6/__init__.py +0 -0
- eventsourcing/examples/aggregate6/application.py +0 -30
- eventsourcing/examples/aggregate6/domainmodel.py +0 -123
- eventsourcing/examples/aggregate6/test_application.py +0 -38
- eventsourcing/examples/aggregate6a/__init__.py +0 -0
- eventsourcing/examples/aggregate6a/application.py +0 -40
- eventsourcing/examples/aggregate6a/domainmodel.py +0 -149
- eventsourcing/examples/aggregate6a/test_application.py +0 -45
- eventsourcing/examples/aggregate7/__init__.py +0 -0
- eventsourcing/examples/aggregate7/application.py +0 -53
- eventsourcing/examples/aggregate7/domainmodel.py +0 -142
- eventsourcing/examples/aggregate7/persistence.py +0 -57
- eventsourcing/examples/aggregate7/test_application.py +0 -45
- eventsourcing/examples/aggregate7/test_compression_and_encryption.py +0 -45
- eventsourcing/examples/aggregate7/test_snapshotting_intervals.py +0 -67
- eventsourcing/examples/aggregate7a/__init__.py +0 -0
- eventsourcing/examples/aggregate7a/application.py +0 -56
- eventsourcing/examples/aggregate7a/domainmodel.py +0 -168
- eventsourcing/examples/aggregate7a/test_application.py +0 -46
- eventsourcing/examples/aggregate7a/test_compression_and_encryption.py +0 -45
- eventsourcing/examples/aggregate8/__init__.py +0 -0
- eventsourcing/examples/aggregate8/application.py +0 -47
- eventsourcing/examples/aggregate8/domainmodel.py +0 -71
- eventsourcing/examples/aggregate8/persistence.py +0 -57
- eventsourcing/examples/aggregate8/test_application.py +0 -44
- eventsourcing/examples/aggregate8/test_compression_and_encryption.py +0 -44
- eventsourcing/examples/aggregate8/test_snapshotting_intervals.py +0 -38
- eventsourcing/examples/bankaccounts/__init__.py +0 -0
- eventsourcing/examples/bankaccounts/application.py +0 -70
- eventsourcing/examples/bankaccounts/domainmodel.py +0 -56
- eventsourcing/examples/bankaccounts/test.py +0 -173
- eventsourcing/examples/cargoshipping/__init__.py +0 -0
- eventsourcing/examples/cargoshipping/application.py +0 -126
- eventsourcing/examples/cargoshipping/domainmodel.py +0 -330
- eventsourcing/examples/cargoshipping/interface.py +0 -143
- eventsourcing/examples/cargoshipping/test.py +0 -231
- eventsourcing/examples/contentmanagement/__init__.py +0 -0
- eventsourcing/examples/contentmanagement/application.py +0 -118
- eventsourcing/examples/contentmanagement/domainmodel.py +0 -69
- eventsourcing/examples/contentmanagement/test.py +0 -180
- eventsourcing/examples/contentmanagement/utils.py +0 -26
- eventsourcing/examples/contentmanagementsystem/__init__.py +0 -0
- eventsourcing/examples/contentmanagementsystem/application.py +0 -54
- eventsourcing/examples/contentmanagementsystem/postgres.py +0 -17
- eventsourcing/examples/contentmanagementsystem/sqlite.py +0 -17
- eventsourcing/examples/contentmanagementsystem/system.py +0 -14
- eventsourcing/examples/contentmanagementsystem/test_system.py +0 -180
- eventsourcing/examples/searchablecontent/__init__.py +0 -0
- eventsourcing/examples/searchablecontent/application.py +0 -45
- eventsourcing/examples/searchablecontent/persistence.py +0 -23
- eventsourcing/examples/searchablecontent/postgres.py +0 -118
- eventsourcing/examples/searchablecontent/sqlite.py +0 -136
- eventsourcing/examples/searchablecontent/test_application.py +0 -110
- eventsourcing/examples/searchablecontent/test_recorder.py +0 -68
- eventsourcing/examples/searchabletimestamps/__init__.py +0 -0
- eventsourcing/examples/searchabletimestamps/application.py +0 -32
- eventsourcing/examples/searchabletimestamps/persistence.py +0 -20
- eventsourcing/examples/searchabletimestamps/postgres.py +0 -110
- eventsourcing/examples/searchabletimestamps/sqlite.py +0 -99
- eventsourcing/examples/searchabletimestamps/test_searchabletimestamps.py +0 -94
- eventsourcing/examples/test_invoice.py +0 -176
- eventsourcing/examples/test_parking_lot.py +0 -206
- eventsourcing/tests/application_tests/__init__.py +0 -0
- eventsourcing/tests/application_tests/test_application_with_automatic_snapshotting.py +0 -55
- eventsourcing/tests/application_tests/test_application_with_popo.py +0 -22
- eventsourcing/tests/application_tests/test_application_with_postgres.py +0 -75
- eventsourcing/tests/application_tests/test_application_with_sqlite.py +0 -72
- eventsourcing/tests/application_tests/test_cache.py +0 -134
- eventsourcing/tests/application_tests/test_event_sourced_log.py +0 -162
- eventsourcing/tests/application_tests/test_notificationlog.py +0 -232
- eventsourcing/tests/application_tests/test_notificationlogreader.py +0 -126
- eventsourcing/tests/application_tests/test_processapplication.py +0 -110
- eventsourcing/tests/application_tests/test_processingpolicy.py +0 -109
- eventsourcing/tests/application_tests/test_repository.py +0 -504
- eventsourcing/tests/application_tests/test_snapshotting.py +0 -68
- eventsourcing/tests/application_tests/test_upcasting.py +0 -459
- eventsourcing/tests/docs_tests/__init__.py +0 -0
- eventsourcing/tests/docs_tests/test_docs.py +0 -293
- eventsourcing/tests/domain_tests/__init__.py +0 -0
- eventsourcing/tests/domain_tests/test_aggregate.py +0 -1200
- eventsourcing/tests/domain_tests/test_aggregate_decorators.py +0 -1604
- eventsourcing/tests/domain_tests/test_domainevent.py +0 -80
- eventsourcing/tests/interface_tests/__init__.py +0 -0
- eventsourcing/tests/interface_tests/test_remotenotificationlog.py +0 -258
- eventsourcing/tests/persistence_tests/__init__.py +0 -0
- eventsourcing/tests/persistence_tests/test_aes.py +0 -93
- eventsourcing/tests/persistence_tests/test_connection_pool.py +0 -722
- eventsourcing/tests/persistence_tests/test_eventstore.py +0 -72
- eventsourcing/tests/persistence_tests/test_infrastructure_factory.py +0 -21
- eventsourcing/tests/persistence_tests/test_mapper.py +0 -113
- eventsourcing/tests/persistence_tests/test_noninterleaving_notification_ids.py +0 -69
- eventsourcing/tests/persistence_tests/test_popo.py +0 -124
- eventsourcing/tests/persistence_tests/test_postgres.py +0 -1120
- eventsourcing/tests/persistence_tests/test_sqlite.py +0 -348
- eventsourcing/tests/persistence_tests/test_transcoder.py +0 -44
- eventsourcing/tests/system_tests/__init__.py +0 -0
- eventsourcing/tests/system_tests/test_runner.py +0 -935
- eventsourcing/tests/system_tests/test_system.py +0 -284
- eventsourcing/tests/utils_tests/__init__.py +0 -0
- eventsourcing/tests/utils_tests/test_utils.py +0 -226
- eventsourcing-9.3.3.dist-info/RECORD +0 -145
- {eventsourcing-9.3.3.dist-info → eventsourcing-9.3.4.dist-info}/AUTHORS +0 -0
- {eventsourcing-9.3.3.dist-info → eventsourcing-9.3.4.dist-info}/LICENSE +0 -0
- {eventsourcing-9.3.3.dist-info → eventsourcing-9.3.4.dist-info}/WHEEL +0 -0
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from unittest import TestCase
|
|
3
|
-
|
|
4
|
-
from eventsourcing.postgres import PostgresDatastore
|
|
5
|
-
from eventsourcing.tests.application import (
|
|
6
|
-
TIMEIT_FACTOR,
|
|
7
|
-
ApplicationTestCase,
|
|
8
|
-
ExampleApplicationTestCase,
|
|
9
|
-
)
|
|
10
|
-
from eventsourcing.tests.postgres_utils import drop_postgres_table
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class WithPostgres(TestCase):
|
|
14
|
-
timeit_number = 5 * TIMEIT_FACTOR
|
|
15
|
-
expected_factory_topic = "eventsourcing.postgres:Factory"
|
|
16
|
-
|
|
17
|
-
def setUp(self) -> None:
|
|
18
|
-
super().setUp()
|
|
19
|
-
|
|
20
|
-
os.environ["PERSISTENCE_MODULE"] = "eventsourcing.postgres"
|
|
21
|
-
os.environ["CREATE_TABLE"] = "y"
|
|
22
|
-
os.environ["POSTGRES_DBNAME"] = "eventsourcing"
|
|
23
|
-
os.environ["POSTGRES_HOST"] = "127.0.0.1"
|
|
24
|
-
os.environ["POSTGRES_PORT"] = "5432"
|
|
25
|
-
os.environ["POSTGRES_USER"] = "eventsourcing"
|
|
26
|
-
os.environ["POSTGRES_PASSWORD"] = "eventsourcing" # noqa: S105
|
|
27
|
-
os.environ["POSTGRES_SCHEMA"] = "public"
|
|
28
|
-
|
|
29
|
-
db = PostgresDatastore(
|
|
30
|
-
os.getenv("POSTGRES_DBNAME"),
|
|
31
|
-
os.getenv("POSTGRES_HOST"),
|
|
32
|
-
os.getenv("POSTGRES_PORT"),
|
|
33
|
-
os.getenv("POSTGRES_USER"),
|
|
34
|
-
os.getenv("POSTGRES_PASSWORD"),
|
|
35
|
-
)
|
|
36
|
-
drop_postgres_table(db, "public.bankaccounts_events")
|
|
37
|
-
drop_postgres_table(db, "public.bankaccounts_snapshots")
|
|
38
|
-
db.close()
|
|
39
|
-
|
|
40
|
-
def tearDown(self) -> None:
|
|
41
|
-
db = PostgresDatastore(
|
|
42
|
-
os.getenv("POSTGRES_DBNAME"),
|
|
43
|
-
os.getenv("POSTGRES_HOST"),
|
|
44
|
-
os.getenv("POSTGRES_PORT"),
|
|
45
|
-
os.getenv("POSTGRES_USER"),
|
|
46
|
-
os.getenv("POSTGRES_PASSWORD"),
|
|
47
|
-
)
|
|
48
|
-
drop_postgres_table(db, "public.bankaccounts_events")
|
|
49
|
-
drop_postgres_table(db, "public.bankaccounts_snapshots")
|
|
50
|
-
|
|
51
|
-
del os.environ["PERSISTENCE_MODULE"]
|
|
52
|
-
del os.environ["CREATE_TABLE"]
|
|
53
|
-
del os.environ["POSTGRES_DBNAME"]
|
|
54
|
-
del os.environ["POSTGRES_HOST"]
|
|
55
|
-
del os.environ["POSTGRES_PORT"]
|
|
56
|
-
del os.environ["POSTGRES_USER"]
|
|
57
|
-
del os.environ["POSTGRES_PASSWORD"]
|
|
58
|
-
del os.environ["POSTGRES_SCHEMA"]
|
|
59
|
-
db.close()
|
|
60
|
-
|
|
61
|
-
super().tearDown()
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
class TestApplicationWithPostgres(ApplicationTestCase, WithPostgres):
|
|
65
|
-
pass
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class TestExampleApplicationWithPostgres(ExampleApplicationTestCase, WithPostgres):
|
|
69
|
-
timeit_number = 5 * TIMEIT_FACTOR
|
|
70
|
-
expected_factory_topic = "eventsourcing.postgres:Factory"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
del ApplicationTestCase
|
|
74
|
-
del ExampleApplicationTestCase
|
|
75
|
-
del WithPostgres
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from unittest import TestCase
|
|
3
|
-
|
|
4
|
-
from eventsourcing.tests.application import (
|
|
5
|
-
TIMEIT_FACTOR,
|
|
6
|
-
ApplicationTestCase,
|
|
7
|
-
ExampleApplicationTestCase,
|
|
8
|
-
)
|
|
9
|
-
from eventsourcing.tests.persistence import tmpfile_uris
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class WithSQLiteFile(TestCase):
|
|
13
|
-
timeit_number = 30 * TIMEIT_FACTOR
|
|
14
|
-
expected_factory_topic = "eventsourcing.sqlite:Factory"
|
|
15
|
-
|
|
16
|
-
def setUp(self) -> None:
|
|
17
|
-
super().setUp()
|
|
18
|
-
self.uris = tmpfile_uris()
|
|
19
|
-
# self.db_uri = next(self.uris)
|
|
20
|
-
|
|
21
|
-
os.environ["PERSISTENCE_MODULE"] = "eventsourcing.sqlite"
|
|
22
|
-
os.environ["CREATE_TABLE"] = "y"
|
|
23
|
-
os.environ["SQLITE_DBNAME"] = next(self.uris)
|
|
24
|
-
|
|
25
|
-
def tearDown(self) -> None:
|
|
26
|
-
del os.environ["PERSISTENCE_MODULE"]
|
|
27
|
-
del os.environ["CREATE_TABLE"]
|
|
28
|
-
del os.environ["SQLITE_DBNAME"]
|
|
29
|
-
super().tearDown()
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class WithSQLiteInMemory(TestCase):
|
|
33
|
-
timeit_number = 30 * TIMEIT_FACTOR
|
|
34
|
-
expected_factory_topic = "eventsourcing.sqlite:Factory"
|
|
35
|
-
|
|
36
|
-
def setUp(self) -> None:
|
|
37
|
-
super().setUp()
|
|
38
|
-
os.environ["PERSISTENCE_MODULE"] = "eventsourcing.sqlite"
|
|
39
|
-
os.environ["CREATE_TABLE"] = "y"
|
|
40
|
-
os.environ["SQLITE_DBNAME"] = "file:memory:?mode=memory&cache=shared"
|
|
41
|
-
|
|
42
|
-
def tearDown(self) -> None:
|
|
43
|
-
del os.environ["PERSISTENCE_MODULE"]
|
|
44
|
-
del os.environ["CREATE_TABLE"]
|
|
45
|
-
del os.environ["SQLITE_DBNAME"]
|
|
46
|
-
super().tearDown()
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class TestApplicationWithSQLiteFile(ApplicationTestCase, WithSQLiteFile):
|
|
50
|
-
pass
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
# class TestApplicationWithSQLiteInMemory(TestApplication, WithSQLiteInMemory):
|
|
54
|
-
# pass
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
class TestExampleApplicationWithSQLiteFile(ExampleApplicationTestCase, WithSQLiteFile):
|
|
58
|
-
timeit_number = 30 * TIMEIT_FACTOR
|
|
59
|
-
expected_factory_topic = "eventsourcing.sqlite:Factory"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class TestExampleApplicationWithSQLiteInMemory(
|
|
63
|
-
ExampleApplicationTestCase, WithSQLiteInMemory
|
|
64
|
-
):
|
|
65
|
-
timeit_number = 30 * TIMEIT_FACTOR
|
|
66
|
-
expected_factory_topic = "eventsourcing.sqlite:Factory"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
del ApplicationTestCase
|
|
70
|
-
del ExampleApplicationTestCase
|
|
71
|
-
del WithSQLiteFile
|
|
72
|
-
del WithSQLiteInMemory
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
from unittest import TestCase
|
|
2
|
-
|
|
3
|
-
from eventsourcing.application import Cache, LRUCache
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class TestCache(TestCase):
|
|
7
|
-
def test_put_get(self):
|
|
8
|
-
cache = Cache()
|
|
9
|
-
|
|
10
|
-
with self.assertRaises(KeyError):
|
|
11
|
-
cache.get(1)
|
|
12
|
-
|
|
13
|
-
cache.put(1, 1)
|
|
14
|
-
self.assertEqual(cache.get(1), 1)
|
|
15
|
-
|
|
16
|
-
cache.put(2, 2)
|
|
17
|
-
self.assertEqual(1, cache.get(1))
|
|
18
|
-
self.assertEqual(2, cache.get(2))
|
|
19
|
-
|
|
20
|
-
cache.put(3, 3)
|
|
21
|
-
self.assertEqual(3, cache.get(3))
|
|
22
|
-
self.assertEqual(2, cache.get(2))
|
|
23
|
-
self.assertEqual(1, cache.get(1))
|
|
24
|
-
|
|
25
|
-
cache.put(1, 2)
|
|
26
|
-
self.assertEqual(2, cache.get(1))
|
|
27
|
-
cache.put(1, 3)
|
|
28
|
-
self.assertEqual(3, cache.get(1))
|
|
29
|
-
|
|
30
|
-
cache.get(1, evict=True)
|
|
31
|
-
with self.assertRaises(KeyError):
|
|
32
|
-
cache.get(1)
|
|
33
|
-
|
|
34
|
-
cache.put(1, None)
|
|
35
|
-
with self.assertRaises(KeyError):
|
|
36
|
-
cache.get(1)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class TestLRUCache(TestCase):
|
|
40
|
-
def test_put_get(self):
|
|
41
|
-
cache = LRUCache(maxsize=2)
|
|
42
|
-
|
|
43
|
-
with self.assertRaises(KeyError):
|
|
44
|
-
cache.get(1)
|
|
45
|
-
|
|
46
|
-
evicted = cache.put(1, 1)
|
|
47
|
-
self.assertEqual(evicted, (None, None))
|
|
48
|
-
self.assertEqual(cache.get(1), 1)
|
|
49
|
-
|
|
50
|
-
evicted = cache.put(2, 2)
|
|
51
|
-
self.assertEqual(evicted, (None, None))
|
|
52
|
-
self.assertEqual(1, cache.get(1))
|
|
53
|
-
self.assertEqual(2, cache.get(2))
|
|
54
|
-
|
|
55
|
-
evicted = cache.put(3, 3)
|
|
56
|
-
self.assertEqual(evicted, (1, 1))
|
|
57
|
-
|
|
58
|
-
self.assertEqual(3, cache.get(3))
|
|
59
|
-
self.assertEqual(2, cache.get(2))
|
|
60
|
-
|
|
61
|
-
cache.put(1, 1)
|
|
62
|
-
self.assertEqual(1, cache.get(1))
|
|
63
|
-
cache.put(1, 2)
|
|
64
|
-
self.assertEqual(2, cache.get(1))
|
|
65
|
-
cache.put(1, 3)
|
|
66
|
-
self.assertEqual(3, cache.get(1))
|
|
67
|
-
|
|
68
|
-
def test_put_get_evict_recent(self):
|
|
69
|
-
cache = LRUCache(maxsize=3)
|
|
70
|
-
|
|
71
|
-
cache.put(1, 1)
|
|
72
|
-
self.assertEqual(1, cache.get(1))
|
|
73
|
-
self.assertEqual(1, cache.get(1))
|
|
74
|
-
self.assertEqual(1, cache.get(1, evict=True))
|
|
75
|
-
|
|
76
|
-
with self.assertRaises(KeyError):
|
|
77
|
-
self.assertEqual(1, cache.get(1))
|
|
78
|
-
|
|
79
|
-
cache.put(1, 1)
|
|
80
|
-
cache.put(2, 2)
|
|
81
|
-
cache.put(3, 3)
|
|
82
|
-
evicted = cache.put(4, 4)
|
|
83
|
-
self.assertEqual(evicted, (1, 1))
|
|
84
|
-
|
|
85
|
-
self.assertEqual(3, cache.get(3, evict=True))
|
|
86
|
-
|
|
87
|
-
evicted = cache.put(5, 5)
|
|
88
|
-
self.assertEqual(evicted, (None, None))
|
|
89
|
-
|
|
90
|
-
evicted = cache.put(6, 6)
|
|
91
|
-
self.assertEqual(evicted, (2, 2))
|
|
92
|
-
|
|
93
|
-
evicted = cache.put(7, 7)
|
|
94
|
-
self.assertEqual(evicted, (4, 4))
|
|
95
|
-
|
|
96
|
-
def test_put_get_evict_oldest(self):
|
|
97
|
-
cache = LRUCache(maxsize=3)
|
|
98
|
-
|
|
99
|
-
cache.put(1, 1)
|
|
100
|
-
cache.put(2, 2)
|
|
101
|
-
cache.put(3, 3)
|
|
102
|
-
self.assertEqual(1, cache.get(1, evict=True))
|
|
103
|
-
|
|
104
|
-
evicted = cache.put(4, 4)
|
|
105
|
-
self.assertEqual(evicted, (None, None))
|
|
106
|
-
|
|
107
|
-
evicted = cache.put(5, 5)
|
|
108
|
-
self.assertEqual(evicted, (2, 2))
|
|
109
|
-
|
|
110
|
-
evicted = cache.put(6, 6)
|
|
111
|
-
self.assertEqual(evicted, (3, 3))
|
|
112
|
-
|
|
113
|
-
evicted = cache.put(7, 7)
|
|
114
|
-
self.assertEqual(evicted, (4, 4))
|
|
115
|
-
|
|
116
|
-
def test_put_get_evict_newest(self):
|
|
117
|
-
cache = LRUCache(maxsize=3)
|
|
118
|
-
|
|
119
|
-
cache.put(1, 1)
|
|
120
|
-
cache.put(2, 2)
|
|
121
|
-
cache.put(3, 3)
|
|
122
|
-
self.assertEqual(3, cache.get(3, evict=True))
|
|
123
|
-
|
|
124
|
-
evicted = cache.put(4, 4)
|
|
125
|
-
self.assertEqual(evicted, (None, None))
|
|
126
|
-
|
|
127
|
-
evicted = cache.put(5, 5)
|
|
128
|
-
self.assertEqual(evicted, (1, 1))
|
|
129
|
-
|
|
130
|
-
evicted = cache.put(6, 6)
|
|
131
|
-
self.assertEqual(evicted, (2, 2))
|
|
132
|
-
|
|
133
|
-
evicted = cache.put(7, 7)
|
|
134
|
-
self.assertEqual(evicted, (4, 4))
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
from unittest import TestCase
|
|
5
|
-
from uuid import NAMESPACE_URL, UUID, uuid4, uuid5
|
|
6
|
-
|
|
7
|
-
from eventsourcing.application import Application, EventSourcedLog
|
|
8
|
-
from eventsourcing.domain import Aggregate, DomainEvent
|
|
9
|
-
from eventsourcing.persistence import (
|
|
10
|
-
DatetimeAsISO,
|
|
11
|
-
DecimalAsStr,
|
|
12
|
-
EventStore,
|
|
13
|
-
JSONTranscoder,
|
|
14
|
-
Mapper,
|
|
15
|
-
UUIDAsHex,
|
|
16
|
-
)
|
|
17
|
-
from eventsourcing.popo import POPOAggregateRecorder
|
|
18
|
-
|
|
19
|
-
if TYPE_CHECKING: # pragma: nocover
|
|
20
|
-
from eventsourcing.utils import EnvType
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class TestEventSourcedLog(TestCase):
|
|
24
|
-
def test_logging_aggregate_ids(self) -> None:
|
|
25
|
-
class LoggedID(DomainEvent):
|
|
26
|
-
aggregate_id: UUID
|
|
27
|
-
|
|
28
|
-
transcoder = JSONTranscoder()
|
|
29
|
-
transcoder.register(UUIDAsHex())
|
|
30
|
-
transcoder.register(DecimalAsStr())
|
|
31
|
-
transcoder.register(DatetimeAsISO())
|
|
32
|
-
|
|
33
|
-
event_recorder = POPOAggregateRecorder()
|
|
34
|
-
event_store = EventStore(
|
|
35
|
-
mapper=Mapper(transcoder=transcoder),
|
|
36
|
-
recorder=event_recorder,
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
log: EventSourcedLog[LoggedID] = EventSourcedLog(
|
|
40
|
-
events=event_store,
|
|
41
|
-
originator_id=uuid5(NAMESPACE_URL, "/aggregates"),
|
|
42
|
-
logged_cls=LoggedID,
|
|
43
|
-
)
|
|
44
|
-
id1 = uuid4()
|
|
45
|
-
id2 = uuid4()
|
|
46
|
-
id3 = uuid4()
|
|
47
|
-
|
|
48
|
-
self.assertEqual(log.get_first(), None)
|
|
49
|
-
self.assertEqual(log.get_last(), None)
|
|
50
|
-
logged = log.trigger_event(aggregate_id=id1)
|
|
51
|
-
event_store.put([logged])
|
|
52
|
-
first = log.get_first()
|
|
53
|
-
assert first
|
|
54
|
-
self.assertEqual(first.aggregate_id, id1)
|
|
55
|
-
last = log.get_last()
|
|
56
|
-
assert last
|
|
57
|
-
self.assertEqual(last.aggregate_id, id1)
|
|
58
|
-
logged = log.trigger_event(aggregate_id=id2)
|
|
59
|
-
event_store.put([logged])
|
|
60
|
-
last = log.get_last()
|
|
61
|
-
assert last
|
|
62
|
-
self.assertEqual(last.aggregate_id, id2)
|
|
63
|
-
logged = log.trigger_event(aggregate_id=id3, next_originator_version=3)
|
|
64
|
-
event_store.put([logged])
|
|
65
|
-
last = log.get_last()
|
|
66
|
-
assert last
|
|
67
|
-
self.assertEqual(last.aggregate_id, id3)
|
|
68
|
-
first = log.get_first()
|
|
69
|
-
assert first
|
|
70
|
-
self.assertEqual(first.aggregate_id, id1)
|
|
71
|
-
|
|
72
|
-
ids = [e.aggregate_id for e in log.get()]
|
|
73
|
-
self.assertEqual(ids, [id1, id2, id3])
|
|
74
|
-
|
|
75
|
-
ids = [e.aggregate_id for e in log.get(gt=1)]
|
|
76
|
-
self.assertEqual(ids, [id2, id3])
|
|
77
|
-
|
|
78
|
-
ids = [e.aggregate_id for e in log.get(lte=2)]
|
|
79
|
-
self.assertEqual(ids, [id1, id2])
|
|
80
|
-
|
|
81
|
-
ids = [e.aggregate_id for e in log.get(limit=1)]
|
|
82
|
-
self.assertEqual(ids, [id1])
|
|
83
|
-
|
|
84
|
-
ids = [e.aggregate_id for e in log.get(desc=True)]
|
|
85
|
-
self.assertEqual(ids, [id3, id2, id1])
|
|
86
|
-
|
|
87
|
-
def test_with_application(self) -> None:
|
|
88
|
-
class LoggedID(DomainEvent):
|
|
89
|
-
aggregate_id: UUID
|
|
90
|
-
|
|
91
|
-
class MyApplication(Application):
|
|
92
|
-
def __init__(self, env: EnvType | None = None) -> None:
|
|
93
|
-
super().__init__(env=env)
|
|
94
|
-
self.aggregate_log = EventSourcedLog(
|
|
95
|
-
events=self.events,
|
|
96
|
-
originator_id=uuid5(NAMESPACE_URL, "/aggregates"),
|
|
97
|
-
logged_cls=LoggedID,
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
def create_aggregate(self) -> UUID:
|
|
101
|
-
aggregate = Aggregate()
|
|
102
|
-
logged_id = self.aggregate_log.trigger_event(aggregate_id=aggregate.id)
|
|
103
|
-
self.save(aggregate, logged_id)
|
|
104
|
-
return aggregate.id
|
|
105
|
-
|
|
106
|
-
app = MyApplication()
|
|
107
|
-
|
|
108
|
-
self.assertEqual(app.aggregate_log.get_last(), None)
|
|
109
|
-
|
|
110
|
-
aggregate1_id = app.create_aggregate()
|
|
111
|
-
last = app.aggregate_log.get_last()
|
|
112
|
-
assert last
|
|
113
|
-
self.assertEqual(last.aggregate_id, aggregate1_id)
|
|
114
|
-
|
|
115
|
-
aggregate2_id = app.create_aggregate()
|
|
116
|
-
last = app.aggregate_log.get_last()
|
|
117
|
-
assert last
|
|
118
|
-
self.assertEqual(last.aggregate_id, aggregate2_id)
|
|
119
|
-
|
|
120
|
-
aggregate_ids = [i.aggregate_id for i in app.aggregate_log.get()]
|
|
121
|
-
self.assertEqual(aggregate_ids, [aggregate1_id, aggregate2_id])
|
|
122
|
-
|
|
123
|
-
def test_subclasses(self) -> None:
|
|
124
|
-
transcoder = JSONTranscoder()
|
|
125
|
-
transcoder.register(UUIDAsHex())
|
|
126
|
-
transcoder.register(DecimalAsStr())
|
|
127
|
-
transcoder.register(DatetimeAsISO())
|
|
128
|
-
|
|
129
|
-
event_recorder = POPOAggregateRecorder()
|
|
130
|
-
event_store = EventStore(
|
|
131
|
-
mapper=Mapper(transcoder=transcoder),
|
|
132
|
-
recorder=event_recorder,
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
class TransactionLogEvent(DomainEvent):
|
|
136
|
-
pass
|
|
137
|
-
|
|
138
|
-
class AccountCredited(TransactionLogEvent):
|
|
139
|
-
pass
|
|
140
|
-
|
|
141
|
-
class AccountDebited(TransactionLogEvent):
|
|
142
|
-
pass
|
|
143
|
-
|
|
144
|
-
# Subclass EventSourcedLog.
|
|
145
|
-
class TransactionLog(EventSourcedLog[TransactionLogEvent]):
|
|
146
|
-
def account_credited(self) -> AccountCredited:
|
|
147
|
-
return self._trigger_event(logged_cls=AccountCredited)
|
|
148
|
-
|
|
149
|
-
def account_debited(self) -> AccountDebited:
|
|
150
|
-
return self._trigger_event(logged_cls=AccountDebited)
|
|
151
|
-
|
|
152
|
-
transaction_log = TransactionLog(
|
|
153
|
-
events=event_store,
|
|
154
|
-
originator_id=uuid5(NAMESPACE_URL, "/aggregates"),
|
|
155
|
-
logged_cls=TransactionLogEvent,
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
account_credited = transaction_log.account_credited()
|
|
159
|
-
self.assertIsInstance(account_credited, AccountCredited)
|
|
160
|
-
|
|
161
|
-
account_debited = transaction_log.account_debited()
|
|
162
|
-
self.assertIsInstance(account_debited, AccountDebited)
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
from unittest.case import TestCase
|
|
2
|
-
from uuid import uuid4
|
|
3
|
-
|
|
4
|
-
from eventsourcing.application import LocalNotificationLog
|
|
5
|
-
from eventsourcing.persistence import StoredEvent
|
|
6
|
-
from eventsourcing.sqlite import SQLiteApplicationRecorder, SQLiteDatastore
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class TestNotificationLog(TestCase):
|
|
10
|
-
def test_get_section(self):
|
|
11
|
-
recorder = SQLiteApplicationRecorder(SQLiteDatastore(":memory:"))
|
|
12
|
-
recorder.create_table()
|
|
13
|
-
|
|
14
|
-
# Construct notification log.
|
|
15
|
-
notification_log = LocalNotificationLog(recorder, section_size=5)
|
|
16
|
-
|
|
17
|
-
# Get the "current" section of log.
|
|
18
|
-
section = notification_log["1,10"]
|
|
19
|
-
self.assertEqual(len(section.items), 0) # event notifications
|
|
20
|
-
self.assertEqual(section.id, None)
|
|
21
|
-
self.assertEqual(section.next_id, None)
|
|
22
|
-
|
|
23
|
-
# Write 5 events.
|
|
24
|
-
originator_id = uuid4()
|
|
25
|
-
for i in range(5):
|
|
26
|
-
stored_event = StoredEvent(
|
|
27
|
-
originator_id=originator_id,
|
|
28
|
-
originator_version=i,
|
|
29
|
-
topic="topic",
|
|
30
|
-
state=b"state",
|
|
31
|
-
)
|
|
32
|
-
recorder.insert_events([stored_event])
|
|
33
|
-
|
|
34
|
-
# Get the "head" section of log.
|
|
35
|
-
section = notification_log["1,10"]
|
|
36
|
-
self.assertEqual(len(section.items), 5) # event notifications
|
|
37
|
-
self.assertEqual(section.items[0].id, 1)
|
|
38
|
-
self.assertEqual(section.items[1].id, 2)
|
|
39
|
-
self.assertEqual(section.items[2].id, 3)
|
|
40
|
-
self.assertEqual(section.items[3].id, 4)
|
|
41
|
-
self.assertEqual(section.items[4].id, 5)
|
|
42
|
-
self.assertEqual(section.id, "1,5")
|
|
43
|
-
self.assertEqual(section.next_id, "6,10")
|
|
44
|
-
|
|
45
|
-
# Get the "1,5" section of log.
|
|
46
|
-
section = notification_log["1,5"]
|
|
47
|
-
self.assertEqual(len(section.items), 5) # event notifications
|
|
48
|
-
self.assertEqual(section.items[0].id, 1)
|
|
49
|
-
self.assertEqual(section.items[1].id, 2)
|
|
50
|
-
self.assertEqual(section.items[2].id, 3)
|
|
51
|
-
self.assertEqual(section.items[3].id, 4)
|
|
52
|
-
self.assertEqual(section.items[4].id, 5)
|
|
53
|
-
self.assertEqual(section.id, "1,5")
|
|
54
|
-
self.assertEqual(section.next_id, "6,10")
|
|
55
|
-
|
|
56
|
-
# Get the next section of log.
|
|
57
|
-
section = notification_log["6,10"]
|
|
58
|
-
self.assertEqual(len(section.items), 0) # event notifications
|
|
59
|
-
self.assertEqual(section.id, None)
|
|
60
|
-
self.assertEqual(section.next_id, None)
|
|
61
|
-
|
|
62
|
-
# Write 4 events.
|
|
63
|
-
originator_id = uuid4()
|
|
64
|
-
for i in range(4):
|
|
65
|
-
stored_event = StoredEvent(
|
|
66
|
-
originator_id=originator_id,
|
|
67
|
-
originator_version=i,
|
|
68
|
-
topic="topic",
|
|
69
|
-
state=b"state",
|
|
70
|
-
)
|
|
71
|
-
recorder.insert_events([stored_event])
|
|
72
|
-
|
|
73
|
-
# Get the next section of log.
|
|
74
|
-
section = notification_log["6,10"]
|
|
75
|
-
self.assertEqual(len(section.items), 4) # event notifications
|
|
76
|
-
self.assertEqual(section.items[0].id, 6)
|
|
77
|
-
self.assertEqual(section.items[1].id, 7)
|
|
78
|
-
self.assertEqual(section.items[2].id, 8)
|
|
79
|
-
self.assertEqual(section.items[3].id, 9)
|
|
80
|
-
self.assertEqual(section.id, "6,9")
|
|
81
|
-
self.assertEqual(section.next_id, None)
|
|
82
|
-
|
|
83
|
-
# Start at non-regular section start.
|
|
84
|
-
section = notification_log["3,7"]
|
|
85
|
-
self.assertEqual(len(section.items), 5) # event notifications
|
|
86
|
-
self.assertEqual(section.items[0].id, 3)
|
|
87
|
-
self.assertEqual(section.items[1].id, 4)
|
|
88
|
-
self.assertEqual(section.items[2].id, 5)
|
|
89
|
-
self.assertEqual(section.items[3].id, 6)
|
|
90
|
-
self.assertEqual(section.items[4].id, 7)
|
|
91
|
-
self.assertEqual(section.id, "3,7")
|
|
92
|
-
self.assertEqual(section.next_id, "8,12")
|
|
93
|
-
|
|
94
|
-
# Notification log limits section size.
|
|
95
|
-
section = notification_log["3,10"]
|
|
96
|
-
self.assertEqual(len(section.items), 5) # event notifications
|
|
97
|
-
self.assertEqual(section.items[0].id, 3)
|
|
98
|
-
self.assertEqual(section.items[1].id, 4)
|
|
99
|
-
self.assertEqual(section.items[2].id, 5)
|
|
100
|
-
self.assertEqual(section.items[3].id, 6)
|
|
101
|
-
self.assertEqual(section.items[4].id, 7)
|
|
102
|
-
self.assertEqual(section.id, "3,7")
|
|
103
|
-
self.assertEqual(section.next_id, "8,12")
|
|
104
|
-
|
|
105
|
-
# Reader limits section size.
|
|
106
|
-
section = notification_log["3,4"]
|
|
107
|
-
self.assertEqual(len(section.items), 2) # event notifications
|
|
108
|
-
self.assertEqual(section.items[0].id, 3)
|
|
109
|
-
self.assertEqual(section.items[1].id, 4)
|
|
110
|
-
self.assertEqual(section.id, "3,4")
|
|
111
|
-
self.assertEqual(section.next_id, "5,6")
|
|
112
|
-
|
|
113
|
-
# Meaningless section ID.
|
|
114
|
-
section = notification_log["3,2"]
|
|
115
|
-
self.assertEqual(len(section.items), 0) # event notifications
|
|
116
|
-
self.assertEqual(section.id, None)
|
|
117
|
-
self.assertEqual(section.next_id, None)
|
|
118
|
-
|
|
119
|
-
# # Numbers below 1.
|
|
120
|
-
# section = notification_log["-3,0"]
|
|
121
|
-
# self.assertEqual(
|
|
122
|
-
# len(section.items), 4
|
|
123
|
-
# ) # event notifications
|
|
124
|
-
# self.assertEqual(section.items[0].id, 6)
|
|
125
|
-
# self.assertEqual(section.items[1].id, 7)
|
|
126
|
-
# self.assertEqual(section.items[2].id, 8)
|
|
127
|
-
# self.assertEqual(section.items[3].id, 9)
|
|
128
|
-
# self.assertEqual(section.section_id, "6,9")
|
|
129
|
-
# self.assertEqual(section.next_id, None)
|
|
130
|
-
#
|
|
131
|
-
# section = notification_log["-4,0"]
|
|
132
|
-
# self.assertEqual(
|
|
133
|
-
# len(section.items), 5
|
|
134
|
-
# ) # event notifications
|
|
135
|
-
# self.assertEqual(section.items[0].id, 5)
|
|
136
|
-
# self.assertEqual(section.items[1].id, 6)
|
|
137
|
-
# self.assertEqual(section.items[2].id, 7)
|
|
138
|
-
# self.assertEqual(section.items[3].id, 8)
|
|
139
|
-
# self.assertEqual(section.items[4].id, 9)
|
|
140
|
-
# self.assertEqual(section.section_id, "5,9")
|
|
141
|
-
# self.assertEqual(section.next_id, "10,14")
|
|
142
|
-
#
|
|
143
|
-
# section = notification_log["-4,-1"]
|
|
144
|
-
# self.assertEqual(
|
|
145
|
-
# len(section.items), 4
|
|
146
|
-
# ) # event notifications
|
|
147
|
-
# self.assertEqual(section.items[0].id, 5)
|
|
148
|
-
# self.assertEqual(section.items[1].id, 6)
|
|
149
|
-
# self.assertEqual(section.items[2].id, 7)
|
|
150
|
-
# self.assertEqual(section.items[3].id, 8)
|
|
151
|
-
# self.assertEqual(section.section_id, "5,8")
|
|
152
|
-
# self.assertEqual(section.next_id, "9,12")
|
|
153
|
-
|
|
154
|
-
def test_select(self):
|
|
155
|
-
recorder = SQLiteApplicationRecorder(SQLiteDatastore(":memory:"))
|
|
156
|
-
recorder.create_table()
|
|
157
|
-
|
|
158
|
-
# Construct notification log.
|
|
159
|
-
notification_log = LocalNotificationLog(recorder, section_size=10)
|
|
160
|
-
|
|
161
|
-
# Select start 1, limit 10
|
|
162
|
-
notifications = notification_log.select(1, 10)
|
|
163
|
-
self.assertEqual(len(notifications), 0)
|
|
164
|
-
|
|
165
|
-
# Write 5 events.
|
|
166
|
-
originator_id = uuid4()
|
|
167
|
-
for i in range(5):
|
|
168
|
-
stored_event = StoredEvent(
|
|
169
|
-
originator_id=originator_id,
|
|
170
|
-
originator_version=i,
|
|
171
|
-
topic="topic",
|
|
172
|
-
state=b"state",
|
|
173
|
-
)
|
|
174
|
-
recorder.insert_events([stored_event])
|
|
175
|
-
|
|
176
|
-
# Select start 1, limit 10
|
|
177
|
-
notifications = notification_log.select(1, 5)
|
|
178
|
-
self.assertEqual(len(notifications), 5)
|
|
179
|
-
self.assertEqual(notifications[0].id, 1)
|
|
180
|
-
self.assertEqual(notifications[1].id, 2)
|
|
181
|
-
self.assertEqual(notifications[2].id, 3)
|
|
182
|
-
self.assertEqual(notifications[3].id, 4)
|
|
183
|
-
self.assertEqual(notifications[4].id, 5)
|
|
184
|
-
|
|
185
|
-
# Select start 1, limit 10
|
|
186
|
-
notifications = notification_log.select(1, 5)
|
|
187
|
-
self.assertEqual(len(notifications), 5)
|
|
188
|
-
self.assertEqual(notifications[0].id, 1)
|
|
189
|
-
self.assertEqual(notifications[1].id, 2)
|
|
190
|
-
self.assertEqual(notifications[2].id, 3)
|
|
191
|
-
self.assertEqual(notifications[3].id, 4)
|
|
192
|
-
self.assertEqual(notifications[4].id, 5)
|
|
193
|
-
|
|
194
|
-
# Select start 6, limit 5
|
|
195
|
-
notifications = notification_log.select(6, 5)
|
|
196
|
-
self.assertEqual(len(notifications), 0)
|
|
197
|
-
|
|
198
|
-
# Write 4 events.
|
|
199
|
-
originator_id = uuid4()
|
|
200
|
-
for i in range(4):
|
|
201
|
-
stored_event = StoredEvent(
|
|
202
|
-
originator_id=originator_id,
|
|
203
|
-
originator_version=i,
|
|
204
|
-
topic="topic",
|
|
205
|
-
state=b"state",
|
|
206
|
-
)
|
|
207
|
-
recorder.insert_events([stored_event])
|
|
208
|
-
|
|
209
|
-
# Select start 6, limit 5
|
|
210
|
-
notifications = notification_log.select(6, 5)
|
|
211
|
-
self.assertEqual(len(notifications), 4) # event notifications
|
|
212
|
-
self.assertEqual(notifications[0].id, 6)
|
|
213
|
-
self.assertEqual(notifications[1].id, 7)
|
|
214
|
-
self.assertEqual(notifications[2].id, 8)
|
|
215
|
-
self.assertEqual(notifications[3].id, 9)
|
|
216
|
-
|
|
217
|
-
# Select start 3, limit 5
|
|
218
|
-
notifications = notification_log.select(3, 5)
|
|
219
|
-
self.assertEqual(len(notifications), 5) # event notifications
|
|
220
|
-
self.assertEqual(notifications[0].id, 3)
|
|
221
|
-
self.assertEqual(notifications[1].id, 4)
|
|
222
|
-
self.assertEqual(notifications[2].id, 5)
|
|
223
|
-
self.assertEqual(notifications[3].id, 6)
|
|
224
|
-
self.assertEqual(notifications[4].id, 7)
|
|
225
|
-
|
|
226
|
-
# Notification log limits limit.
|
|
227
|
-
# Select start 1, limit 20
|
|
228
|
-
with self.assertRaises(ValueError) as cm:
|
|
229
|
-
notification_log.select(1, 20)
|
|
230
|
-
self.assertEqual(
|
|
231
|
-
cm.exception.args[0], "Requested limit 20 greater than section size 10"
|
|
232
|
-
)
|