Coverage for src / lexigram / contracts / data / sql / append_log.py: 0%
18 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-15 18:57 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-15 18:57 +0800
1"""Append log protocols for event sourcing.
3This module defines protocols for append-only event log storage,
4used by the event sourcing infrastructure in lexigram-events.
5"""
7from __future__ import annotations
9from typing import Any, Protocol, TypeVar, runtime_checkable
11T = TypeVar("T")
14@runtime_checkable
15class AppendLogProtocol(Protocol[T]):
16 """Protocol for append-only event log storage.
18 This protocol defines the interface for storing and retrieving
19 events in an append-only log structure, typical of event sourcing
20 architectures.
22 Example:
23 ```python
24 class PostgresAppendLog:
25 def __init__(self, pool):
26 self.pool = pool
28 async def append(self, stream_id: str, events: list[Event]) -> int:
29 async with self.pool.acquire() as conn:
30 # Implementation uses parameterized queries
31 pass
33 async def read(self, stream_id: str, from_version: int = 0) -> list[Event]:
34 # Read events from a specific stream version
35 pass
37 async def read_all(self, offset: int = 0, limit: int = 100) -> list[Event]:
38 # Read all events with pagination
39 pass
40 ```
41 """
43 async def append(
44 self,
45 stream_id: str,
46 events: list[T],
47 expected_version: int | None = None,
48 ) -> int:
49 """Append events to a stream.
51 Args:
52 stream_id: Unique identifier for the event stream.
53 events: List of events to append.
54 expected_version: Expected current version for optimistic concurrency.
55 If provided and doesn't match, raise ConflictError.
57 Returns:
58 The new stream version after appending.
60 Raises:
61 ConflictError: If expected_version doesn't match current version.
62 """
63 ...
65 async def read(
66 self,
67 stream_id: str,
68 from_version: int = 0,
69 to_version: int | None = None,
70 ) -> list[T]:
71 """Read events from a stream.
73 Args:
74 stream_id: Unique identifier for the event stream.
75 from_version: Starting stream version (inclusive).
76 to_version: Ending stream version (inclusive). If None, read to end.
78 Returns:
79 List of events from the stream.
80 """
81 ...
83 async def read_all(self, offset: int = 0, limit: int = 100) -> list[T]:
84 """Read all events with pagination.
86 Args:
87 offset: Number of events to skip.
88 limit: Maximum number of events to return.
90 Returns:
91 List of events.
92 """
93 ...
95 async def get_stream_version(self, stream_id: str) -> int:
96 """Get the current version of a stream.
98 Args:
99 stream_id: Unique identifier for the event stream.
101 Returns:
102 Current stream version (0 if stream doesn't exist).
103 """
104 ...
106 async def delete_stream(self, stream_id: str) -> bool:
107 """Delete all events from a stream.
109 Args:
110 stream_id: Unique identifier for the event stream.
112 Returns:
113 True if stream was deleted, False if not found.
114 """
115 ...
117 async def count(self, stream_id: str | None = None) -> int:
118 """Count events in a stream or total events.
120 Args:
121 stream_id: Optional stream ID. If None, count all events.
123 Returns:
124 Number of events.
125 """
126 ...
129from lexigram.contracts.events.protocols import SnapshotStoreProtocol
132@runtime_checkable
133class AppendLogSnapshotStore(SnapshotStoreProtocol, Protocol):
134 """Protocol for aggregate snapshot storage used by append-log.
136 Unlike the event-sourcing snapshot store, this interface includes
137 explicit aggregate type and state serialization helpers. The name has
138 been changed to avoid collision with the generic ``SnapshotStoreProtocol`` used
139 by the events package.
140 """
142 async def save_snapshot(
143 self,
144 aggregate_id: str,
145 aggregate_type: str,
146 version: int,
147 state: dict[str, Any],
148 ) -> None:
149 """Save an aggregate snapshot.
151 Args:
152 aggregate_id: Unique identifier for the aggregate.
153 aggregate_type: Type of the aggregate.
154 version: Snapshot version.
155 state: Serialized aggregate state.
156 """
157 ...
159 async def get_snapshot(self, aggregate_id: str) -> dict[str, Any] | None:
160 """Get the latest snapshot for an aggregate.
162 Args:
163 aggregate_id: Unique identifier for the aggregate.
165 Returns:
166 Snapshot data with version and state, or None if not found.
167 """
168 ...
170 async def delete_snapshots(self, aggregate_id: str) -> int:
171 """Delete all snapshots for an aggregate.
173 Args:
174 aggregate_id: Unique identifier for the aggregate.
176 Returns:
177 Number of snapshots deleted.
178 """
179 ...
182__all__ = ["AppendLogProtocol", "AppendLogSnapshotStore", "T"]