Skip to main content

Eventing infrastructure for event sourced architectures.

Project description

logicblocks.event.store

PyPI - Version Python - Version Documentation Status CircleCI

Eventing infrastructure for event-sourced architectures.

Table of Contents

Installation

pip install logicblocks-event-store

Usage

Basic Example

import asyncio

from logicblocks.event.store import EventStore, adapters
from logicblocks.event.types import NewEvent, StreamIdentifier
from logicblocks.event.projection import Projector


class ProfileProjector(
    Projector[StreamIdentifier, dict[str, str], dict[str, str]]
):
    def initial_state_factory(self) -> dict[str, str]:
        return {}

    def initial_metadata_factory(self) -> dict[str, str]:
        return {}

    def id_factory(self, state, source: StreamIdentifier) -> str:
        return source.stream

    def profile_created(self, state, event):
        state['name'] = event.payload['name']
        state['email'] = event.payload['email']
        return state

    def date_of_birth_set(self, state, event):
        state['dob'] = event.payload['dob']
        return state


async def main():
    adapter = adapters.InMemoryEventStorageAdapter()
    store = EventStore(adapter)

    stream = store.stream(category="profiles", stream="joe.bloggs")
    profile_created_event = NewEvent(name="profile-created",
                                     payload={"name": "Joe Bloggs", "email": "joe.bloggs@example.com"})
    date_of_birth_set_event = NewEvent(name="date-of-birth-set", payload={"dob": "1992-07-10"})

    await stream.publish(
        events=[
            profile_created_event
        ])
    await stream.publish(
        events=[
            date_of_birth_set_event
        ]
    )

    projector = ProfileProjector()
    projection = await projector.project(source=stream)
    profile = projection.state


asyncio.run(main())


# profile == {
#   "name": "Joe Bloggs", 
#   "email": "joe.bloggs@example.com", 
#   "dob": "1992-07-10"
# }

Features

  • 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 occurred 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 (at log level by default, but customisable) to guarantee consistent ordering at scan time.
    • asyncio support: the event store is implemented using asyncio and can be used in cooperative multitasking 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.
  • Projections:
    • Reduction: event sequences can be reduced to a single value, a projection, using a projector.
    • Metadata: projections have metadata for keeping track of things like update timestamps, versions, etc.
    • Storage: a general purpose projection store allows easy management of projections for the majority of use cases, utilising the same adapter architecture as the event store, with a rich and customisable query language providing store search.
    • 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.

Documentation

Development

To run the full pre-commit build:

mise run

To run tests:

mise test              # all tests
mise test:unit         # unit tests
mise test:integration  # integration tests
mise test:component    # integration tests

The unit, integration and component tests can be run with a filter option allowing running a subset of tests in the suite, for example:

mise test:unit [TestAllTestsInFile]
mise test:component [test_a_specific_test]

To perform linting:

mise lint:check  # check linting rules are met
mise lint:fix    # attempt to fix linting issues

To format code:

mise format:check  # check code formatting
mise format:fix    # attempt to fix code formatting

To run type checking:

mise types:check  # check type hints

To build packages:

mise build

To see all available tasks:

mise tasks ls

Contributing

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.

License

Copyright © 2025 LogicBlocks Maintainers

Distributed under the terms of the MIT License.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

logicblocks_event_store-0.1.10a14.tar.gz (70.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

logicblocks_event_store-0.1.10a14-py3-none-any.whl (121.6 kB view details)

Uploaded Python 3

File details

Details for the file logicblocks_event_store-0.1.10a14.tar.gz.

File metadata

  • Download URL: logicblocks_event_store-0.1.10a14.tar.gz
  • Upload date:
  • Size: 70.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.12 {"installer":{"name":"uv","version":"0.9.12"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for logicblocks_event_store-0.1.10a14.tar.gz
Algorithm Hash digest
SHA256 7491c88a5758b298f7503307b442906c27e45d52b397911e5b552529361135d8
MD5 91fffd1b5ec68a59b1ac375b25af730b
BLAKE2b-256 9e5ce5400cd4ac69241c7a82223effb46d58a697a95d90ee002518f217cedfe0

See more details on using hashes here.

File details

Details for the file logicblocks_event_store-0.1.10a14-py3-none-any.whl.

File metadata

  • Download URL: logicblocks_event_store-0.1.10a14-py3-none-any.whl
  • Upload date:
  • Size: 121.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.12 {"installer":{"name":"uv","version":"0.9.12"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for logicblocks_event_store-0.1.10a14-py3-none-any.whl
Algorithm Hash digest
SHA256 83b5681f2270890692eaca515e0dad525c30bb348dd3da8dc5a44560215b6e1d
MD5 cc807c6a2a67f44f4eef01683f050d85
BLAKE2b-256 27e78d89b5581fe279cdf45b5154566ffc2e856f83dfb9a4447be12ed5dc6fd5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page