eventsource-py 0.1.2__tar.gz → 0.2.0__tar.gz
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.
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/.github/ISSUE_TEMPLATE/bug_report.md +4 -2
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/.github/ISSUE_TEMPLATE/config.yml +2 -2
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/.github/ISSUE_TEMPLATE/feature_request.md +4 -2
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/.github/workflows/docs.yml +1 -1
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/.pre-commit-config.yaml +3 -1
- eventsource_py-0.2.0/CHANGELOG.md +135 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/PKG-INFO +57 -49
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/README.md +43 -47
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/adrs/0001-async-first-design.md +28 -31
- eventsource_py-0.2.0/docs/adrs/0007-remove-sync-event-store.md +158 -0
- eventsource_py-0.2.0/docs/adrs/0008-kafka-event-bus-integration.md +182 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/adrs/index.md +2 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/api/aggregates.md +68 -6
- eventsource_py-0.2.0/docs/api/bus.md +1190 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/api/index.md +130 -3
- eventsource_py-0.2.0/docs/api/observability.md +417 -0
- eventsource_py-0.2.0/docs/api/snapshots.md +714 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/api/stores.md +7 -1
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/architecture.md +60 -8
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/development/code-structure.md +1 -3
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/examples/multi-tenant.md +1 -2
- eventsource_py-0.2.0/docs/examples/snapshotting.md +809 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/getting-started.md +18 -7
- eventsource_py-0.2.0/docs/guides/fanout-exchange.md +322 -0
- eventsource_py-0.2.0/docs/guides/kafka-event-bus.md +658 -0
- eventsource_py-0.2.0/docs/guides/kafka-metrics.md +564 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/guides/multi-tenant.md +1 -2
- eventsource_py-0.2.0/docs/guides/observability.md +583 -0
- eventsource_py-0.2.0/docs/guides/snapshotting-migration.md +396 -0
- eventsource_py-0.2.0/docs/guides/snapshotting.md +642 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/index.md +18 -7
- eventsource_py-0.2.0/docs/installation.md +458 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/mkdocs.yml +11 -4
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/pyproject.toml +31 -3
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/__init__.py +69 -7
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/aggregates/__init__.py +2 -2
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/aggregates/base.py +247 -9
- eventsource_py-0.2.0/src/eventsource/aggregates/repository.py +833 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/bus/__init__.py +70 -5
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/bus/interface.py +112 -85
- eventsource_py-0.2.0/src/eventsource/bus/kafka.py +2904 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/bus/memory.py +60 -76
- eventsource_py-0.2.0/src/eventsource/bus/rabbitmq.py +4441 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/bus/redis.py +189 -147
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/exceptions.py +41 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/__init__.py +3 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/schemas/all.sql +31 -1
- eventsource_py-0.2.0/src/eventsource/migrations/schemas/snapshots.sql +1 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/schemas/sqlite_all.sql +25 -1
- eventsource_py-0.2.0/src/eventsource/migrations/templates/snapshots.sql +86 -0
- eventsource_py-0.2.0/src/eventsource/migrations/templates/sqlite/snapshots.sql +67 -0
- eventsource_py-0.2.0/src/eventsource/observability/__init__.py +115 -0
- eventsource_py-0.2.0/src/eventsource/observability/attributes.py +165 -0
- eventsource_py-0.2.0/src/eventsource/observability/tracing.py +276 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/projections/__init__.py +4 -2
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/projections/base.py +158 -27
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/projections/coordinator.py +55 -7
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/projections/decorators.py +45 -17
- eventsource_py-0.2.0/src/eventsource/projections/protocols.py +137 -0
- eventsource_py-0.2.0/src/eventsource/protocols.py +188 -0
- eventsource_py-0.2.0/src/eventsource/repositories/checkpoint.py +820 -0
- eventsource_py-0.2.0/src/eventsource/repositories/dlq.py +1358 -0
- eventsource_py-0.2.0/src/eventsource/repositories/outbox.py +1067 -0
- eventsource_py-0.2.0/src/eventsource/snapshots/__init__.py +116 -0
- eventsource_py-0.2.0/src/eventsource/snapshots/exceptions.py +192 -0
- eventsource_py-0.2.0/src/eventsource/snapshots/in_memory.py +325 -0
- eventsource_py-0.2.0/src/eventsource/snapshots/interface.py +282 -0
- eventsource_py-0.2.0/src/eventsource/snapshots/postgresql.py +382 -0
- eventsource_py-0.2.0/src/eventsource/snapshots/sqlite.py +365 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/stores/__init__.py +0 -2
- eventsource_py-0.2.0/src/eventsource/stores/_compat.py +66 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/stores/in_memory.py +108 -8
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/stores/interface.py +6 -83
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/stores/postgresql.py +203 -75
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/stores/sqlite.py +77 -6
- eventsource_py-0.2.0/tests/benchmarks/__init__.py +24 -0
- eventsource_py-0.2.0/tests/benchmarks/conftest.py +275 -0
- eventsource_py-0.2.0/tests/benchmarks/test_event_store.py +445 -0
- eventsource_py-0.2.0/tests/benchmarks/test_projections.py +418 -0
- eventsource_py-0.2.0/tests/benchmarks/test_repositories.py +468 -0
- eventsource_py-0.2.0/tests/benchmarks/test_serialization.py +430 -0
- eventsource_py-0.2.0/tests/conftest.py +795 -0
- eventsource_py-0.2.0/tests/fixtures/__init__.py +70 -0
- eventsource_py-0.2.0/tests/fixtures/aggregates.py +274 -0
- eventsource_py-0.2.0/tests/fixtures/events.py +161 -0
- eventsource_py-0.2.0/tests/integration/bus/test_kafka.py +2321 -0
- eventsource_py-0.2.0/tests/integration/bus/test_rabbitmq.py +2993 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/conftest.py +2 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/e2e/test_full_flow.py +2 -2
- eventsource_py-0.2.0/tests/integration/observability/__init__.py +10 -0
- eventsource_py-0.2.0/tests/integration/observability/conftest.py +271 -0
- eventsource_py-0.2.0/tests/integration/observability/test_distributed_tracing.py +634 -0
- eventsource_py-0.2.0/tests/integration/observability/test_tracing_integration.py +792 -0
- eventsource_py-0.2.0/tests/integration/observability/test_tracing_performance.py +713 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/projections/test_database_projection.py +2 -2
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/repositories/test_dlq.py +26 -23
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/repositories/test_outbox.py +17 -17
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/repositories/test_sqlite_repos.py +1 -1
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/stores/test_sqlite_event_store.py +1 -1
- eventsource_py-0.2.0/tests/unit/aggregates/__init__.py +1 -0
- eventsource_py-0.2.0/tests/unit/aggregates/test_aggregate_snapshot_methods.py +858 -0
- eventsource_py-0.2.0/tests/unit/aggregates/test_repository_snapshot.py +1230 -0
- eventsource_py-0.2.0/tests/unit/aggregates/test_repository_tracing.py +708 -0
- eventsource_py-0.2.0/tests/unit/bus/__init__.py +1 -0
- eventsource_py-0.2.0/tests/unit/bus/test_eventbus_tracing_patterns.py +383 -0
- eventsource_py-0.2.0/tests/unit/bus/test_rabbitmq_tracing.py +210 -0
- eventsource_py-0.2.0/tests/unit/migrations/__init__.py +1 -0
- eventsource_py-0.2.0/tests/unit/migrations/test_sqlite_snapshot_schema.py +234 -0
- eventsource_py-0.2.0/tests/unit/observability/__init__.py +1 -0
- eventsource_py-0.2.0/tests/unit/observability/test_attributes.py +337 -0
- eventsource_py-0.2.0/tests/unit/observability/test_projection_tracing.py +520 -0
- eventsource_py-0.2.0/tests/unit/observability/test_tracing.py +452 -0
- eventsource_py-0.2.0/tests/unit/repositories/test_checkpoint_tracing.py +669 -0
- eventsource_py-0.2.0/tests/unit/snapshots/__init__.py +1 -0
- eventsource_py-0.2.0/tests/unit/snapshots/test_in_memory_snapshot_store.py +329 -0
- eventsource_py-0.2.0/tests/unit/snapshots/test_postgresql_snapshot_store.py +753 -0
- eventsource_py-0.2.0/tests/unit/snapshots/test_snapshot.py +201 -0
- eventsource_py-0.2.0/tests/unit/snapshots/test_snapshot_exceptions.py +258 -0
- eventsource_py-0.2.0/tests/unit/snapshots/test_snapshot_store_interface.py +131 -0
- eventsource_py-0.2.0/tests/unit/snapshots/test_snapshot_store_tracing.py +513 -0
- eventsource_py-0.2.0/tests/unit/snapshots/test_snapshots_module.py +122 -0
- eventsource_py-0.2.0/tests/unit/snapshots/test_sqlite_snapshot_store.py +420 -0
- eventsource_py-0.2.0/tests/unit/stores/__init__.py +1 -0
- eventsource_py-0.2.0/tests/unit/stores/test_memory_tracing.py +582 -0
- eventsource_py-0.2.0/tests/unit/stores/test_postgresql_tracing.py +524 -0
- eventsource_py-0.2.0/tests/unit/stores/test_sqlite_tracing.py +435 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_aggregate_root.py +334 -2
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_checkpoint_repository.py +6 -6
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_dlq_repository.py +213 -15
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_edge_cases.py +6 -2
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_event_store_interface.py +6 -155
- eventsource_py-0.2.0/tests/unit/test_fixtures.py +448 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_in_memory_event_store.py +7 -2
- eventsource_py-0.2.0/tests/unit/test_kafka_event_bus.py +1683 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_outbox_repository.py +167 -2
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_postgresql_event_store.py +227 -4
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_projection_base.py +352 -13
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_projection_decorators.py +129 -0
- eventsource_py-0.2.0/tests/unit/test_protocols.py +382 -0
- eventsource_py-0.2.0/tests/unit/test_rabbitmq_event_bus.py +11611 -0
- eventsource_py-0.2.0/tests/unit/test_rabbitmq_exports.py +260 -0
- eventsource_py-0.2.0/tests/unit/test_redis_event_bus_tracing.py +707 -0
- eventsource_py-0.2.0/tests/unit/test_timestamp_types.py +410 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/uv.lock +474 -6
- eventsource_py-0.1.2/CHANGELOG.md +0 -54
- eventsource_py-0.1.2/docs/api/bus.md +0 -540
- eventsource_py-0.1.2/docs/eventsource-py.code-workspace +0 -14
- eventsource_py-0.1.2/src/eventsource/aggregates/repository.py +0 -294
- eventsource_py-0.1.2/src/eventsource/projections/protocols.py +0 -161
- eventsource_py-0.1.2/src/eventsource/repositories/checkpoint.py +0 -717
- eventsource_py-0.1.2/src/eventsource/repositories/dlq.py +0 -1124
- eventsource_py-0.1.2/src/eventsource/repositories/outbox.py +0 -816
- eventsource_py-0.1.2/tests/conftest.py +0 -248
- eventsource_py-0.1.2/tests/fixtures/__init__.py +0 -1
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/.github/workflows/ci.yml +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/.github/workflows/release.yml +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/.gitignore +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/LICENSE +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/RELEASING.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docker-compose.test.yml +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/adrs/0000-template.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/adrs/0002-pydantic-event-models.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/adrs/0003-optimistic-locking.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/adrs/0004-projection-error-handling.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/adrs/0005-api-design-patterns.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/adrs/0006-event-registry-serialization.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/api/events.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/api/projections.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/development/testing.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/examples/basic-order.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/examples/projections.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/examples/sqlite-usage.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/examples/testing.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/faq.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/guides/authentication.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/guides/error-handling.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/guides/production.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/guides/sqlite-backend.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/docs/infrastructure-tracking.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/examples/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/examples/aggregate_example.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/examples/basic_usage.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/examples/projection_example.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/py.typed +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/scripts/validate_examples.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/config.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/events/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/events/base.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/events/registry.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/SCHEMA_DESIGN.md +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/schemas/checkpoints.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/schemas/dlq.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/schemas/events.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/schemas/events_partitioned.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/schemas/outbox.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/alembic/all_tables.py.template +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/alembic/checkpoints.py.template +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/alembic/dlq.py.template +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/alembic/events.py.template +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/alembic/outbox.py.template +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/checkpoints.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/dlq.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/events.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/events_partitioned.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/outbox.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/sqlite/checkpoints.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/sqlite/dlq.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/sqlite/events.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/migrations/templates/sqlite/outbox.sql +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/py.typed +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/repositories/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/repositories/_connection.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/repositories/_json.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/src/eventsource/types.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/bus/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/bus/test_redis.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/e2e/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/projections/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/repositories/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/repositories/test_checkpoint.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/stores/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/integration/stores/test_postgresql.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/repositories/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/stores/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/__init__.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_additional_coverage.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_aggregate_repository.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_connection_helper.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_domain_event.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_event_bus.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_event_registry.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_exceptions.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_json_encoder.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_projection_coordinator.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_projection_protocols.py +0 -0
- {eventsource_py-0.1.2 → eventsource_py-0.2.0}/tests/unit/test_redis_event_bus.py +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
blank_issues_enabled: false
|
|
2
2
|
contact_links:
|
|
3
3
|
- name: Documentation
|
|
4
|
-
url: https://
|
|
4
|
+
url: https://tyevans.github.io/eventsource-py
|
|
5
5
|
about: Check our documentation for answers
|
|
6
6
|
- name: Questions & Discussions
|
|
7
|
-
url: https://github.com/
|
|
7
|
+
url: https://github.com/tyevans/eventsource-py/discussions
|
|
8
8
|
about: Ask questions and discuss ideas
|
|
@@ -10,7 +10,7 @@ repos:
|
|
|
10
10
|
- id: debug-statements
|
|
11
11
|
|
|
12
12
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
13
|
-
rev: v0.8
|
|
13
|
+
rev: v0.14.8
|
|
14
14
|
hooks:
|
|
15
15
|
- id: ruff
|
|
16
16
|
args: [--fix]
|
|
@@ -25,6 +25,8 @@ repos:
|
|
|
25
25
|
- sqlalchemy>=2.0
|
|
26
26
|
- redis==5.3.1
|
|
27
27
|
- opentelemetry-api>=1.0
|
|
28
|
+
- aio-pika>=9.0.0
|
|
29
|
+
- aiosqlite>=0.20.0
|
|
28
30
|
args: [--config-file=pyproject.toml]
|
|
29
31
|
files: ^src/
|
|
30
32
|
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.2.0] - 2025-12-08
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
#### Observability & Telemetry
|
|
15
|
+
|
|
16
|
+
- **Observability Module** (`eventsource.observability`) - Reusable OpenTelemetry utilities
|
|
17
|
+
- `OTEL_AVAILABLE` constant for checking OpenTelemetry availability
|
|
18
|
+
- `get_tracer()` and `should_trace()` helper functions
|
|
19
|
+
- `@traced` decorator for method-level tracing
|
|
20
|
+
- `TracingMixin` class for consistent tracing across components
|
|
21
|
+
- **Kafka Event Bus Metrics** - Comprehensive OpenTelemetry metrics
|
|
22
|
+
- Counters: `messages.published`, `messages.consumed`, `handler.invocations`, `handler.errors`, `messages.dlq`, `connection.errors`, `reconnections`, `rebalances`, `publish.errors`
|
|
23
|
+
- Histograms: `publish.duration`, `consume.duration`, `handler.duration`, `batch.size`
|
|
24
|
+
- Gauges: `connections.active`, `consumer.lag` (per partition)
|
|
25
|
+
- New `KafkaEventBusMetrics` class with `enable_metrics` config option
|
|
26
|
+
- Less than 5% performance overhead
|
|
27
|
+
- **SQLiteEventStore Tracing** - `enable_tracing` parameter for `append_events` and `get_events` operations
|
|
28
|
+
- **InMemoryEventBus Tracing** - `enable_tracing` parameter for event dispatch and handler execution
|
|
29
|
+
|
|
30
|
+
#### Aggregate Snapshotting
|
|
31
|
+
|
|
32
|
+
- `Snapshot` dataclass for point-in-time aggregate state capture
|
|
33
|
+
- `SnapshotStore` interface with `InMemorySnapshotStore`, `PostgreSQLSnapshotStore`, and `SQLiteSnapshotStore` implementations
|
|
34
|
+
- `AggregateRepository` snapshot support: `snapshot_store`, `snapshot_threshold`, and `snapshot_mode` parameters
|
|
35
|
+
- `AggregateRoot.schema_version` for snapshot schema evolution with automatic invalidation
|
|
36
|
+
- `create_snapshot()` and `await_pending_snapshots()` methods
|
|
37
|
+
- Snapshot exceptions: `SnapshotError`, `SnapshotDeserializationError`, `SnapshotSchemaVersionError`, `SnapshotNotFoundError`
|
|
38
|
+
- Database migrations for `snapshots` table (PostgreSQL and SQLite)
|
|
39
|
+
|
|
40
|
+
#### Event Handling & Validation
|
|
41
|
+
|
|
42
|
+
- `EventVersionError` exception and configurable version validation via `AggregateRoot.validate_versions`
|
|
43
|
+
- `UnhandledEventError` exception with configurable handling via `unregistered_event_handling` attribute ("ignore", "warn", "error")
|
|
44
|
+
- `FlexibleEventHandler` and `FlexibleEventSubscriber` protocols for sync/async handler signatures
|
|
45
|
+
- Consolidated `eventsource.protocols` module as canonical location for protocol definitions
|
|
46
|
+
|
|
47
|
+
#### Database & Repository
|
|
48
|
+
|
|
49
|
+
- `DatabaseProjection` class for projections requiring raw database connection access
|
|
50
|
+
- `execute_with_connection` helper for consistent connection handling
|
|
51
|
+
- Configurable UUID field detection in `PostgreSQLEventStore` via `uuid_fields`, `string_id_fields`, and `auto_detect_uuid` parameters
|
|
52
|
+
- `PostgreSQLEventStore.with_strict_uuid_detection()` class method
|
|
53
|
+
|
|
54
|
+
#### Developer Experience
|
|
55
|
+
|
|
56
|
+
- Pre-commit hooks with ruff, mypy, and bandit
|
|
57
|
+
- GitHub Actions workflow for performance benchmarks with baseline tracking and PR comparison
|
|
58
|
+
- Shared test fixtures module (`tests/fixtures/`) with reusable components
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
|
|
62
|
+
- Improved type annotations for better mypy compatibility
|
|
63
|
+
- Consolidated `@handles` decorator to `eventsource.projections.decorators` (old location deprecated)
|
|
64
|
+
- Consolidated protocol definitions to `eventsource.protocols` (old locations deprecated)
|
|
65
|
+
- Repository methods `get_pending_events`, `get_failed_events`, `get_failed_event_by_id` now return typed dataclasses (`OutboxEntry`, `DLQEntry`) instead of dicts
|
|
66
|
+
- Unified `get_events_by_type()` timestamp parameters to use `datetime` instead of `float`
|
|
67
|
+
- Refactored repositories to use `execute_with_connection` helper
|
|
68
|
+
- In-memory repositories now use `asyncio.Lock` for proper async concurrency
|
|
69
|
+
|
|
70
|
+
### Removed
|
|
71
|
+
|
|
72
|
+
- `SyncEventStore` abstract class (use `asyncio.run()` for sync access; see ADR-0007)
|
|
73
|
+
|
|
74
|
+
### Fixed
|
|
75
|
+
|
|
76
|
+
- Broken documentation links in ADRs and guides
|
|
77
|
+
- Mypy type errors in projections, repositories, and event bus modules
|
|
78
|
+
- `DeclarativeProjection` connection handling for proper transaction sharing
|
|
79
|
+
|
|
80
|
+
## [0.1.3] - 2025-12-07
|
|
81
|
+
|
|
82
|
+
### Documentation
|
|
83
|
+
|
|
84
|
+
- Added documentation badge linking to GitHub Pages
|
|
85
|
+
- Updated all documentation URLs to point to https://tyevans.github.io/eventsource-py
|
|
86
|
+
- Fixed mkdocs.yml site configuration with correct repository URLs
|
|
87
|
+
- Simplified README documentation section with links to hosted docs
|
|
88
|
+
|
|
89
|
+
## [0.1.2] - 2025-12-07
|
|
90
|
+
|
|
91
|
+
### Fixed
|
|
92
|
+
|
|
93
|
+
- Fixed release workflow version validation
|
|
94
|
+
|
|
95
|
+
## [0.1.1] - 2025-12-07
|
|
96
|
+
|
|
97
|
+
### Fixed
|
|
98
|
+
|
|
99
|
+
- Release infrastructure corrections
|
|
100
|
+
|
|
101
|
+
## [0.1.0] - 2025-12-07
|
|
102
|
+
|
|
103
|
+
### Added
|
|
104
|
+
|
|
105
|
+
- Initial release of eventsource-py library
|
|
106
|
+
- Event Store with PostgreSQL, SQLite, and In-Memory backends
|
|
107
|
+
- Domain Events with Pydantic validation
|
|
108
|
+
- Aggregate base class with optimistic concurrency control
|
|
109
|
+
- Projection system for building read models with checkpoint tracking
|
|
110
|
+
- Dead Letter Queue (DLQ) for failed event handling
|
|
111
|
+
- Snapshot support for aggregate state caching
|
|
112
|
+
- Multi-tenant support with tenant isolation
|
|
113
|
+
- Async-first API design throughout
|
|
114
|
+
- Comprehensive type hints and mypy compatibility
|
|
115
|
+
- Event registry for type-safe event deserialization
|
|
116
|
+
- Event Bus with In-Memory and Redis Streams backends
|
|
117
|
+
- Transactional Outbox pattern implementation
|
|
118
|
+
- `DatabaseProjection` class for projections requiring raw database connection access
|
|
119
|
+
- Pre-commit hooks configuration with ruff, mypy, and bandit
|
|
120
|
+
|
|
121
|
+
### Infrastructure
|
|
122
|
+
|
|
123
|
+
- PostgreSQL backend with connection pooling (asyncpg)
|
|
124
|
+
- SQLite backend for lightweight deployments, development, and testing
|
|
125
|
+
- Redis Streams backend for distributed event bus
|
|
126
|
+
- In-Memory backends for testing and development
|
|
127
|
+
- Automatic schema creation and migrations
|
|
128
|
+
- GitHub Actions CI/CD pipeline
|
|
129
|
+
|
|
130
|
+
[Unreleased]: https://github.com/tyevans/eventsource-py/compare/v0.2.0...HEAD
|
|
131
|
+
[0.2.0]: https://github.com/tyevans/eventsource-py/compare/v0.1.3...v0.2.0
|
|
132
|
+
[0.1.3]: https://github.com/tyevans/eventsource-py/compare/v0.1.2...v0.1.3
|
|
133
|
+
[0.1.2]: https://github.com/tyevans/eventsource-py/compare/v0.1.1...v0.1.2
|
|
134
|
+
[0.1.1]: https://github.com/tyevans/eventsource-py/compare/v0.1.0...v0.1.1
|
|
135
|
+
[0.1.0]: https://github.com/tyevans/eventsource-py/releases/tag/v0.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eventsource-py
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Production-ready event sourcing library for Python
|
|
5
5
|
Project-URL: Homepage, https://github.com/tyevans/eventsource-py
|
|
6
6
|
Project-URL: Documentation, https://tyevans.github.io/eventsource-py
|
|
@@ -24,6 +24,8 @@ Requires-Dist: pydantic<3.0,>=2.0
|
|
|
24
24
|
Requires-Dist: redis>=5.0
|
|
25
25
|
Requires-Dist: sqlalchemy<3.0,>=2.0
|
|
26
26
|
Provides-Extra: all
|
|
27
|
+
Requires-Dist: aio-pika>=9.0.0; extra == 'all'
|
|
28
|
+
Requires-Dist: aiokafka<1.0.0,>=0.9.0; extra == 'all'
|
|
27
29
|
Requires-Dist: aiosqlite<1.0,>=0.19.0; extra == 'all'
|
|
28
30
|
Requires-Dist: asyncpg<1.0,>=0.27.0; extra == 'all'
|
|
29
31
|
Requires-Dist: opentelemetry-api<2.0,>=1.0; extra == 'all'
|
|
@@ -32,21 +34,31 @@ Requires-Dist: redis<6.0,>=5.0; extra == 'all'
|
|
|
32
34
|
Provides-Extra: all-backends
|
|
33
35
|
Requires-Dist: aiosqlite<1.0,>=0.19.0; extra == 'all-backends'
|
|
34
36
|
Requires-Dist: asyncpg<1.0,>=0.27.0; extra == 'all-backends'
|
|
37
|
+
Provides-Extra: benchmark
|
|
38
|
+
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'benchmark'
|
|
35
39
|
Provides-Extra: dev
|
|
36
40
|
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
37
41
|
Requires-Dist: pre-commit>=4.0; extra == 'dev'
|
|
38
42
|
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
43
|
+
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'dev'
|
|
39
44
|
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
40
45
|
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
41
|
-
Requires-Dist: ruff>=0.
|
|
46
|
+
Requires-Dist: ruff>=0.14.8; extra == 'dev'
|
|
42
47
|
Requires-Dist: testcontainers>=4.0; extra == 'dev'
|
|
43
48
|
Provides-Extra: docs
|
|
44
49
|
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
|
|
45
50
|
Requires-Dist: mkdocs>=1.5; extra == 'docs'
|
|
46
51
|
Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
|
|
47
52
|
Requires-Dist: pymdown-extensions>=10.0; extra == 'docs'
|
|
53
|
+
Provides-Extra: kafka
|
|
54
|
+
Requires-Dist: aiokafka<1.0.0,>=0.9.0; extra == 'kafka'
|
|
55
|
+
Provides-Extra: kafka-schema-registry
|
|
56
|
+
Requires-Dist: aiokafka<1.0.0,>=0.9.0; extra == 'kafka-schema-registry'
|
|
57
|
+
Requires-Dist: confluent-kafka<3.0.0,>=2.0.0; extra == 'kafka-schema-registry'
|
|
48
58
|
Provides-Extra: postgresql
|
|
49
59
|
Requires-Dist: asyncpg<1.0,>=0.27.0; extra == 'postgresql'
|
|
60
|
+
Provides-Extra: rabbitmq
|
|
61
|
+
Requires-Dist: aio-pika>=9.0.0; extra == 'rabbitmq'
|
|
50
62
|
Provides-Extra: redis
|
|
51
63
|
Requires-Dist: redis<6.0,>=5.0; extra == 'redis'
|
|
52
64
|
Provides-Extra: sqlite
|
|
@@ -62,6 +74,7 @@ Description-Content-Type: text/markdown
|
|
|
62
74
|
[](https://opensource.org/licenses/MIT)
|
|
63
75
|
[](https://pypi.org/project/eventsource-py/)
|
|
64
76
|
[](https://github.com/tyevans/eventsource-py/actions)
|
|
77
|
+
[](https://tyevans.github.io/eventsource-py)
|
|
65
78
|
[](https://github.com/astral-sh/ruff)
|
|
66
79
|
|
|
67
80
|
A production-ready event sourcing library for Python 3.11+.
|
|
@@ -73,39 +86,69 @@ A production-ready event sourcing library for Python 3.11+.
|
|
|
73
86
|
- **Event Registry** - Thread-safe event type registration for serialization/deserialization
|
|
74
87
|
- **Aggregate Pattern** - Base classes for event-sourced aggregates with state reconstruction
|
|
75
88
|
- **Repository Pattern** - Clean abstractions for loading and saving aggregates
|
|
89
|
+
- **Aggregate Snapshotting** - Optimize load performance for long-lived aggregates
|
|
76
90
|
- **Projection System** - Checkpoint tracking, retry logic, and dead letter queue support
|
|
77
|
-
- **Event Bus** - In-Memory
|
|
91
|
+
- **Event Bus** - In-Memory, Redis Streams, RabbitMQ, and Kafka backends for event distribution
|
|
78
92
|
- **Transactional Outbox** - Reliable event publishing pattern
|
|
79
93
|
- **Multi-tenancy** - Built-in tenant isolation support
|
|
80
94
|
- **Observability** - Optional OpenTelemetry integration
|
|
81
95
|
|
|
82
96
|
## Installation
|
|
83
97
|
|
|
98
|
+
### Basic Installation
|
|
99
|
+
|
|
84
100
|
```bash
|
|
85
|
-
# Basic installation
|
|
86
101
|
pip install eventsource-py
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### With Optional Dependencies
|
|
87
105
|
|
|
88
|
-
|
|
106
|
+
eventsource uses optional dependencies to keep the core package lightweight. Install only what you need:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# PostgreSQL support - production event store with asyncpg
|
|
89
110
|
pip install eventsource-py[postgresql]
|
|
90
111
|
|
|
91
|
-
#
|
|
112
|
+
# SQLite support - lightweight deployments
|
|
92
113
|
pip install eventsource-py[sqlite]
|
|
93
114
|
|
|
94
|
-
#
|
|
115
|
+
# Redis support - distributed event bus with Redis Streams
|
|
95
116
|
pip install eventsource-py[redis]
|
|
96
117
|
|
|
97
|
-
#
|
|
118
|
+
# RabbitMQ support - distributed event bus with RabbitMQ
|
|
119
|
+
pip install eventsource-py[rabbitmq]
|
|
120
|
+
|
|
121
|
+
# Kafka support - distributed event bus with Apache Kafka
|
|
122
|
+
pip install eventsource-py[kafka]
|
|
123
|
+
|
|
124
|
+
# Telemetry support - OpenTelemetry tracing integration
|
|
98
125
|
pip install eventsource-py[telemetry]
|
|
99
126
|
|
|
100
127
|
# All optional dependencies
|
|
101
128
|
pip install eventsource-py[all]
|
|
129
|
+
|
|
130
|
+
# Multiple extras
|
|
131
|
+
pip install eventsource-py[postgresql,redis,telemetry]
|
|
102
132
|
```
|
|
103
133
|
|
|
134
|
+
| Extra | Enables | Dependencies |
|
|
135
|
+
|-------|---------|--------------|
|
|
136
|
+
| `postgresql` | `PostgreSQLEventStore`, checkpoint/outbox/DLQ repositories | asyncpg |
|
|
137
|
+
| `sqlite` | `SQLiteEventStore` for lightweight deployments | aiosqlite |
|
|
138
|
+
| `redis` | `RedisEventBus` with consumer groups and DLQ | redis |
|
|
139
|
+
| `rabbitmq` | `RabbitMQEventBus` with exchange routing and DLQ | aio-pika |
|
|
140
|
+
| `kafka` | `KafkaEventBus` with consumer groups, DLQ, and tracing | aiokafka |
|
|
141
|
+
| `telemetry` | Distributed tracing for event operations | opentelemetry-api, opentelemetry-sdk |
|
|
142
|
+
| `all` | All of the above | All of the above |
|
|
143
|
+
| `dev` | Development tools | pytest, mypy, ruff, pre-commit |
|
|
144
|
+
|
|
145
|
+
For detailed installation instructions, troubleshooting, and version compatibility, see the [Installation Guide](docs/installation.md).
|
|
146
|
+
|
|
104
147
|
## Requirements
|
|
105
148
|
|
|
106
149
|
- Python 3.11+
|
|
107
150
|
- pydantic >= 2.0
|
|
108
|
-
- sqlalchemy >= 2.0
|
|
151
|
+
- sqlalchemy >= 2.0
|
|
109
152
|
|
|
110
153
|
## Quick Start
|
|
111
154
|
|
|
@@ -263,47 +306,12 @@ asyncio.run(main())
|
|
|
263
306
|
|
|
264
307
|
## Documentation
|
|
265
308
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
### Getting Started
|
|
269
|
-
|
|
270
|
-
- [Getting Started Guide](docs/getting-started.md) - Installation and first steps
|
|
271
|
-
- [Architecture Overview](docs/architecture.md) - System design and concepts
|
|
272
|
-
- [FAQ](docs/faq.md) - Frequently asked questions
|
|
273
|
-
|
|
274
|
-
### Guides
|
|
275
|
-
|
|
276
|
-
- [Multi-tenant Setup](docs/guides/multi-tenant.md) - Tenant isolation patterns and configuration
|
|
277
|
-
- [Error Handling](docs/guides/error-handling.md) - Exception handling best practices
|
|
278
|
-
- [Authentication](docs/guides/authentication.md) - Security integration patterns
|
|
279
|
-
- [Production Deployment](docs/guides/production.md) - Production readiness checklist
|
|
280
|
-
|
|
281
|
-
### API Reference
|
|
282
|
-
|
|
283
|
-
- [Events API](docs/api/events.md) - DomainEvent and EventRegistry
|
|
284
|
-
- [Event Stores](docs/api/stores.md) - EventStore interface and implementations
|
|
285
|
-
- [Aggregates](docs/api/aggregates.md) - AggregateRoot and Repository
|
|
286
|
-
- [Projections](docs/api/projections.md) - Projection system
|
|
287
|
-
- [Event Bus](docs/api/bus.md) - Event distribution
|
|
288
|
-
|
|
289
|
-
### Examples
|
|
290
|
-
|
|
291
|
-
- [Basic Usage](docs/examples/basic-order.md) - Simple order example
|
|
292
|
-
- [Multi-tenant Setup](docs/examples/multi-tenant.md) - Multi-tenancy configuration
|
|
293
|
-
- [Projections](docs/examples/projections.md) - Building read models
|
|
294
|
-
- [Testing Patterns](docs/examples/testing.md) - Unit and integration testing
|
|
295
|
-
|
|
296
|
-
### Architecture Decision Records
|
|
297
|
-
|
|
298
|
-
- [ADR Index](docs/adrs/index.md) - All architectural decisions
|
|
299
|
-
- [ADR-0001: Async-First Design](docs/adrs/0001-async-first-design.md)
|
|
300
|
-
- [ADR-0002: Pydantic Event Models](docs/adrs/0002-pydantic-event-models.md)
|
|
301
|
-
- [ADR-0003: Optimistic Locking](docs/adrs/0003-optimistic-locking.md)
|
|
302
|
-
|
|
303
|
-
### Developer Documentation
|
|
309
|
+
📚 **[Full Documentation](https://tyevans.github.io/eventsource-py)**
|
|
304
310
|
|
|
305
|
-
- [
|
|
306
|
-
- [
|
|
311
|
+
- [Getting Started Guide](https://tyevans.github.io/eventsource-py/getting-started/) - Installation and first steps
|
|
312
|
+
- [Architecture Overview](https://tyevans.github.io/eventsource-py/architecture/) - System design and concepts
|
|
313
|
+
- [API Reference](https://tyevans.github.io/eventsource-py/api/) - Complete API documentation
|
|
314
|
+
- [FAQ](https://tyevans.github.io/eventsource-py/faq/) - Frequently asked questions
|
|
307
315
|
|
|
308
316
|
## Development
|
|
309
317
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://pypi.org/project/eventsource-py/)
|
|
6
6
|
[](https://github.com/tyevans/eventsource-py/actions)
|
|
7
|
+
[](https://tyevans.github.io/eventsource-py)
|
|
7
8
|
[](https://github.com/astral-sh/ruff)
|
|
8
9
|
|
|
9
10
|
A production-ready event sourcing library for Python 3.11+.
|
|
@@ -15,39 +16,69 @@ A production-ready event sourcing library for Python 3.11+.
|
|
|
15
16
|
- **Event Registry** - Thread-safe event type registration for serialization/deserialization
|
|
16
17
|
- **Aggregate Pattern** - Base classes for event-sourced aggregates with state reconstruction
|
|
17
18
|
- **Repository Pattern** - Clean abstractions for loading and saving aggregates
|
|
19
|
+
- **Aggregate Snapshotting** - Optimize load performance for long-lived aggregates
|
|
18
20
|
- **Projection System** - Checkpoint tracking, retry logic, and dead letter queue support
|
|
19
|
-
- **Event Bus** - In-Memory
|
|
21
|
+
- **Event Bus** - In-Memory, Redis Streams, RabbitMQ, and Kafka backends for event distribution
|
|
20
22
|
- **Transactional Outbox** - Reliable event publishing pattern
|
|
21
23
|
- **Multi-tenancy** - Built-in tenant isolation support
|
|
22
24
|
- **Observability** - Optional OpenTelemetry integration
|
|
23
25
|
|
|
24
26
|
## Installation
|
|
25
27
|
|
|
28
|
+
### Basic Installation
|
|
29
|
+
|
|
26
30
|
```bash
|
|
27
|
-
# Basic installation
|
|
28
31
|
pip install eventsource-py
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### With Optional Dependencies
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
eventsource uses optional dependencies to keep the core package lightweight. Install only what you need:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# PostgreSQL support - production event store with asyncpg
|
|
31
40
|
pip install eventsource-py[postgresql]
|
|
32
41
|
|
|
33
|
-
#
|
|
42
|
+
# SQLite support - lightweight deployments
|
|
34
43
|
pip install eventsource-py[sqlite]
|
|
35
44
|
|
|
36
|
-
#
|
|
45
|
+
# Redis support - distributed event bus with Redis Streams
|
|
37
46
|
pip install eventsource-py[redis]
|
|
38
47
|
|
|
39
|
-
#
|
|
48
|
+
# RabbitMQ support - distributed event bus with RabbitMQ
|
|
49
|
+
pip install eventsource-py[rabbitmq]
|
|
50
|
+
|
|
51
|
+
# Kafka support - distributed event bus with Apache Kafka
|
|
52
|
+
pip install eventsource-py[kafka]
|
|
53
|
+
|
|
54
|
+
# Telemetry support - OpenTelemetry tracing integration
|
|
40
55
|
pip install eventsource-py[telemetry]
|
|
41
56
|
|
|
42
57
|
# All optional dependencies
|
|
43
58
|
pip install eventsource-py[all]
|
|
59
|
+
|
|
60
|
+
# Multiple extras
|
|
61
|
+
pip install eventsource-py[postgresql,redis,telemetry]
|
|
44
62
|
```
|
|
45
63
|
|
|
64
|
+
| Extra | Enables | Dependencies |
|
|
65
|
+
|-------|---------|--------------|
|
|
66
|
+
| `postgresql` | `PostgreSQLEventStore`, checkpoint/outbox/DLQ repositories | asyncpg |
|
|
67
|
+
| `sqlite` | `SQLiteEventStore` for lightweight deployments | aiosqlite |
|
|
68
|
+
| `redis` | `RedisEventBus` with consumer groups and DLQ | redis |
|
|
69
|
+
| `rabbitmq` | `RabbitMQEventBus` with exchange routing and DLQ | aio-pika |
|
|
70
|
+
| `kafka` | `KafkaEventBus` with consumer groups, DLQ, and tracing | aiokafka |
|
|
71
|
+
| `telemetry` | Distributed tracing for event operations | opentelemetry-api, opentelemetry-sdk |
|
|
72
|
+
| `all` | All of the above | All of the above |
|
|
73
|
+
| `dev` | Development tools | pytest, mypy, ruff, pre-commit |
|
|
74
|
+
|
|
75
|
+
For detailed installation instructions, troubleshooting, and version compatibility, see the [Installation Guide](docs/installation.md).
|
|
76
|
+
|
|
46
77
|
## Requirements
|
|
47
78
|
|
|
48
79
|
- Python 3.11+
|
|
49
80
|
- pydantic >= 2.0
|
|
50
|
-
- sqlalchemy >= 2.0
|
|
81
|
+
- sqlalchemy >= 2.0
|
|
51
82
|
|
|
52
83
|
## Quick Start
|
|
53
84
|
|
|
@@ -205,47 +236,12 @@ asyncio.run(main())
|
|
|
205
236
|
|
|
206
237
|
## Documentation
|
|
207
238
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
### Getting Started
|
|
211
|
-
|
|
212
|
-
- [Getting Started Guide](docs/getting-started.md) - Installation and first steps
|
|
213
|
-
- [Architecture Overview](docs/architecture.md) - System design and concepts
|
|
214
|
-
- [FAQ](docs/faq.md) - Frequently asked questions
|
|
215
|
-
|
|
216
|
-
### Guides
|
|
217
|
-
|
|
218
|
-
- [Multi-tenant Setup](docs/guides/multi-tenant.md) - Tenant isolation patterns and configuration
|
|
219
|
-
- [Error Handling](docs/guides/error-handling.md) - Exception handling best practices
|
|
220
|
-
- [Authentication](docs/guides/authentication.md) - Security integration patterns
|
|
221
|
-
- [Production Deployment](docs/guides/production.md) - Production readiness checklist
|
|
222
|
-
|
|
223
|
-
### API Reference
|
|
224
|
-
|
|
225
|
-
- [Events API](docs/api/events.md) - DomainEvent and EventRegistry
|
|
226
|
-
- [Event Stores](docs/api/stores.md) - EventStore interface and implementations
|
|
227
|
-
- [Aggregates](docs/api/aggregates.md) - AggregateRoot and Repository
|
|
228
|
-
- [Projections](docs/api/projections.md) - Projection system
|
|
229
|
-
- [Event Bus](docs/api/bus.md) - Event distribution
|
|
230
|
-
|
|
231
|
-
### Examples
|
|
232
|
-
|
|
233
|
-
- [Basic Usage](docs/examples/basic-order.md) - Simple order example
|
|
234
|
-
- [Multi-tenant Setup](docs/examples/multi-tenant.md) - Multi-tenancy configuration
|
|
235
|
-
- [Projections](docs/examples/projections.md) - Building read models
|
|
236
|
-
- [Testing Patterns](docs/examples/testing.md) - Unit and integration testing
|
|
237
|
-
|
|
238
|
-
### Architecture Decision Records
|
|
239
|
-
|
|
240
|
-
- [ADR Index](docs/adrs/index.md) - All architectural decisions
|
|
241
|
-
- [ADR-0001: Async-First Design](docs/adrs/0001-async-first-design.md)
|
|
242
|
-
- [ADR-0002: Pydantic Event Models](docs/adrs/0002-pydantic-event-models.md)
|
|
243
|
-
- [ADR-0003: Optimistic Locking](docs/adrs/0003-optimistic-locking.md)
|
|
244
|
-
|
|
245
|
-
### Developer Documentation
|
|
239
|
+
📚 **[Full Documentation](https://tyevans.github.io/eventsource-py)**
|
|
246
240
|
|
|
247
|
-
- [
|
|
248
|
-
- [
|
|
241
|
+
- [Getting Started Guide](https://tyevans.github.io/eventsource-py/getting-started/) - Installation and first steps
|
|
242
|
+
- [Architecture Overview](https://tyevans.github.io/eventsource-py/architecture/) - System design and concepts
|
|
243
|
+
- [API Reference](https://tyevans.github.io/eventsource-py/api/) - Complete API documentation
|
|
244
|
+
- [FAQ](https://tyevans.github.io/eventsource-py/faq/) - Frequently asked questions
|
|
249
245
|
|
|
250
246
|
## Development
|
|
251
247
|
|
|
@@ -106,35 +106,33 @@ class EventStore(ABC):
|
|
|
106
106
|
...
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
#### Sync
|
|
109
|
+
#### Sync Usage via asyncio.run()
|
|
110
110
|
|
|
111
|
-
For contexts where async is not available,
|
|
111
|
+
For contexts where async is not available or desired, users can wrap async calls:
|
|
112
112
|
|
|
113
113
|
```python
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
@abstractmethod
|
|
117
|
-
def append_events(
|
|
118
|
-
self,
|
|
119
|
-
aggregate_id: UUID,
|
|
120
|
-
aggregate_type: str,
|
|
121
|
-
events: list[DomainEvent],
|
|
122
|
-
expected_version: int,
|
|
123
|
-
) -> AppendResult:
|
|
124
|
-
"""Append events (synchronous)."""
|
|
125
|
-
pass
|
|
114
|
+
import asyncio
|
|
115
|
+
from eventsource import InMemoryEventStore
|
|
126
116
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
117
|
+
store = InMemoryEventStore()
|
|
118
|
+
|
|
119
|
+
# Synchronous usage via asyncio.run()
|
|
120
|
+
result = asyncio.run(store.append_events(
|
|
121
|
+
aggregate_id=order_id,
|
|
122
|
+
aggregate_type="Order",
|
|
123
|
+
events=[order_created],
|
|
124
|
+
expected_version=0,
|
|
125
|
+
))
|
|
126
|
+
|
|
127
|
+
stream = asyncio.run(store.get_events(order_id, "Order"))
|
|
136
128
|
```
|
|
137
129
|
|
|
130
|
+
This approach was chosen over a separate `SyncEventStore` ABC because:
|
|
131
|
+
- No concrete implementations existed for the sync interface
|
|
132
|
+
- Modern Python I/O libraries are async-first
|
|
133
|
+
- `asyncio.run()` provides a simple escape hatch when needed
|
|
134
|
+
- Maintaining both interfaces adds maintenance burden without clear benefit
|
|
135
|
+
|
|
138
136
|
#### Repository Pattern
|
|
139
137
|
|
|
140
138
|
The `AggregateRepository` follows the async-first pattern:
|
|
@@ -189,14 +187,14 @@ class EventBus(ABC):
|
|
|
189
187
|
pass
|
|
190
188
|
```
|
|
191
189
|
|
|
192
|
-
### When to Use
|
|
190
|
+
### When to Use Async vs asyncio.run()
|
|
193
191
|
|
|
194
|
-
| Use Case | Recommended
|
|
195
|
-
|
|
192
|
+
| Use Case | Recommended Approach |
|
|
193
|
+
|----------|---------------------|
|
|
196
194
|
| Web applications (FastAPI, Starlette) | Async `EventStore` |
|
|
197
195
|
| Background workers | Async `EventStore` |
|
|
198
|
-
| CLI tools |
|
|
199
|
-
| Django (without async views) | `
|
|
196
|
+
| CLI tools | `asyncio.run()` wrapper for simplicity |
|
|
197
|
+
| Django (without async views) | `asyncio.run()` wrapper |
|
|
200
198
|
| Testing | Async (with pytest-asyncio) |
|
|
201
199
|
| Jupyter notebooks | Async with `await` |
|
|
202
200
|
|
|
@@ -221,15 +219,14 @@ class EventBus(ABC):
|
|
|
221
219
|
|
|
222
220
|
### Neutral
|
|
223
221
|
|
|
224
|
-
- **
|
|
225
|
-
- **Framework integration varies**: FastAPI and Starlette are async-native; Flask and Django require adaptation
|
|
222
|
+
- **Framework integration varies**: FastAPI and Starlette are async-native; Flask and Django require `asyncio.run()` wrappers
|
|
226
223
|
- **Ecosystem dependency on async-capable drivers**: Must use asyncpg (not psycopg2) for PostgreSQL
|
|
227
224
|
|
|
228
225
|
## References
|
|
229
226
|
|
|
230
227
|
### Code References
|
|
231
228
|
|
|
232
|
-
- `src/eventsource/stores/interface.py` - EventStore
|
|
229
|
+
- `src/eventsource/stores/interface.py` - EventStore ABC
|
|
233
230
|
- `src/eventsource/stores/postgresql.py` - Async PostgreSQL implementation
|
|
234
231
|
- `src/eventsource/stores/in_memory.py` - Async in-memory implementation
|
|
235
232
|
- `src/eventsource/aggregates/repository.py` - Async repository pattern
|