logicblocks/event.store
61.5
Adequate · 21 September 2026
11.7k
lines of production code
Python
primary language
4
measurements over time
What this system is
This system is an event sourcing and processing library that provides a complete infrastructure for building distributed, event-driven applications. It manages the persistence of events and projections using both in-memory and PostgreSQL backends, supporting flexible query and filtering capabilities. The framework also includes abstractions for distributed event brokers, asynchronous consumers, and state management, enabling robust handling of event streams and subscriber coordination.
Features
Add PostgreSQL schema definitions and indexes for event, projection, and subscription stores
The system now includes SQL scripts to create the underlying database tables and indexes for the event store, projection store, and subscriber/subscription stores. Specifically, the \events\ table is defined with columns for id, name, stream, category, position, payload, metadata, sequence\_number, and timestamps, along with composite indexes on category, stream, and sequence\_number to optimize query performance. The \projections\ table stores state keyed by name and id, while \subscribers\ and \subscriptions\ tables track subscriber groups and node associations. Additionally, the \pg\_trgm\ extension is enabled to support text similarity operations.
sql · high confidence
Add in-memory and PostgreSQL lock managers for event processing
The \src/logicblocks/event/processing/locks\ package now provides two concrete implementations of the \LockManager\ interface: \InMemoryLockManager\ for local, non-persistent locking, and \PostgresLockManager\ which uses PostgreSQL advisory locks for distributed coordination. Both implement \try\_lock\ and \wait\_for\_lock\ methods, allowing event processing logic to acquire and wait for locks with configurable timeouts.
src/logicblocks/event/processing/locks · high confidence
Add in-memory event subscriber store implementation
The event processing broker now includes an in-memory implementation of the event subscriber store, allowing subscribers to be registered, removed, and listed in memory. This provides a lightweight, non-persistent storage option for event subscribers, complementing the existing PostgreSQL-based broker implementation.
src/logicblocks/event/processing/broker/subscribers/stores/instances · high confidence
Add singleton event broker implementation
A new singleton event broker strategy has been introduced, providing a single-instance event processing loop that periodically polls for events and distributes them to registered subscribers. The implementation includes a core \SingletonEventBroker\ class that manages the main processing loop, along with builder classes and factory functions (\make\_in\_memory\_singleton\_event\_broker\ and \make\_postgres\_singleton\_event\_broker\) to construct the broker for either in-memory or PostgreSQL-backed event storage. This adds a new way to run event processing as a singleton process rather than relying on other broker strategies.
src/logicblocks/event/processing/broker/strategies/singleton · high confidence
Initial project scaffolding and tooling setup
The repository was initialized with a comprehensive development environment, including a \mise.toml\ configuration for managing Python 3.13 and the \uv\ package manager, alongside task scripts for linting, formatting, and testing. The project also includes a \docker-compose.yml\ for PostgreSQL integration tests, a \mkdocs.yml\ for documentation, and a \uv.lock\ file pinning all Python dependencies. This establishes the baseline for building, testing, and maintaining the event store library.
(repo-wide) · high confidence
Introduce Projector and ProjectionStore abstractions for event projection
The event projection subsystem now provides a \Projector\ base class that manages the lifecycle of projecting events into state, supporting configurable missing-handler behavior and metadata updates. A \ProjectionStore\ interface and its \InMemoryProjectionStorageAdapter\ and \PostgresProjectionStorageAdapter\ implementations allow pluggable storage for projections. These changes enable users to define custom projectors and choose their preferred storage backend for projection state.
src/logicblocks/event/projection · high confidence
Introduce abstract event storage adapter with in-memory and Postgres implementations
The event store now uses a new abstract \EventStorageAdapter\ interface that defines how events are persisted and retrieved. This change introduces concrete implementations for both in-memory and Postgres-backed storage, allowing the application to persist events with configurable serialisation guarantees (log, category, or stream level) and write conditions. Users can now choose between an in-memory adapter for testing or lightweight scenarios, or a Postgres adapter for production use, with the latter supporting features like page scans and stream-level serialisation guarantees.
src/logicblocks/event/store/adapters · high confidence
Introduce async EventStore with write conditions and transactional wrappers
The event store module now provides an asynchronous event storage interface (EventStore, EventStream, EventCategory, and EventLog) backed by pluggable storage adapters. Users can publish events with optional write conditions (e.g., position or empty stream checks) and use transactional decorators (retry or ignore on errors) to manage concurrency and reliability.
src/logicblocks/event/store · high confidence
Introduce distributed event broker with coordinator, observer, and subscriber management
A new distributed event broker implementation is added to the codebase, providing a scalable way to manage event processing across multiple nodes. This includes a \DistributedEventBroker\ that coordinates subscriptions, observes state changes, and manages subscribers with heartbeat and purge cycles. The change introduces key components such as \EventSubscriptionCoordinator\ for leader election and distribution, \EventSubscriptionObserver\ for synchronizing state, and \EventSubscriberManager\ for handling subscriber lifecycle. Factories are provided to instantiate in-memory or PostgreSQL-backed brokers, allowing for flexible deployment options. The broker also integrates error handling and process status tracking.
src/logicblocks/event/processing/broker/strategies/distributed · high confidence
Introduce distributed event processing and error handling abstractions
The \src/logicblocks/event/processing\ module now exposes a comprehensive set of classes and functions for building distributed event-driven systems. This includes the \EventBroker\ interface with \make\_in\_memory\_event\_broker\ and \make\_postgres\_event\_broker\ factories, alongside a \SingletonEventBroker\ for single-instance scenarios. The update also introduces a robust error handling framework featuring \ErrorHandlingService\, \ErrorHandlingServiceMixin\, and various \ErrorHandler\ implementations (e.g., \RetryErrorHandler\, \ExitErrorHandler\) with configurable \RetryStrategy\ behaviors. Additionally, it provides core infrastructure for asynchronous consumers, including \EventConsumer\, \EventProcessor\, and state management classes like \EventConsumerState\ and \EventConsumerStateStore\. A \NOTES.md\ file documents the architectural design for async consumers, partitioning, and subscription management.
src/logicblocks/event/processing · high confidence
Introduce event consumer state management and persistence
Added a new state management system for event consumers, including the \EventConsumerState\ dataclass and \EventConsumerStateStore\ for tracking and persisting consumer progress. The \StoredEventEventConsumerStateConverter\ is introduced to handle state serialization, deserialization, and query constraints for stored events. A \reset\ method is added to \EventConsumerStateStore\ to allow resetting consumer state, and backwards compatibility is supported for missing or \None\ states during deserialization.
src/logicblocks/event/processing/consumers/state · high confidence
Introduce in-memory and Postgres stores for distributed subscriber state
The broker now persists distributed subscriber state using a new \state\ package containing an \InMemoryEventSubscriberStateStore\ and a \PostgresEventSubscriberStateStore\. These implementations provide the \add\, \remove\, \list\, \heartbeat\, and \purge\ operations required to track and manage the state of event subscribers in a distributed environment, with the Postgres store handling persistence via SQL queries and the in-memory store providing a temporary alternative.
src/logicblocks/event/processing/broker/strategies/distributed/subscribers/stores/state · high confidence
Introduce in-memory event store adapter with category-level publishing and condition enforcement
The in-memory event store adapter now supports publishing events at the category level, allowing multiple streams to be written in a single operation. The adapter also enforces write conditions (such as position or empty stream checks) using a converter-based system, and includes a multi-lock mechanism to ensure thread safety during concurrent writes.
src/logicblocks/event/store/adapters/memory · high confidence
Introduce modular event source abstractions and in-memory implementation
The event source logic has been reorganized into a dedicated \sources\ package, providing a generic \EventSource\ base class that supports constraint-based filtering and asynchronous iteration. This change introduces a \ConstrainedEventSource\ decorator for applying query constraints, a \QueryConstraint\ system for filtering events, and a new \InMemoryEventSource\ implementation for testing and development. These components are exported via \\_\all\\\ in the package's \\\init\\_.py\, making the new interfaces and implementations available for use across the application.
src/logicblocks/event/sources · high confidence
Introduce new event processing consumer architecture
Added a new event processing consumer architecture in the \src/logicblocks/event/processing/consumers\ module, introducing \EventSourceConsumer\ and \EventSubscriptionConsumer\ to handle event iteration and state management. The update includes a \ProjectionEventProcessor\ for handling projections, factory functions \make\_subscriber\ and \make\_event\_store\_subscriber\ for creating subscription-based consumers, and supporting types like \AutoCommitEventIteratorProcessor\ and \ManagedEventIteratorProcessor\ to define how events are processed and committed.
src/logicblocks/event/processing/consumers · high confidence
Introduce pluggable projection storage adapters
The projection store now supports multiple storage backends via a new \ProjectionStorageAdapter\ interface. Users can choose between an in-memory adapter for testing or lightweight use cases, and a Postgres adapter for production workloads. Both adapters implement the same \save\, \find\_one\, \find\_many\, and \count\ methods, allowing the rest of the application to remain agnostic about the underlying storage mechanism.
src/logicblocks/event/projection/store/adapters · high confidence
Introduce process status tracking and multi-process status aggregation
A new process status tracking system has been introduced, defining a \ProcessStatus\ enum with states such as \initialised\, \starting\, \running\, \stopped\, and \unknown\. The \Process\ base class and \HasProcessStatus\ protocol are added to standardize status reporting. Additionally, a \determine\_multi\_process\_status\ function is provided to aggregate the statuses of multiple processes into a single representative status, handling edge cases like mixed states and errors.
src/logicblocks/event/processing/process · high confidence
Introduce service management and execution framework
The event processing logic now includes a comprehensive service management system. This adds a \ServiceManager\ to coordinate and track the lifecycle of background tasks, supporting both main-thread and isolated-thread execution modes. It introduces abstractions for services, including \CallableService\ to wrap callables, \PollingService\ for repeated execution, and \StatusTrackingService\ for monitoring state. The framework also provides built-in error handling and retry strategies, allowing developers to define how services should behave when they fail or need to be retried.
src/logicblocks/event/processing/services · high confidence
Introduce structured event and projection types with JSON serialization
The \src/logicblocks/event/types\ module now provides a comprehensive set of types for event sourcing and projections. This includes \NewEvent\ and \StoredEvent\ classes that support generic payloads and metadata, along with a \Projection\ type for storing state. The change introduces robust JSON serialization and deserialization logic via \JsonValue\ protocols and conversion utilities, allowing events and projections to be easily converted to and from JSON values. Additionally, identifier types like \EventSourceIdentifier\, \StreamIdentifier\, and \CategoryIdentifier\ are defined to represent event sources and partitions in a structured way.
src/logicblocks/event/types · high confidence
Introduce subscription state management with in-memory and Postgres backends
Added new modules for managing event subscription states, including abstract base classes and concrete implementations for both in-memory and Postgres-backed storage. The change introduces \EventSubscriptionStateStore\ as an abstract interface, with \InMemoryEventSubscriptionStateStore\ and \PostgresEventSubscriptionStateStore\ providing specific storage mechanisms. This allows the distributed broker strategy to persist and retrieve subscription states using either a simple in-memory store for testing or a Postgres database for production use.
src/logicblocks/event/processing/broker/strategies/distributed/subscriptions · high confidence
New query and clause data types for event queries
A new top-level package for query datatypes has been created, introducing structured types for query components including filters, sorting, and paging. This includes new classes for operators (such as REGEX\_MATCHES and NOT\_REGEX\MATCHES), clauses (FilterClause, SortClause, PagingClause), and query types (Search, Lookup). The module also introduces support for functions (e.g., Similarity) and a Path utility for field references, with all public types exported via \\all\\_.
src/logicblocks/event/query · high confidence
Behavioural changes
Add clock abstraction and utility helpers
The event logic now includes a clock abstraction (Clock, SystemClock, StaticClock, and TimezoneRequiredStaticClock) to manage time, which ensures consistent UTC datetime usage for operations like heartbeats. Additionally, utility functions for class naming and type hinting support have been added to the utils package.
src/logicblocks/event/utils · medium confidence
Adopts Invoke for task management and uv for dependency/build operations
The project's task management has been migrated to the Invoke framework, providing a structured set of commands for building, testing, linting, and releasing. The build process now utilizes uv for package building and dependency synchronization, while the type-checking tool has been switched from pyright to pyrefly. Additionally, the test runner has been updated to use pytest with coverage reporting, and the release workflow has been reorganized to handle version bumps and publishing via uv.
tasks · high confidence
Centralized version retrieval via uv
The project has introduced a shared utility in tasks/shared/project.py that retrieves the current version string by executing 'uv version --short --no-color'. This change, supported by the addition of the shared module files, provides a consistent, color-free method for other tasks to determine the project version using the uv tool.
tasks/shared · medium confidence
Introduce ProjectionStore with in-memory and Postgres adapters
A new ProjectionStore class has been added to manage projection storage, supporting both in-memory and Postgres-backed adapters. The store exposes methods to save, locate, load, and search for projections, with logging enabled for each operation. This change introduces the core abstraction for projection storage, allowing users to interact with projections via a consistent interface regardless of the underlying storage mechanism.
src/logicblocks/event/projection/store · high confidence
Introduce generic EventSourceFactory base class
A new base class, EventSourceFactory, has been added to the factory module. This class is now generic over the event type, enforcing that the factory produces EventSource instances for a specific event type. This change refines the API by making the factory's output type more specific and type-safe.
src/logicblocks/event/sources/factory · high confidence
Introduce persistence package with type registry converter
The src/logicblocks/event/persistence package has been created to centralize event persistence logic. It introduces a TypeRegistryConverter class that manages a registry of type-specific converters, allowing for flexible conversion of event data. The package also includes a postgres module and exports the converter via \_\all\\_. A py.typed file has been moved to this new location to support type checking.
src/logicblocks/event/persistence · medium confidence
Introduce singleton and distributed event broker strategies
Users can now choose between a singleton or distributed event broker implementation. The broker package now exposes two distinct strategies: a SingletonEventBroker for single-process scenarios and a DistributedEventBroker for multi-process environments. Both strategies provide in-memory and Postgres-backed implementations, allowing users to select the appropriate concurrency model for their deployment.
src/logicblocks/event/processing/broker/strategies · high confidence
Postgres adapter implements converter-based write condition enforcement
The Postgres event store adapter now uses a converter-based approach to enforce write conditions (such as position or empty stream checks) against the database. This refactors how the adapter validates state before writing events, moving from direct checks to a structured \WriteConditionEnforcer\ system that translates logical conditions into database-level constraints, improving how the adapter handles write conflicts and state validation.
src/logicblocks/event/store/adapters/postgres · high confidence
Refactor error handling to support configurable retry strategies
The error handling service now supports configurable retry strategies, allowing users to define how and when to retry failed events. This is achieved by introducing a \RetryStrategy\ interface with implementations like \ConstantRetryStrategy\, \IncludeExceptionsRetryStrategy\, and \ExcludeExceptionsRetryStrategy\. The \RetryErrorHandler\ now uses these strategies to determine whether to retry immediately, wait for a specified duration, or override the default behavior. This change enables more granular control over error recovery, such as excluding specific exceptions from retrying or applying different wait times based on the exception type.
src/logicblocks/event/processing/services/error · high confidence
Refactor in-memory persistence layer into a modular converter architecture
The in-memory persistence implementation has been restructured into a modular converter architecture, introducing dedicated classes for handling query, clause, and function transformations. This includes new support for regex-based filtering (REGEX\_MATCHES and NOT\_REGEX\_MATCHES operators) and similarity scoring functions, alongside a more flexible query conversion pipeline that composes these transformations. Users benefit from a more robust and extensible in-memory query engine that correctly handles None values in regex searches and supports advanced filtering and sorting capabilities.
src/logicblocks/event/persistence/memory · high confidence
Refactored Postgres persistence layer with new query and settings modules
The Postgres persistence implementation has been restructured into dedicated modules for query construction, type definitions, and configuration. This introduces a new query builder infrastructure that supports SQL functions, casting, and column references, alongside dedicated settings classes for database connections and table configurations. These changes provide a more modular and type-safe approach to generating and managing Postgres queries within the event persistence system.
src/logicblocks/event/persistence/postgres · medium confidence
Refactored Postgres query conversion to a modular converter architecture
The Postgres persistence layer now uses a new converter-based architecture to translate generic query objects into Postgres-specific SQL. This introduces dedicated converters for clauses (filters, sorting, paging) and functions (such as similarity), allowing for more flexible and maintainable query generation. The system now supports IS\_NULL/IS\_NOT\_NULL operators, a NOT\_REGEX\_MATCHES operator, and general function support in the query/converter infrastructure.
src/logicblocks/event/persistence/postgres/converters · medium confidence
Refactored event broker architecture with unified factory and storage abstraction
The event broker implementation has been restructured to support both in-memory and Postgres storage backends through a unified \make\_event\_broker\ factory. This change introduces a new \EventBroker\ base class and a \EventBrokerStorageType\ abstraction, allowing users to construct distributed or singleton brokers with either in-memory or Postgres storage. The previous \make\_in\_memory\_event\_broker\ and \make\_postgres\_event\_broker\ functions are now deprecated in favor of the new unified factory, which handles the routing logic. Additionally, the \EventSubscriber\ interface has been updated to include health status tracking and subscription request management.
src/logicblocks/event/processing/broker · medium confidence
Restructured event subscriber store modules
The event broker's subscriber store implementation has been reorganized into a new package structure. The \subscribers\ module now exposes \EventSubscriberStore\ and \InMemoryEventSubscriberStore\ via a dedicated \stores\ subpackage, centralizing the definitions for both in-memory and persistent (Postgres) subscriber storage backends.
src/logicblocks/event/processing/broker/subscribers · medium confidence
Test coverage
Add integration tests for the Postgres projection storage adapter; Add unit tests for the SingletonEventBroker; Added component tests for event processing and asynchronous projections; Added integration tests for Postgres-backed event processing components; Added shared test support utilities for event processing; Added test cases for event processing components; Added test configuration for event logic blocks; Added test infrastructure for event broker integration tests; Added test logging utilities for event-based testing; Added test utilities for event and projection builders; Added tests for InMemoryEventSubscriberStore; Added tests for event processing logic blocks; Added tests for event store adapters; Added tests for projection store adapters; Added unit tests for InMemoryLockManager; Added unit tests for Postgres persistence components; Added unit tests for distributed event broker components; Added unit tests for error handling and retry strategies; Added unit tests for event broker factories; Added unit tests for event builders and data generation utilities; Added unit tests for event query logic; Added unit tests for event source implementations; Added unit tests for event store adapters; Added unit tests for event store conditions, transactions, and types; Added unit tests for event types, identifiers, and projections; Added unit tests for in-memory persistence converters; Added unit tests for multi-process status determination; Added unit tests for the in-memory projection storage adapter; Added unit tests for the in-memory projection store; Added unit tests for the redesigned Projector; Integration tests for Postgres event storage adapter.
Dependencies
Migrate from Poetry to Hatch and update project metadata
The project has switched its build system from Poetry to Hatch, replacing the \poetry.lock\ file and updating \pyproject.toml\ to use \hatchling\ as the build backend. The package name was changed to \logicblocks.event.store\, the Python version requirement was updated to \\>=3.13\, and the project now includes explicit dependency declarations for libraries such as \psycopg\, \uvloop\, and \structlog\. Additionally, the project added a \pyrefly\ configuration for type checking and updated the author list to include Jonas Svalin.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.
Score
- CAI 60 → 62 (+1.4)
- Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 91 → 95 (+3.6)
- Architecture 96 → 77 (-19.2)
- Maturity 53 → 53 (-0.2)
- Readiness 55 → 56 (+1.5)
- Security 58 → 83 (+24.8)
Resolved (22)
- Change coupling: memory.py ↔ postgres.py (src/logicblocks/event/processing/broker/strategies/distributed/subscribers/stores/state/memory.py)
- Change coupling: memory.py ↔ store.py (src/logicblocks/event/projection/store/adapters/memory.py)
- Coverage not included — suite not readable by the collector
- Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
- Duplicated block (10 lines × 2) (src/logicblocks/event/persistence/postgres/query.py)
- Duplicated block (13 lines × 2) (src/logicblocks/event/store/adapters/memory/adapter.py)
- Duplicated block (15 lines × 2) (src/logicblocks/event/persistence/postgres/converters/clause.py)
- Duplicated block (17 lines × 2) (src/logicblocks/event/persistence/postgres/converters/clause.py)
- Duplicated block (17 lines × 2) (src/logicblocks/event/persistence/postgres/converters/clause.py)
- Duplicated block (18 lines × 2) (src/logicblocks/event/store/adapters/memory/adapter.py)
- Duplicated block (8 lines × 2) (src/logicblocks/event/processing/broker/strategies/distributed/subscribers/stores/state/postgres.py)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- Medium CVE: [GHSA redacted] (uv.lock)
- Medium CVE: PYSEC-2026-2132 (uv.lock)
- No exposed public API
- …and 2 more
New (42)
- Banned license: psycopg
- Dependency hygiene PARTLY measured — Python dependencies read, no exact pin to grade for currency
- Documentation: no installation or build instructions (README.md)
- Documentation: no usage examples (README.md)
- Duplicated block (10 lines × 2) (src/logicblocks/event/persistence/postgres/query.py)
- Duplicated block (16 lines × 2) (src/logicblocks/event/persistence/postgres/converters/clause.py)
- Duplicated block (19 lines × 2) (src/logicblocks/event/persistence/postgres/converters/clause.py)
- Duplicated block (21 lines × 2) (src/logicblocks/event/store/adapters/memory/adapter.py)
- Duplicated block (39–45 lines × 2) (src/logicblocks/event/store/adapters/memory/adapter.py)
- Duplicated block (43–44 lines × 2) (src/logicblocks/event/persistence/postgres/converters/clause.py)
- Duplicated block (7 lines × 2) (src/logicblocks/event/store/adapters/memory/converters.py)
- Duplicated block (8 lines × 2) (src/logicblocks/event/processing/broker/strategies/distributed/subscribers/stores/state/postgres.py)
- Excessive method proliferation in clause module for paging queries. There are 5 methods for 'first page' alone, differentiated by sort state and direction. This is a code smell indicating a lack of abstraction or a complex conditional logic that should be encapsulated in a single method with parameters.
- Extreme method proliferation in clause module for subsequent page queries. There are 9 methods for 'subsequent pages', combining sort state, direction, and pagination direction (forward/backward). This is highly redundant and difficult to maintain.
- Further sole-owners (lower concentration)
- High CVE: [GHSA redacted] (uv.lock)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- …and 22 more
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
logicblocks/event.store was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 21 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 4d496b24bddaee28a7d45df54721ce3461a58f5f — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-fa71c66cabd8.