Eventing infrastructure for event sourced architectures.
pip install logicblocks.event.store
from logicblocks.event.store import EventStore, adapters
from logicblocks.event.types import NewEvent
from logicblocks.event.projection import Projector
adapter = adapters.InMemoryStorageAdapter()
store = EventStore(adapter)
stream = store.stream(category="profiles", stream="joe.bloggs")
stream.publish(
events = [
NewEvent(
name="profile-created",
payload={
"name": "Joe Bloggs",
"email": "[email protected]"
}
)
])
stream.publish(
events = [
NewEvent(
name="date-of-birth-set",
payload={
"dob": "1992-07-10"
}
)
]
)
projector = Projector(
handlers={
"profile-created": lambda state, event: state.merge({
"name": event.payload["name"],
"email": event.payload["email"]
}),
"date-of-birth-set": lambda state, event: state.merge({
"dob": event.payload["dob"]
})
}
)
profile = projector.project({}, stream.read())
# profile == {
# "name": "Joe Bloggs",
# "email": "[email protected]",
# "dob": "1992-07-10"
# }
- Event modelling:
- Log / category / stream based: events are grouped into logs of categories of streams.
- Arbitrary payloads and metadata: events can have arbitrary payloads and metadata limited only by what the underlying storage backend can support.
- Bi-temporality support: events included timestamps for both the time the event was created and the time the event was recorded in the log.
- Event storage:
- Immutable and append only: the event store is modelled as an append-only log of immutable events.
- Consistency guarantees: concurrent stream updates can optionally be handled with optimistic concurrency control.
- Write conditions: an extensible write condition system allows pre-conditions to be evaluated before publish.
- Ordering guarantees: event writes are serialised (currently at log level) to guarantee consistent ordering at scan time.
- Thread safety: the event store is thread safe and can be used in multithreaded applications.
- Storage adapters:
- Storage adapter abstraction: adapters are provided for different storage
backends, currently including:
- an in-memory implementation for testing and experimentation; and
- a PostgreSQL backed implementation for production use.
- Extensible to other backends: the storage adapter abstract base class is designed to be relatively easily implemented to support other storage backends.
- Storage adapter abstraction: adapters are provided for different storage
backends, currently including:
- Projections:
- Reduction: event sequences can be reduced to a single value, a projection, using a projector.
- Versioning: projections are versioned based on some attribute of the last event processed (position, sequence number, etc).
- Storage: coming soon.
- Snapshotting: coming soon.
- Types:
- Type hints: includes type hints for all public classes and functions.
- Value types: includes serialisable value types for identifiers, events and projections.
- Pydantic support: coming soon.
- Testing utilities:
- Builders: includes builders for events to simplify testing.
- Data generators: includes random data generators for events and event attributes.
- Storage adapter tests: includes tests for storage adapters to ensure consistency across implementations.
To run the full pre-commit build:
./go
To run tests:
./go library:test:all # all tests
./go library:test:unit # unit tests
./go library:test:integration # integration tests
To perform linting:
./go library:lint:check # check linting rules are met
./go library:lint:fix # attempt to fix linting issues
To format code:
./go library:format:check # check code formatting
./go library:format:fix # attempt to fix code formatting
To run type checking:
./go library:type:check # check type hints
To build packages:
./go library:build
To see all available tasks:
./go -T
Bug reports and pull requests are welcome on GitHub at https://github.com/logicblocks/event.store. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
Copyright © 2024 LogicBlocks Maintainers
Distributed under the terms of the MIT License.