Skip to content

api: expose the shared engine facade - #25

Merged
0xgleb merged 2 commits into
masterfrom
feat/0.4-engine-ffi
Jul 16, 2026
Merged

0xgleb merged 2 commits into
masterfrom
feat/0.4-engine-ffi

Conversation

@0xgleb

@0xgleb 0xgleb commented Jul 15, 2026 •

Copy link
Copy Markdown
Member

Publish the extracted Engine, stream identity, commit request, snapshot update, and error types for the C ABI crate instead of creating a second storage implementation.

Engine migration now owns the existing sqlite-es MIGRATOR path, and the native SqliteBackend delegates to it. The facade remains the same cqrs-es, Apalis, SQLx, and SQLite implementation characterized downstack.

Closes #61.


This is part 7 of 32 in a stack made with GitButler:

Summary by CodeRabbit

  • New Features
    • Expanded the public API for the SQLite event storage engine by exposing engine/request/response types, constructors, and related errors.
    • Added public engine operations, including schema migration, bounded event paging, snapshot loading, current version lookup, and commit.
    • Re-exported engine types from the crate root for easier access.
  • Bug Fixes
    • Snapshot attachment is now correctly rejected for empty event batches, propagating a clear engine error and preventing unintended writes.
    • Migration now uses the engine migration path directly, with updated SQL error mapping.
  • Tests
    • Updated/added coverage for engine migration, bounded paging, empty-snapshot rejection, and post-migration commit behavior.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c162b4a0-d3f9-4c9f-aa69-ce944c45e048

📥 Commits

Reviewing files that changed from the base of the PR and between ed8d725 and 22d3a7e.

📒 Files selected for processing (1)
  • crates/event-sorcery/src/engine.rs
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Before work, read SPEC.md and docs/domain.md; read relevant supplemental documentation before implementation.
New features must be documented in SPEC.md before implementation and must follow the hierarchy SPEC.md -> issue -> plan -> tests -> implementation.
Fix all known problems immediately, complete all tasks, and do not allow warnings or errors to pass through.
Keep a granular task list and clear completed tasks from the active list.
All new or modified logic must have corresponding test coverage.
Understand relevant documentation and source code before implementation, keep diffs small, and review the approach critically.
When changing direction or making an important undocumented architectural decision, obtain confirmation; record significant decisions as ADRs under adrs/.
Before handover, review the diff, revert unjustified changes, and check for scope creep.
Each aggregate in a consuming application must use exactly one SqliteCqrs instance constructed at startup; per-request construction is forbidden.
Never read secret or credential files such as .env*, credentials.json, *.key, *.pem, *.p12, *.pfx, or sensitive database files without explicit permission.
Never bypass, disable, suppress, or obscure quality-control mechanisms without explicit permission; fix lint and test issues at their root.
Use cargo check, cargo nextest, and cargo clippy for verification; never use cargo build unless build artifacts are required.

Files:

  • crates/event-sorcery/src/engine.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Organize code by business feature rather than technical layer; avoid catch-all modules such as types.rs, error.rs, models.rs, utils.rs, helpers.rs, and services.rs.
Never write directly to the events table; emit events through CqrsFramework::execute() or execute_with_metadata().
Use cqrs-es Services for side effects in handle() and follow the {Action}er -> {Domain}Service -> {Domain}Manager naming pattern.
Place command-execution logging in aggregate handle() methods rather than callers.
Model invalid states with enums, ADTs, newtypes, and typestate rather than relying on runtime validation.
Use domain newtypes at APIs and convert to SDK primitives inside the callee, except at cross-crate boundaries where conversion at the call site is necessary.
Keep visibility as restrictive as possible: private over pub(crate) over pub.
Use a three-group import order: external crates, workspace crates, then crate-internal imports; do not use function-level imports except enum variants.
Do not use unwrap() or expect() in production Rust code; they are permitted in #[cfg(test)] code.
Never create error variants containing opaque String values; prefer #[from], ?, #[source], and preserve error chains.
Log a warning or error before silent early returns such as let-else failures.
Never silently mask numeric failures with caps, fallback defaults, precision truncation, unwrap_or(), or unwrap_or_default(); use explicit checked conversions and errors.
Prefer functional patterns, pattern matching, combinators, type-driven design, and iterators over imperative loops unless complexity increases.
Use ASCII in identifiers, comments, log messages, and configuration keys; Unicode is preferred only in user-facing rendered output.
Do not use single-letter variables, arguments, closure parameters, or generic type parameters except an unambiguous lone type parameter or short unambiguous closure.
Every module must have a //! docstring and should order public API, private implementati...

Files:

  • crates/event-sorcery/src/engine.rs
🔇 Additional comments (2)
crates/event-sorcery/src/engine.rs (2)

6-7: LGTM!

Also applies to: 19-60, 69-76, 96-98, 107-118, 130-151, 172-228, 228-388, 471-546, 733-733, 782-796, 801-821, 834-872, 933-941, 953-954


797-800: 📐 Maintainability & Code Quality

Keep the direct in-memory pool here. sqlite_es::testing::create_test_pool() applies migrations, so it would defeat this test's unmigrated-schema setup.

			> Likely an incorrect or invalid review comment.

Walkthrough

Changes

The SQLite engine facade and related request types are made public, bounded event paging and version reads are exposed, snapshot attachment now validates persisted events, and backend schema migration delegates through Engine::migrate().

Engine facade and commit flow

Layer / File(s) Summary
Public engine API
crates/event-sorcery/src/engine.rs, crates/event-sorcery/src/lib.rs
Engine request types, errors, constructors, storage operations, job operations, event paging, version reads, row mapping, tests, and crate re-exports are made public.
Snapshot attachment validation
crates/event-sorcery/src/engine.rs, crates/event-sorcery/src/sqlite_event_repository.rs
Snapshot attachment now returns an error when no events are persisted, and repository persistence propagates that result without writing events or snapshots.
Engine migration routing
crates/event-sorcery/src/engine.rs, crates/event-sorcery/src/job_sqlite.rs
Schema migration is exposed through Engine::migrate() and SqliteBackend delegates migration to it; migration coverage verifies subsequent commits.

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes exposing the shared engine facade.
Linked Issues check ✅ Passed The changes expose the shared engine facade and related types as required by issue #61.
Out of Scope Changes check ✅ Passed The additional migration and persistence updates support the same engine facade objective and appear in scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/0.4-engine-ffi

Comment @coderabbitai help to get the list of available commands.

@0xgleb
0xgleb force-pushed the feat/0.4-job-engine-facade branch from 728a17c to 58ff308 Compare July 15, 2026 05:11
@0xgleb
0xgleb force-pushed the feat/0.4-engine-ffi branch from 13bb559 to 5d46691 Compare July 15, 2026 05:11
@0xgleb
0xgleb force-pushed the feat/0.4-job-engine-facade branch from 58ff308 to d4b3ef1 Compare July 15, 2026 06:24
@0xgleb
0xgleb force-pushed the feat/0.4-engine-ffi branch from 5d46691 to 7e3232b Compare July 15, 2026 06:24
@0xgleb
0xgleb force-pushed the feat/0.4-job-engine-facade branch from d4b3ef1 to 77c3ba8 Compare July 15, 2026 07:41
@0xgleb
0xgleb force-pushed the feat/0.4-engine-ffi branch from 7e3232b to 277ac60 Compare July 15, 2026 07:41
@0xgleb
0xgleb force-pushed the feat/0.4-job-engine-facade branch from 77c3ba8 to 089e5c2 Compare July 15, 2026 09:21
@0xgleb
0xgleb force-pushed the feat/0.4-engine-ffi branch from 277ac60 to 350262e Compare July 15, 2026 09:21
@0xgleb
0xgleb force-pushed the feat/0.4-job-engine-facade branch from 089e5c2 to 8bb49f6 Compare July 15, 2026 09:40
@0xgleb
0xgleb force-pushed the feat/0.4-engine-ffi branch from 350262e to 3e8cffd Compare July 15, 2026 09:40
@0xgleb
0xgleb force-pushed the feat/0.4-job-engine-facade branch from 8bb49f6 to d090e49 Compare July 15, 2026 16:31
@0xgleb
0xgleb force-pushed the feat/0.4-engine-ffi branch 2 times, most recently from b3875b8 to 7aa769e Compare July 16, 2026 15:58
@0xgleb
0xgleb enabled auto-merge July 16, 2026 15:58
@0xgleb

0xgleb commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/event-sorcery/src/job_sqlite.rs`:
- Line 78: Add a backend-level test for SqliteBackend::migrate that uses an
in-memory SQLite database and invokes migration through the EventBackend
interface, rather than calling Engine::migrate directly. Preserve the existing
migration assertions while covering the SqliteBackend implementation path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9e9d506b-ef4e-4159-8ff3-9551d14df7ed

📥 Commits

Reviewing files that changed from the base of the PR and between 0e79e4c and 7aa769e.

📒 Files selected for processing (4)
  • crates/event-sorcery/src/engine.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/sqlite_event_repository.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Before work, read SPEC.md and docs/domain.md; read relevant supplemental documentation before implementation.
New features must be documented in SPEC.md before implementation and must follow the hierarchy SPEC.md -> issue -> plan -> tests -> implementation.
Fix all known problems immediately, complete all tasks, and do not allow warnings or errors to pass through.
Keep a granular task list and clear completed tasks from the active list.
All new or modified logic must have corresponding test coverage.
Understand relevant documentation and source code before implementation, keep diffs small, and review the approach critically.
When changing direction or making an important undocumented architectural decision, obtain confirmation; record significant decisions as ADRs under adrs/.
Before handover, review the diff, revert unjustified changes, and check for scope creep.
Each aggregate in a consuming application must use exactly one SqliteCqrs instance constructed at startup; per-request construction is forbidden.
Never read secret or credential files such as .env*, credentials.json, *.key, *.pem, *.p12, *.pfx, or sensitive database files without explicit permission.
Never bypass, disable, suppress, or obscure quality-control mechanisms without explicit permission; fix lint and test issues at their root.
Use cargo check, cargo nextest, and cargo clippy for verification; never use cargo build unless build artifacts are required.

Files:

  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/sqlite_event_repository.rs
  • crates/event-sorcery/src/engine.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Organize code by business feature rather than technical layer; avoid catch-all modules such as types.rs, error.rs, models.rs, utils.rs, helpers.rs, and services.rs.
Never write directly to the events table; emit events through CqrsFramework::execute() or execute_with_metadata().
Use cqrs-es Services for side effects in handle() and follow the {Action}er -> {Domain}Service -> {Domain}Manager naming pattern.
Place command-execution logging in aggregate handle() methods rather than callers.
Model invalid states with enums, ADTs, newtypes, and typestate rather than relying on runtime validation.
Use domain newtypes at APIs and convert to SDK primitives inside the callee, except at cross-crate boundaries where conversion at the call site is necessary.
Keep visibility as restrictive as possible: private over pub(crate) over pub.
Use a three-group import order: external crates, workspace crates, then crate-internal imports; do not use function-level imports except enum variants.
Do not use unwrap() or expect() in production Rust code; they are permitted in #[cfg(test)] code.
Never create error variants containing opaque String values; prefer #[from], ?, #[source], and preserve error chains.
Log a warning or error before silent early returns such as let-else failures.
Never silently mask numeric failures with caps, fallback defaults, precision truncation, unwrap_or(), or unwrap_or_default(); use explicit checked conversions and errors.
Prefer functional patterns, pattern matching, combinators, type-driven design, and iterators over imperative loops unless complexity increases.
Use ASCII in identifiers, comments, log messages, and configuration keys; Unicode is preferred only in user-facing rendered output.
Do not use single-letter variables, arguments, closure parameters, or generic type parameters except an unambiguous lone type parameter or short unambiguous closure.
Every module must have a //! docstring and should order public API, private implementati...

Files:

  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/sqlite_event_repository.rs
  • crates/event-sorcery/src/engine.rs
🔇 Additional comments (4)
crates/event-sorcery/src/engine.rs (2)

17-63: LGTM!

Also applies to: 67-74, 94-117, 385-460, 800-808, 820-821


705-710: 🎯 Functional Correctness

Leave the raw pool here. create_test_pool() applies migrations up front, so it would skip the path this test is meant to cover, and the repository’s SQLite fixture also uses :memory:.

			> Likely an incorrect or invalid review comment.
crates/event-sorcery/src/sqlite_event_repository.rs (1)

125-125: LGTM!

crates/event-sorcery/src/lib.rs (1)

128-128: 🗄️ Data Integrity & Integration

No additional re-exports needed here. The crate root already exposes SqliteJobError, ClaimDecision, ClaimOutcome, ClaimRead, and LeaseRenewal, so the public Engine surface is reachable as-is.

			> Likely an incorrect or invalid review comment.

Comment thread crates/event-sorcery/src/job_sqlite.rs
@0xgleb

0xgleb commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@0xgleb
0xgleb force-pushed the feat/0.4-engine-ffi branch from 7aa769e to 03c01e6 Compare July 16, 2026 16:26
@0xgleb

0xgleb commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/event-sorcery/src/engine.rs`:
- Around line 707-708: Configure the test SQLite pools in
crates/event-sorcery/src/engine.rs lines 707-708 and
crates/event-sorcery/src/job_sqlite.rs lines 119-120 with
SqlitePoolOptions::new().max_connections(1) before connecting to :memory:,
preserving the existing Engine::new and job test setup.

In `@crates/event-sorcery/src/job_sqlite.rs`:
- Around line 109-110: Add a module-level `//!` documentation comment
immediately inside the `tests` module declaration, describing the purpose of the
test module.

In `@crates/event-sorcery/src/sqlite_event_repository.rs`:
- Line 125: Add a regression test for the `SqliteEventRepository::persist` path
using an empty event list with a snapshot, asserting that it returns the
propagated `PersistenceError` from `CommitRequest::with_snapshot` and that the
database remains unchanged. Reuse the repository’s existing test setup and
persistence helpers, and avoid changing production behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9d3d4b86-06fc-49e9-a41f-e6b67fce79aa

📥 Commits

Reviewing files that changed from the base of the PR and between 7aa769e and 03c01e6.

📒 Files selected for processing (4)
  • crates/event-sorcery/src/engine.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/sqlite_event_repository.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (6)
  • GitHub Check: examples
  • GitHub Check: clippy
  • GitHub Check: check
  • GitHub Check: test
  • GitHub Check: fmt
  • GitHub Check: hooks
🧰 Additional context used
📓 Path-based instructions (2)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Before work, read SPEC.md and docs/domain.md; read relevant supplemental documentation before implementation.
New features must be documented in SPEC.md before implementation and must follow the hierarchy SPEC.md -> issue -> plan -> tests -> implementation.
Fix all known problems immediately, complete all tasks, and do not allow warnings or errors to pass through.
Keep a granular task list and clear completed tasks from the active list.
All new or modified logic must have corresponding test coverage.
Understand relevant documentation and source code before implementation, keep diffs small, and review the approach critically.
When changing direction or making an important undocumented architectural decision, obtain confirmation; record significant decisions as ADRs under adrs/.
Before handover, review the diff, revert unjustified changes, and check for scope creep.
Each aggregate in a consuming application must use exactly one SqliteCqrs instance constructed at startup; per-request construction is forbidden.
Never read secret or credential files such as .env*, credentials.json, *.key, *.pem, *.p12, *.pfx, or sensitive database files without explicit permission.
Never bypass, disable, suppress, or obscure quality-control mechanisms without explicit permission; fix lint and test issues at their root.
Use cargo check, cargo nextest, and cargo clippy for verification; never use cargo build unless build artifacts are required.

Files:

  • crates/event-sorcery/src/sqlite_event_repository.rs
  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/engine.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Organize code by business feature rather than technical layer; avoid catch-all modules such as types.rs, error.rs, models.rs, utils.rs, helpers.rs, and services.rs.
Never write directly to the events table; emit events through CqrsFramework::execute() or execute_with_metadata().
Use cqrs-es Services for side effects in handle() and follow the {Action}er -> {Domain}Service -> {Domain}Manager naming pattern.
Place command-execution logging in aggregate handle() methods rather than callers.
Model invalid states with enums, ADTs, newtypes, and typestate rather than relying on runtime validation.
Use domain newtypes at APIs and convert to SDK primitives inside the callee, except at cross-crate boundaries where conversion at the call site is necessary.
Keep visibility as restrictive as possible: private over pub(crate) over pub.
Use a three-group import order: external crates, workspace crates, then crate-internal imports; do not use function-level imports except enum variants.
Do not use unwrap() or expect() in production Rust code; they are permitted in #[cfg(test)] code.
Never create error variants containing opaque String values; prefer #[from], ?, #[source], and preserve error chains.
Log a warning or error before silent early returns such as let-else failures.
Never silently mask numeric failures with caps, fallback defaults, precision truncation, unwrap_or(), or unwrap_or_default(); use explicit checked conversions and errors.
Prefer functional patterns, pattern matching, combinators, type-driven design, and iterators over imperative loops unless complexity increases.
Use ASCII in identifiers, comments, log messages, and configuration keys; Unicode is preferred only in user-facing rendered output.
Do not use single-letter variables, arguments, closure parameters, or generic type parameters except an unambiguous lone type parameter or short unambiguous closure.
Every module must have a //! docstring and should order public API, private implementati...

Files:

  • crates/event-sorcery/src/sqlite_event_repository.rs
  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/engine.rs
🔇 Additional comments (5)
crates/event-sorcery/src/engine.rs (3)

17-55: LGTM!

Also applies to: 94-117, 142-144, 146-302, 385-460


705-706: LGTM!

Also applies to: 710-726, 800-808, 820-821


67-92: 📐 Maintainability & Code Quality

Public error types are already exposed
JobStoreError and SqliteJobError are re-exported from the crate root, so the public engine errors remain nameable by downstream users.

			> Likely an incorrect or invalid review comment.
crates/event-sorcery/src/lib.rs (1)

128-128: LGTM!

crates/event-sorcery/src/job_sqlite.rs (1)

78-78: LGTM!

Also applies to: 122-138

Comment thread crates/event-sorcery/src/engine.rs Outdated
Comment thread crates/event-sorcery/src/job_sqlite.rs
Comment thread crates/event-sorcery/src/sqlite_event_repository.rs
@0xgleb
0xgleb force-pushed the feat/0.4-engine-ffi branch from 03c01e6 to 8983b16 Compare July 16, 2026 16:43
@0xgleb

0xgleb commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/event-sorcery/src/engine.rs (1)

778-778: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document both test modules.

  • crates/event-sorcery/src/engine.rs#L778-L778: add an inner //! docstring.
  • crates/event-sorcery/src/job_sqlite.rs#L109-L110: add an inner //! docstring.

As per coding guidelines, every module must have a //! docstring.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/event-sorcery/src/engine.rs` at line 778, Add an inner //!
documentation comment immediately inside the tests module in
crates/event-sorcery/src/engine.rs at lines 778-778, and add an equivalent
descriptive //! comment inside the tests module in
crates/event-sorcery/src/job_sqlite.rs at lines 109-110. Ensure both test
modules are documented without changing their test behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/event-sorcery/src/engine.rs`:
- Line 778: Add an inner //! documentation comment immediately inside the tests
module in crates/event-sorcery/src/engine.rs at lines 778-778, and add an
equivalent descriptive //! comment inside the tests module in
crates/event-sorcery/src/job_sqlite.rs at lines 109-110. Ensure both test
modules are documented without changing their test behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d3c6abbe-f21c-42e3-8666-fa3e8d2131fd

📥 Commits

Reviewing files that changed from the base of the PR and between 03c01e6 and 8983b16.

📒 Files selected for processing (4)
  • crates/event-sorcery/src/engine.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/sqlite_event_repository.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (6)
  • GitHub Check: test
  • GitHub Check: check
  • GitHub Check: fmt
  • GitHub Check: clippy
  • GitHub Check: hooks
  • GitHub Check: examples
🧰 Additional context used
📓 Path-based instructions (2)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Before work, read SPEC.md and docs/domain.md; read relevant supplemental documentation before implementation.
New features must be documented in SPEC.md before implementation and must follow the hierarchy SPEC.md -> issue -> plan -> tests -> implementation.
Fix all known problems immediately, complete all tasks, and do not allow warnings or errors to pass through.
Keep a granular task list and clear completed tasks from the active list.
All new or modified logic must have corresponding test coverage.
Understand relevant documentation and source code before implementation, keep diffs small, and review the approach critically.
When changing direction or making an important undocumented architectural decision, obtain confirmation; record significant decisions as ADRs under adrs/.
Before handover, review the diff, revert unjustified changes, and check for scope creep.
Each aggregate in a consuming application must use exactly one SqliteCqrs instance constructed at startup; per-request construction is forbidden.
Never read secret or credential files such as .env*, credentials.json, *.key, *.pem, *.p12, *.pfx, or sensitive database files without explicit permission.
Never bypass, disable, suppress, or obscure quality-control mechanisms without explicit permission; fix lint and test issues at their root.
Use cargo check, cargo nextest, and cargo clippy for verification; never use cargo build unless build artifacts are required.

Files:

  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/sqlite_event_repository.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/engine.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Organize code by business feature rather than technical layer; avoid catch-all modules such as types.rs, error.rs, models.rs, utils.rs, helpers.rs, and services.rs.
Never write directly to the events table; emit events through CqrsFramework::execute() or execute_with_metadata().
Use cqrs-es Services for side effects in handle() and follow the {Action}er -> {Domain}Service -> {Domain}Manager naming pattern.
Place command-execution logging in aggregate handle() methods rather than callers.
Model invalid states with enums, ADTs, newtypes, and typestate rather than relying on runtime validation.
Use domain newtypes at APIs and convert to SDK primitives inside the callee, except at cross-crate boundaries where conversion at the call site is necessary.
Keep visibility as restrictive as possible: private over pub(crate) over pub.
Use a three-group import order: external crates, workspace crates, then crate-internal imports; do not use function-level imports except enum variants.
Do not use unwrap() or expect() in production Rust code; they are permitted in #[cfg(test)] code.
Never create error variants containing opaque String values; prefer #[from], ?, #[source], and preserve error chains.
Log a warning or error before silent early returns such as let-else failures.
Never silently mask numeric failures with caps, fallback defaults, precision truncation, unwrap_or(), or unwrap_or_default(); use explicit checked conversions and errors.
Prefer functional patterns, pattern matching, combinators, type-driven design, and iterators over imperative loops unless complexity increases.
Use ASCII in identifiers, comments, log messages, and configuration keys; Unicode is preferred only in user-facing rendered output.
Do not use single-letter variables, arguments, closure parameters, or generic type parameters except an unambiguous lone type parameter or short unambiguous closure.
Every module must have a //! docstring and should order public API, private implementati...

Files:

  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/sqlite_event_repository.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/engine.rs
🔇 Additional comments (4)
crates/event-sorcery/src/sqlite_event_repository.rs (1)

125-125: Add the repository-level empty-snapshot regression test.

This path still needs coverage proving that empty events plus a snapshot propagates the error and writes nothing.

crates/event-sorcery/src/engine.rs (1)

6-7: LGTM!

Also applies to: 19-60, 69-76, 96-118, 131-542, 730-730, 824-862, 923-931, 943-944

crates/event-sorcery/src/lib.rs (1)

128-128: LGTM!

crates/event-sorcery/src/job_sqlite.rs (1)

78-78: LGTM!

@0xgleb
0xgleb force-pushed the feat/0.4-engine-ffi branch from 8983b16 to ed8d725 Compare July 16, 2026 16:48
@0xgleb

0xgleb commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/event-sorcery/src/engine.rs`:
- Around line 129-142: Update the documentation comment for Engine::new to
describe construction from a SQLite pool without claiming the pool is already
migrated, and document the required separate migrate() call or initialization
sequence so external consumers use the correct order.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 05630b1a-9adf-4bc1-92aa-37b41098196c

📥 Commits

Reviewing files that changed from the base of the PR and between 8983b16 and ed8d725.

📒 Files selected for processing (4)
  • crates/event-sorcery/src/engine.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/sqlite_event_repository.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (6)
  • GitHub Check: examples
  • GitHub Check: check
  • GitHub Check: clippy
  • GitHub Check: fmt
  • GitHub Check: hooks
  • GitHub Check: test
🧰 Additional context used
📓 Path-based instructions (2)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Before work, read SPEC.md and docs/domain.md; read relevant supplemental documentation before implementation.
New features must be documented in SPEC.md before implementation and must follow the hierarchy SPEC.md -> issue -> plan -> tests -> implementation.
Fix all known problems immediately, complete all tasks, and do not allow warnings or errors to pass through.
Keep a granular task list and clear completed tasks from the active list.
All new or modified logic must have corresponding test coverage.
Understand relevant documentation and source code before implementation, keep diffs small, and review the approach critically.
When changing direction or making an important undocumented architectural decision, obtain confirmation; record significant decisions as ADRs under adrs/.
Before handover, review the diff, revert unjustified changes, and check for scope creep.
Each aggregate in a consuming application must use exactly one SqliteCqrs instance constructed at startup; per-request construction is forbidden.
Never read secret or credential files such as .env*, credentials.json, *.key, *.pem, *.p12, *.pfx, or sensitive database files without explicit permission.
Never bypass, disable, suppress, or obscure quality-control mechanisms without explicit permission; fix lint and test issues at their root.
Use cargo check, cargo nextest, and cargo clippy for verification; never use cargo build unless build artifacts are required.

Files:

  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/sqlite_event_repository.rs
  • crates/event-sorcery/src/engine.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Organize code by business feature rather than technical layer; avoid catch-all modules such as types.rs, error.rs, models.rs, utils.rs, helpers.rs, and services.rs.
Never write directly to the events table; emit events through CqrsFramework::execute() or execute_with_metadata().
Use cqrs-es Services for side effects in handle() and follow the {Action}er -> {Domain}Service -> {Domain}Manager naming pattern.
Place command-execution logging in aggregate handle() methods rather than callers.
Model invalid states with enums, ADTs, newtypes, and typestate rather than relying on runtime validation.
Use domain newtypes at APIs and convert to SDK primitives inside the callee, except at cross-crate boundaries where conversion at the call site is necessary.
Keep visibility as restrictive as possible: private over pub(crate) over pub.
Use a three-group import order: external crates, workspace crates, then crate-internal imports; do not use function-level imports except enum variants.
Do not use unwrap() or expect() in production Rust code; they are permitted in #[cfg(test)] code.
Never create error variants containing opaque String values; prefer #[from], ?, #[source], and preserve error chains.
Log a warning or error before silent early returns such as let-else failures.
Never silently mask numeric failures with caps, fallback defaults, precision truncation, unwrap_or(), or unwrap_or_default(); use explicit checked conversions and errors.
Prefer functional patterns, pattern matching, combinators, type-driven design, and iterators over imperative loops unless complexity increases.
Use ASCII in identifiers, comments, log messages, and configuration keys; Unicode is preferred only in user-facing rendered output.
Do not use single-letter variables, arguments, closure parameters, or generic type parameters except an unambiguous lone type parameter or short unambiguous closure.
Every module must have a //! docstring and should order public API, private implementati...

Files:

  • crates/event-sorcery/src/lib.rs
  • crates/event-sorcery/src/job_sqlite.rs
  • crates/event-sorcery/src/sqlite_event_repository.rs
  • crates/event-sorcery/src/engine.rs
🔇 Additional comments (8)
crates/event-sorcery/src/engine.rs (5)

6-65: LGTM!


69-127: LGTM!


144-364: Public API promotions and read-path additions look correct.

pool() correctly stays pub(crate), checked conversions (i64::try_from/usize::try_from) are used consistently in load_events_page/current_version, and bind counts match placeholder counts in both branches. One note: migrate() (line 136) returns SqliteJobError while every other non-job Engine op here returns EngineError — see the lib.rs comment for the cross-file reachability concern this creates now that Engine is public.


468-468: LGTM!

Also applies to: 730-739


779-1060: Solid integration coverage; past single-connection-pool concern is resolved.

The migration and paging tests correctly use SqlitePoolOptions::new().max_connections(1) for :memory: pools, addressing the earlier review comment about private per-connection in-memory databases. snapshot_attachment_requires_persisted_events correctly uses a sync #[test] since with_snapshot is no longer async-dependent.

crates/event-sorcery/src/sqlite_event_repository.rs (1)

125-125: Resolves prior review feedback with correct implementation.

with_snapshot(...)? correctly propagates the new fallible constructor, and the new empty_snapshot_update_propagates_without_writing test directly satisfies the earlier request for empty-snapshot regression coverage on the persist path (asserts the exact EngineError::EmptySnapshotUpdate variant and zero rows written, per the guideline to assert exact error variants).

Also applies to: 147-148, 292-306, 338-369

crates/event-sorcery/src/job_sqlite.rs (1)

78-78: LGTM! Delegation to Engine::migrate removes the duplicated migrator logic, and the new test module (with its //! docstring and single-connection in-memory pool) resolves the two previously flagged review comments on this file.

Also applies to: 108-146

crates/event-sorcery/src/lib.rs (1)

128-128: 🗄️ Data Integrity & Integration

No missing re-exports here The job-related result and error types are already re-exported from crates/event-sorcery/src/lib.rs, and EnqueueRequest stays crate-private and is only used internally.

			> Likely an incorrect or invalid review comment.

Comment thread crates/event-sorcery/src/engine.rs
@0xgleb

0xgleb commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@0xgleb
0xgleb added this pull request to the merge queue Jul 16, 2026
Merged via the queue into master with commit 0b22ada Jul 16, 2026
7 checks passed
@0xgleb
0xgleb deleted the feat/0.4-engine-ffi branch July 16, 2026 17:11
@github-project-automation github-project-automation Bot moved this from In Progress to Done in event-sorcery Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

The shared engine facade is not public

1 participant