Skip to content

Add SQLite event store implementation#502

Merged
alexeyzimarev merged 5 commits intodevfrom
feature/sqlite-event-store
Mar 3, 2026
Merged

Add SQLite event store implementation#502
alexeyzimarev merged 5 commits intodevfrom
feature/sqlite-event-store

Conversation

@alexeyzimarev
Copy link
Contributor

Summary

  • Add Eventuous.Sqlite package — a full SQLite-based event store implementation for embedded/local apps
  • Extends SqlEventStoreBase<SqliteConnection, SqliteTransaction> from Eventuous.Sql.Base, following the same patterns as PostgreSQL and SQL Server implementations
  • Uses Microsoft.Data.Sqlite ADO.NET provider with WAL mode enabled by default
  • Includes event store, subscriptions (all-stream + per-stream), checkpoint store, projector base class, schema initializer, and DI registration extensions

Base class changes

  • SqlEventStoreBase.AppendEvents — made virtual (SQLite overrides it since it can't use stored procedures)
  • SqlEventStoreBase.Serializer/MetaSerializer — made protected (were private readonly)
  • SqlEventStoreBase.StreamExists — uses Convert.ToBoolean() for cross-DB compatibility (SQLite returns long 0/1, not bool)
  • StoreFixtureBase.EventStore setter — protected set (was protected private set)

SQLite-specific design decisions

  • No stored procedures — append logic is step-by-step C# within a transaction
  • Table name prefix (eventuous_streams, eventuous_messages) instead of SQL schema namespaces
  • Events inserted row-by-row with RETURNING global_position
  • IsTransient always returns false (embedded DB, no network errors)
  • Test fixture uses temp files instead of Docker/Testcontainers

Test plan

  • 23 SQLite-specific tests passing (store: 15, subscriptions: 4, registrations: 2, other: 2)
  • SqlServer and PostgreSQL projects still build cleanly
  • Verify CI passes for all target frameworks (net8.0, net9.0, net10.0)

🤖 Generated with Claude Code

alexeyzimarev and others added 5 commits March 3, 2026 12:52
…ory, and extensions

- Add Microsoft.Data.Sqlite 9.0.6 to Directory.Packages.props
- Make SqlEventStoreBase.AppendEvents virtual for SQLite override
- Promote _serializer/_metaSerializer to protected properties (Serializer/MetaSerializer)
- Create Eventuous.Sqlite project with .csproj, Schema.cs, ConnectionFactory.cs, SqliteExtensions.cs
- Add SQLite DDL schema script with streams, messages, and checkpoints tables

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement SqliteStore extending SqlEventStoreBase<SqliteConnection, SqliteTransaction>
with SQLite-specific logic. Since SQLite has no stored procedures, the AppendEvents
method is overridden directly with C# logic for stream creation, version validation,
event insertion with RETURNING global_position, and stream version update. Includes
read forward/backward queries using JOIN, stream existence check, and truncation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…re, and projector for SQLite

Implements the remaining infrastructure for the SQLite event store:
- SchemaInitializer: hosted service for database schema creation on startup
- RegistrationExtensions: DI registration for SqliteStore, SchemaInitializer, and checkpoint store
- SqliteSubscriptionBase: base class for SQLite polling subscriptions
- SqliteAllStreamSubscription: subscription for all events across streams
- SqliteStreamSubscription: subscription for events in a single stream
- SqliteCheckpointStore: checkpoint persistence in SQLite
- SqliteProjector: base class for SQLite read model projections
- SqliteConnectionOptions: connection configuration record

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create Eventuous.Tests.Sqlite with:
- SqliteStoreFixtureBase: Docker-free fixture using temp SQLite files
- Store tests (Append, Read, OtherMethods) inheriting from base classes
- Subscription tests (SubscribeToAll, SubscribeToStream) with custom fixture
- Registration tests for DI container resolution
- Parallel limiter for test execution

Fix base class issues for SQLite compatibility:
- Change StoreFixtureBase.EventStore setter to protected (was private protected)
- Use Convert.ToBoolean in SqlEventStoreBase.StreamExists for SQLite int returns
- Add InternalsVisibleTo for Eventuous.Tests.Sqlite in Persistence project
- Fix SqliteStore version mismatch message to include WrongExpectedVersion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link

github-actions bot commented Mar 3, 2026

Test Results

 60 files  + 41   60 suites  +41   34m 52s ⏱️ + 23m 41s
320 tests + 31  320 ✅ + 31  0 💤 ±0  0 ❌ ±0 
969 runs  +669  969 ✅ +669  0 💤 ±0  0 ❌ ±0 

Results for commit 4f90f5c. ± Comparison against base commit 3c727b3.

This pull request removes 5 and adds 36 tests. Note that renamed tests count towards both.
Eventuous.Tests.Azure.ServiceBus.IsSerialisableByServiceBus ‑ Passes(2/27/2026 10:15:43 AM +00:00)
Eventuous.Tests.Azure.ServiceBus.IsSerialisableByServiceBus ‑ Passes(2/27/2026 10:15:43 AM)
Eventuous.Tests.Azure.ServiceBus.IsSerialisableByServiceBus ‑ Passes(2d6a86af-9e50-4e9a-85c5-7321a829ce2a)
Eventuous.Tests.Subscriptions.SequenceTests ‑ ShouldReturnFirstBefore(CommitPosition { Position: 0, Sequence: 1, Timestamp: 2026-02-27T10:15:44.3019643+00:00 }, CommitPosition { Position: 0, Sequence: 2, Timestamp: 2026-02-27T10:15:44.3019643+00:00 }, CommitPosition { Position: 0, Sequence: 4, Timestamp: 2026-02-27T10:15:44.3019643+00:00 }, CommitPosition { Position: 0, Sequence: 6, Timestamp: 2026-02-27T10:15:44.3019643+00:00 }, CommitPosition { Position: 0, Sequence: 2, Timestamp: 2026-02-27T10:15:44.3019643+00:00 })
Eventuous.Tests.Subscriptions.SequenceTests ‑ ShouldReturnFirstBefore(CommitPosition { Position: 0, Sequence: 1, Timestamp: 2026-02-27T10:15:44.3019643+00:00 }, CommitPosition { Position: 0, Sequence: 2, Timestamp: 2026-02-27T10:15:44.3019643+00:00 }, CommitPosition { Position: 0, Sequence: 6, Timestamp: 2026-02-27T10:15:44.3019643+00:00 }, CommitPosition { Position: 0, Sequence: 8, Timestamp: 2026-02-27T10:15:44.3019643+00:00 }, CommitPosition { Position: 0, Sequence: 2, Timestamp: 2026-02-27T10:15:44.3019643+00:00 })
Eventuous.Tests.Azure.ServiceBus.IsSerialisableByServiceBus ‑ Passes(049ac118-644c-4516-a249-6c0cb187d95a)
Eventuous.Tests.Azure.ServiceBus.IsSerialisableByServiceBus ‑ Passes(3/3/2026 11:56:37 AM +00:00)
Eventuous.Tests.Azure.ServiceBus.IsSerialisableByServiceBus ‑ Passes(3/3/2026 11:56:37 AM)
Eventuous.Tests.Azure.ServiceBus.IsSerialisableByServiceBus ‑ Passes(3/3/2026 11:56:39 AM +00:00)
Eventuous.Tests.Azure.ServiceBus.IsSerialisableByServiceBus ‑ Passes(3/3/2026 11:56:39 AM)
Eventuous.Tests.Azure.ServiceBus.IsSerialisableByServiceBus ‑ Passes(4d79650d-0872-4328-b061-5f3d246dacfc)
Eventuous.Tests.Azure.ServiceBus.IsSerialisableByServiceBus ‑ Passes(c182dfdb-e279-4ebf-85a4-42533225f93e)
Eventuous.Tests.Sqlite.Registrations.RegistrationTests ‑ Should_resolve_store_with_extensions
Eventuous.Tests.Sqlite.Registrations.RegistrationTests ‑ Should_resolve_store_with_manual_registration
Eventuous.Tests.Sqlite.Store.Append ‑ ShouldAppendOneByOne
…

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new SQLite-backed Eventuous event store implementation (store + subscriptions + checkpointing + schema init + DI extensions) and introduces corresponding SQLite test coverage, plus small base-class tweaks to support SQLite’s non-stored-procedure append path and cross-DB boolean handling.

Changes:

  • Introduce Eventuous.Sqlite package with schema creation, event store, subscriptions (all/stream), checkpoint store, and projector base.
  • Add DI registration extensions and a hosted schema initializer (optional init on startup).
  • Add a new SQLite test project with store/subscription/registration tests and fixture infrastructure; adjust SqlEventStoreBase and StoreFixtureBase visibility/virtualization to enable overrides.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/Sqlite/test/Eventuous.Tests.Sqlite/Subscriptions/SubscriptionFixture.cs New SQLite subscription fixture wiring DI + schema init + temp DB lifecycle for tests
src/Sqlite/test/Eventuous.Tests.Sqlite/Subscriptions/SubscribeTests.cs New tests for all-stream and per-stream SQLite subscriptions + checkpoint behavior
src/Sqlite/test/Eventuous.Tests.Sqlite/Store/StoreTests.cs Hooks SQLite store into shared store conformance test suites
src/Sqlite/test/Eventuous.Tests.Sqlite/Store/StoreFixture.cs Registers SQLite store in test DI container using SQLite fixture base
src/Sqlite/test/Eventuous.Tests.Sqlite/Registrations/RegistrationTests.cs Verifies DI registration paths resolve the SQLite store correctly
src/Sqlite/test/Eventuous.Tests.Sqlite/Limiter.cs Limits SQLite test parallelism to reduce file/db contention
src/Sqlite/test/Eventuous.Tests.Sqlite/Fixtures/SqliteStoreFixtureBase.cs Base fixture for SQLite store tests using temp DB files and hosted schema init
src/Sqlite/test/Eventuous.Tests.Sqlite/Eventuous.Tests.Sqlite.csproj New SQLite test project referencing SQLite package and shared test infrastructure
src/Sqlite/src/Eventuous.Sqlite/Subscriptions/SqliteSubscriptionBase.cs Base subscription implementation for SQLite (connection mgmt + EOS queries)
src/Sqlite/src/Eventuous.Sqlite/Subscriptions/SqliteStreamSubscription.cs Stream subscription implementation (stream id bootstrap + page reads)
src/Sqlite/src/Eventuous.Sqlite/Subscriptions/SqliteCheckpointStore.cs SQLite-backed checkpoint store implementation
src/Sqlite/src/Eventuous.Sqlite/Subscriptions/SqliteAllStreamSubscription.cs All-stream subscription implementation (global position paging)
src/Sqlite/src/Eventuous.Sqlite/SqliteStore.cs SQLite event store implementation with overridden append path
src/Sqlite/src/Eventuous.Sqlite/Scripts/1_Schema.sql Embedded schema script for SQLite tables and indexes
src/Sqlite/src/Eventuous.Sqlite/SchemaInitializer.cs Hosted service to initialize schema on startup (optional)
src/Sqlite/src/Eventuous.Sqlite/Schema.cs Schema/table naming + embedded script execution for schema creation
src/Sqlite/src/Eventuous.Sqlite/Projections/SqliteProjector.cs Projector base to write read models to SQLite via commands
src/Sqlite/src/Eventuous.Sqlite/Projections/SqliteConnectionOptions.cs Options record for projection/subscription/store connection + schema
src/Sqlite/src/Eventuous.Sqlite/Extensions/SqliteExtensions.cs Helpers to create text commands and add parameters
src/Sqlite/src/Eventuous.Sqlite/Extensions/RegistrationExtensions.cs DI extensions for SQLite store, schema init, and checkpoint store
src/Sqlite/src/Eventuous.Sqlite/Eventuous.Sqlite.csproj New SQLite library project, dependencies, and embedded schema resource
src/Sqlite/src/Eventuous.Sqlite/ConnectionFactory.cs SQLite connection factory enabling WAL mode
src/Relational/src/Eventuous.Sql.Base/SqlEventStoreBase.cs Base store adjustments: serializer visibility, virtual append, bool conversion
src/Core/test/Eventuous.Tests.Persistence.Base/Fixtures/StoreFixtureBase.cs Fixture setter visibility change to support derived fixtures
src/Core/src/Eventuous.Persistence/Eventuous.Persistence.csproj Expose internals to new SQLite test assembly
Eventuous.slnx Add SQLite projects to solution structure
Directory.Packages.props Add central package version entry for Microsoft.Data.Sqlite

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@alexeyzimarev
Copy link
Contributor Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4f90f5cf84

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@qodo-free-for-open-source-projects
Copy link
Contributor

ⓘ Your monthly quota for Qodo has expired. Upgrade your plan
ⓘ Paying users. Check that your Qodo account is linked with this Git user account

2 similar comments
@qodo-free-for-open-source-projects
Copy link
Contributor

ⓘ Your monthly quota for Qodo has expired. Upgrade your plan
ⓘ Paying users. Check that your Qodo account is linked with this Git user account

@qodo-free-for-open-source-projects
Copy link
Contributor

ⓘ Your monthly quota for Qodo has expired. Upgrade your plan
ⓘ Paying users. Check that your Qodo account is linked with this Git user account

@alexeyzimarev alexeyzimarev merged commit edc3148 into dev Mar 3, 2026
5 checks passed
@alexeyzimarev alexeyzimarev deleted the feature/sqlite-event-store branch March 3, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants