Repository navigation
test: pin atomic event and job persistence - #22
Conversation
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
4a1d4a2 to
15a6c5f
Compare
7c01eda to
96c2f9d
Compare
15a6c5f to
7ccdad0
Compare
96c2f9d to
92a06b6
Compare
7ccdad0 to
73ad30b
Compare
73ad30b to
8c2262a
Compare
8c2262a to
6eb40a5
Compare
92a06b6 to
42e06ba
Compare
6eb40a5 to
95c74b5
Compare
42e06ba to
c6a534e
Compare
95c74b5 to
e974aae
Compare
c6a534e to
334387c
Compare
e974aae to
4618481
Compare
b931087 to
b1c7ad7
Compare
9160ca5 to
34bf775
Compare
b1c7ad7 to
3cf971d
Compare
34bf775 to
4ab96c1
Compare
3cf971d to
8c75d18
Compare
4ab96c1 to
57223b8
Compare
8c75d18 to
ad8f4dd
Compare
57223b8 to
48f106d
Compare
ad8f4dd to
f1c71f5
Compare
48f106d to
a26d485
Compare
f1c71f5 to
d607632
Compare
a26d485 to
095ee6c
Compare
d607632 to
2ecbff5
Compare
There was a problem hiding this comment.
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/sqlite_event_repository.rs`:
- Around line 502-548: Extract shared async row-count helpers for event and
queue queries, following the existing test helper pattern: add helpers such as
count_events and count_queue_rows, then update
aggregate_event_job_event_and_queue_seed_commit_together and the other affected
test to call them with the appropriate aggregate type and ID values. Remove the
duplicated inline sqlx::query_scalar blocks while preserving the existing
assertions and query 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: 0f0465e7-8675-4f55-a6ad-21026ecb1b5a
📒 Files selected for processing (2)
crates/event-sorcery/src/job_backend.rscrates/event-sorcery/src/sqlite_event_repository.rs
📜 Review details
⚠️ CI failures not shown inline (2)
GitHub Actions: CI / clippy: test: pin atomic event and job persistence
Conclusion: failure
##[group]Run nix develop -c cargo clippy --workspace --all-targets --all-features
�[36;1mnix develop -c cargo clippy --workspace --all-targets --all-features�[0m
shell: /usr/bin/bash -e {0}
env:
CARGO_INCREMENTAL: 0
NIX_PROFILES: /nix/var/nix/profiles/default /home/runner/.nix-profile
NIX_USER_PROFILE_DIR: /nix/var/nix/profiles/per-user/runner
NIX_SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
NIX_USER_CONF_FILES: /home/runner/work/_temp/cachix-daemon-oFqsj0/nix.conf:/home/runner/.config/nix/nix.conf:/etc/xdg/nix/nix.conf
CACHIX_DAEMON_DIR: /home/runner/work/_temp/cachix-daemon-oFqsj0
##[endgroup]
copying path '/nix/store/01x5k4nlxcpyd85nnr0b9gm89rm8ff4x-source' from 'https://data-cartel-public.cachix.org'...
copying path '/nix/store/yj1wxm9hh8610iyzqnz75kvs6xl8j3my-source' from 'https://data-cartel-public.cachix.org'...
unpacking 'github:rainprotocol/rainix/49fb732e4837dcdaed415a9dad51a0375096e2fe?narHash=sha256-jEU9kpRvyPzF01ra%2B27/uzb/qz5pvx02NudjKwF9pw8%3D' into the Git cache...
unpacking 'github:nixos/nixpkgs/4ba039de0909446943c07e2b42bd2f0f4507072e?narHash=sha256-lKVrom9wOmpC3i7m%2BuBoGaBdW0PfH3QbLRG1XmuC6YA%3D' into the Git cache...
unpacking 'github:oxalica/rust-overlay/77265d2dc1e61b2abfd3b1d6609dbb66fe75e0a5?narHash=sha256-bhk4lawR4ZnFhPtamB5WkCyvfgyZmsEUbWfT/3FRxFY%3D' into the Git cache...
unpacking 'github:shazow/foundry.nix/db117ae95a77b9ead24137c3ccb28896ae4fa4ec?narHash=sha256-iuy/TbK9AbghEld2VSFuxyAF30LkOGUUdtrvixLfE7M%3D' into the Git cache...
unpacking 'github:numtide/flake-utils/3cecb5b042f7f209c56ffd8371b2711a290ec797?narHash=sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k%3D' into the Git cache...
unpacking 'github:hellwolf/solc.nix/e3cf898cb804d5c0e5474b378a300fe8942e67d6?narHash=sha256-iI71iUhD7THLibl3w1JcQEhHmTwZMxChi70RTe33BAo%3D' into the Git cache...
unpacking 'github:cachix/git-hooks.nix/bca82caa46d5ec0f5d422c61fb1e30bc51313cbe?narHash=sha256-jGiy6%2BsxjNWXSjp25uoJuNfyH9zBK1PEDY0lVoL4ibQ%3D' into ...
GitHub Actions: CI / 1_clippy.txt: test: pin atomic event and job persistence
Conclusion: failure
##[group]Run nix develop -c cargo clippy --workspace --all-targets --all-features
�[36;1mnix develop -c cargo clippy --workspace --all-targets --all-features�[0m
shell: /usr/bin/bash -e {0}
env:
CARGO_INCREMENTAL: 0
NIX_PROFILES: /nix/var/nix/profiles/default /home/runner/.nix-profile
NIX_USER_PROFILE_DIR: /nix/var/nix/profiles/per-user/runner
NIX_SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
NIX_USER_CONF_FILES: /home/runner/work/_temp/cachix-daemon-oFqsj0/nix.conf:/home/runner/.config/nix/nix.conf:/etc/xdg/nix/nix.conf
CACHIX_DAEMON_DIR: /home/runner/work/_temp/cachix-daemon-oFqsj0
##[endgroup]
copying path '/nix/store/01x5k4nlxcpyd85nnr0b9gm89rm8ff4x-source' from 'https://data-cartel-public.cachix.org'...
copying path '/nix/store/yj1wxm9hh8610iyzqnz75kvs6xl8j3my-source' from 'https://data-cartel-public.cachix.org'...
unpacking 'github:rainprotocol/rainix/49fb732e4837dcdaed415a9dad51a0375096e2fe?narHash=sha256-jEU9kpRvyPzF01ra%2B27/uzb/qz5pvx02NudjKwF9pw8%3D' into the Git cache...
unpacking 'github:nixos/nixpkgs/4ba039de0909446943c07e2b42bd2f0f4507072e?narHash=sha256-lKVrom9wOmpC3i7m%2BuBoGaBdW0PfH3QbLRG1XmuC6YA%3D' into the Git cache...
unpacking 'github:oxalica/rust-overlay/77265d2dc1e61b2abfd3b1d6609dbb66fe75e0a5?narHash=sha256-bhk4lawR4ZnFhPtamB5WkCyvfgyZmsEUbWfT/3FRxFY%3D' into the Git cache...
unpacking 'github:shazow/foundry.nix/db117ae95a77b9ead24137c3ccb28896ae4fa4ec?narHash=sha256-iuy/TbK9AbghEld2VSFuxyAF30LkOGUUdtrvixLfE7M%3D' into the Git cache...
unpacking 'github:numtide/flake-utils/3cecb5b042f7f209c56ffd8371b2711a290ec797?narHash=sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k%3D' into the Git cache...
unpacking 'github:hellwolf/solc.nix/e3cf898cb804d5c0e5474b378a300fe8942e67d6?narHash=sha256-iI71iUhD7THLibl3w1JcQEhHmTwZMxChi70RTe33BAo%3D' into the Git cache...
unpacking 'github:cachix/git-hooks.nix/bca82caa46d5ec0f5d422c61fb1e30bc51313cbe?narHash=sha256-jGiy6%2BsxjNWXSjp25uoJuNfyH9zBK1PEDY0lVoL4ibQ%3D' into ...
🧰 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/job_backend.rscrates/event-sorcery/src/sqlite_event_repository.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/job_backend.rscrates/event-sorcery/src/sqlite_event_repository.rs
🪛 GitHub Actions: CI / 1_clippy.txt
crates/event-sorcery/src/job_backend.rs
[error] 1-1: Command failed: cargo clippy --workspace --all-targets --all-features. Build/test failed because event-sorcery (lib test) could not compile due to 5 previous errors.
crates/event-sorcery/src/sqlite_event_repository.rs
[error] 512-516: Clippy (pedantic): unnecessary hashes around raw string literal. Rule: clippy::needless-raw-string-hashes (implied by -D clippy::pedantic).
[error] 525-529: Clippy (pedantic): unnecessary hashes around raw string literal. Rule: clippy::needless-raw-string-hashes (implied by -D clippy::pedantic).
[error] 536-540: Clippy (pedantic): unnecessary hashes around raw string literal. Rule: clippy::needless-raw-string-hashes (implied by -D clippy::pedantic).
[error] 572-576: Clippy (pedantic): unnecessary hashes around raw string literal. Rule: clippy::needless-raw-string-hashes (implied by -D clippy::pedantic).
[error] 585-589: Clippy (pedantic): unnecessary hashes around raw string literal. Rule: clippy::needless-raw-string-hashes (implied by -D clippy::pedantic).
[error] 1-1: Command failed: cargo clippy --workspace --all-targets --all-features. Build/test failed because event-sorcery (lib test) could not compile due to 5 previous errors.
🪛 GitHub Actions: CI / clippy
crates/event-sorcery/src/sqlite_event_repository.rs
[error] 512-516: Clippy (pedantic) error: unnecessary hashes around raw string literal. Rule: clippy::needless_raw_string_hashes (-D clippy::pedantic implied).
[error] 525-529: Clippy (pedantic) error: unnecessary hashes around raw string literal. Rule: clippy::needless_raw_string_hashes (-D clippy::pedantic implied).
[error] 536-540: Clippy (pedantic) error: unnecessary hashes around raw string literal. Rule: clippy::needless_raw_string_hashes (-D clippy::pedantic implied).
[error] 572-576: Clippy (pedantic) error: unnecessary hashes around raw string literal. Rule: clippy::needless_raw_string_hashes (-D clippy::pedantic implied).
[error] 585-589: Clippy (pedantic) error: unnecessary hashes around raw string literal. Rule: clippy::needless_raw_string_hashes (-D clippy::pedantic implied).
🔇 Additional comments (2)
crates/event-sorcery/src/sqlite_event_repository.rs (1)
391-396: LGTM!Also applies to: 421-432, 482-500
crates/event-sorcery/src/job_backend.rs (1)
1116-1142: LGTM!
| #[tokio::test] | ||
| async fn aggregate_event_job_event_and_queue_seed_commit_together() { | ||
| let pool = test_pool().await; | ||
| let job_id = JobId::new(); | ||
|
|
||
| persist_with_pending_job(pool.clone(), "atomic-success", job_id) | ||
| .await | ||
| .unwrap(); | ||
|
|
||
| let aggregate_events = sqlx::query_scalar::<_, i64>( | ||
| r#" | ||
| SELECT COUNT(*) | ||
| FROM events | ||
| WHERE aggregate_type = ?1 AND aggregate_id = ?2 | ||
| "#, | ||
| ) | ||
| .bind(TestAggregate::TYPE) | ||
| .bind("atomic-success") | ||
| .fetch_one(&pool) | ||
| .await | ||
| .unwrap(); | ||
| let job_id = job_id.to_string(); | ||
| let job_events = sqlx::query_scalar::<_, i64>( | ||
| r#" | ||
| SELECT COUNT(*) | ||
| FROM events | ||
| WHERE aggregate_type = 'job' AND aggregate_id = ?1 | ||
| "#, | ||
| ) | ||
| .bind(&job_id) | ||
| .fetch_one(&pool) | ||
| .await | ||
| .unwrap(); | ||
| let queue_rows = sqlx::query_scalar::<_, i64>( | ||
| r#" | ||
| SELECT COUNT(*) | ||
| FROM job_queue | ||
| WHERE view_id = ?1 | ||
| "#, | ||
| ) | ||
| .bind(&job_id) | ||
| .fetch_one(&pool) | ||
| .await | ||
| .unwrap(); | ||
|
|
||
| assert_eq!((aggregate_events, job_events, queue_rows), (1, 1, 1)); | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Extract a shared row-count helper instead of duplicating the SQL blocks.
The aggregate_events/job_events (and existing_job_events) query blocks are copy-pasted almost verbatim between the two tests, differing only in bound values. This mirrors the existing event_types/queue_status helper pattern already used in job_backend.rs's test module.
♻️ Proposed helper extraction
+ async fn count_events(pool: &SqlitePool, aggregate_type: &str, aggregate_id: &str) -> i64 {
+ sqlx::query_scalar::<_, i64>(
+ "SELECT COUNT(*) FROM events WHERE aggregate_type = ?1 AND aggregate_id = ?2",
+ )
+ .bind(aggregate_type)
+ .bind(aggregate_id)
+ .fetch_one(pool)
+ .await
+ .unwrap()
+ }
+
+ async fn count_queue_rows(pool: &SqlitePool, view_id: &str) -> i64 {
+ sqlx::query_scalar::<_, i64>("SELECT COUNT(*) FROM job_queue WHERE view_id = ?1")
+ .bind(view_id)
+ .fetch_one(pool)
+ .await
+ .unwrap()
+ }Then both tests can replace their inline sqlx::query_scalar blocks with count_events(&pool, TestAggregate::TYPE, "atomic-success").await, count_events(&pool, "job", &job_id).await, and count_queue_rows(&pool, &job_id).await.
Also applies to: 550-598
🧰 Tools
🪛 GitHub Actions: CI / 1_clippy.txt
[error] 512-516: Clippy (pedantic): unnecessary hashes around raw string literal. Rule: clippy::needless-raw-string-hashes (implied by -D clippy::pedantic).
[error] 525-529: Clippy (pedantic): unnecessary hashes around raw string literal. Rule: clippy::needless-raw-string-hashes (implied by -D clippy::pedantic).
[error] 536-540: Clippy (pedantic): unnecessary hashes around raw string literal. Rule: clippy::needless-raw-string-hashes (implied by -D clippy::pedantic).
🪛 GitHub Actions: CI / clippy
[error] 512-516: Clippy (pedantic) error: unnecessary hashes around raw string literal. Rule: clippy::needless_raw_string_hashes (-D clippy::pedantic implied).
[error] 525-529: Clippy (pedantic) error: unnecessary hashes around raw string literal. Rule: clippy::needless_raw_string_hashes (-D clippy::pedantic implied).
[error] 536-540: Clippy (pedantic) error: unnecessary hashes around raw string literal. Rule: clippy::needless_raw_string_hashes (-D clippy::pedantic implied).
🤖 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/sqlite_event_repository.rs` around lines 502 - 548,
Extract shared async row-count helpers for event and queue queries, following
the existing test helper pattern: add helpers such as count_events and
count_queue_rows, then update
aggregate_event_job_event_and_queue_seed_commit_together and the other affected
test to call them with the appropriate aggregate type and ID values. Remove the
duplicated inline sqlx::query_scalar blocks while preserving the existing
assertions and query behavior.
2ecbff5 to
fa8c4d4
Compare
Characterizes the existing SQLite writer boundary before facade extraction. It proves aggregate events, job events, and the job_queue seed commit together, and that a duplicate job identity rolls the aggregate event back.
Part of #9 and #12.
Closes #58.
This is part 4 of 32 in a stack made with GitButler:
Summary by CodeRabbit
Bug Fixes
Tests