Skip to content

docs: migrate docs to the jobs model#20

Draft
0xgleb wants to merge 1 commit into
feat/jobs-examples-docsfrom
docs/migrate-jobs-model-docs
Draft

docs: migrate docs to the jobs model#20
0xgleb wants to merge 1 commit into
feat/jobs-examples-docsfrom
docs/migrate-jobs-model-docs

Conversation

@0xgleb

@0xgleb 0xgleb commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Motivation

The README, SPEC, domain terminology, and CQRS docs still describe the removed Services model. The docs need to teach the jobs API separately from the example crate migration.

Solution

  • Updates README/SPEC/domain/CQRS prose from Services to the jobs model.
  • Documents JobQueue, worker wiring, and the updated examples at the documentation layer.
  • Stacked on the examples-only migration PR.

Closes RAI-946.

Summary by CodeRabbit

  • Documentation
    • Updated CQRS/event-sourcing docs to describe synchronous command handlers that enqueue durable jobs instead of using injected services.
    • Added clearer guidance for job types, job queues, crash safety, retry behavior, and naming conventions.
    • Expanded contributor and project overview notes to reflect the new job-based workflow and contribution expectations.
    • Refreshed the example README to show command timestamps supplied by callers and the updated no-side-effects flow.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The PR replaces command-side “Services” terminology with “Jobs” across the spec and documentation, updates example handler signatures and job-queue usage, adds crash-safety and naming guidance, and revises contributor notes plus the simple example README.

Changes

Jobs documentation shift

Layer / File(s) Summary
Spec contract and runtime model
SPEC.md
EventSourced now uses Jobs instead of Services, and the spec defines the job queue, backend, and worker flow for durable job execution.
Command API examples
docs/cqrs.md, docs/domain.md
The documented command-handler signatures switch to JobQueue, remove service parameters, and state that handlers are synchronous and pure.
Jobs pattern and crash safety
docs/cqrs.md, docs/domain.md
The docs replace Services-pattern sections with jobs-pattern, crash-safety, job queue, and job-naming guidance.
Example README updates
examples/simple/README.md
The example README adds command timestamps, updates the capability table for Nil jobs, and rewrites the timestamp rationale.
Contributor guidance and references
AGENTS.md, README.md
Contributor guidance adds a pull-request-size rule and reusable script guidance, and the README topic label changes from services to jobs.

Possibly related PRs

Suggested reviewers

  • JuaniRios
  • findolor
🚥 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 accurately summarizes the documentation migration from Services to the jobs model.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/migrate-jobs-model-docs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

0xgleb commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add the label add-to-gt-merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has required the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@0xgleb 0xgleb marked this pull request as ready for review June 10, 2026 04:54
@0xgleb 0xgleb changed the title docs: migrate jobs model docs docs: migrate docs to the jobs model Jun 10, 2026
@linear-code

linear-code Bot commented Jun 10, 2026

Copy link
Copy Markdown

RAI-943

RAI-946

@0xgleb 0xgleb self-assigned this Jun 10, 2026
@0xgleb 0xgleb added the documentation Improvements or additions to documentation label Jun 10, 2026 — with Graphite App
@0xgleb 0xgleb requested review from JuaniRios and findolor June 10, 2026 04:54
@0xgleb 0xgleb force-pushed the docs/migrate-jobs-model-docs branch from 9a4b95f to a7d1b09 Compare June 10, 2026 04:55
@0xgleb 0xgleb force-pushed the feat/jobs-examples-docs branch from 7b0f794 to 2e99de9 Compare June 10, 2026 04:55
@0xgleb 0xgleb force-pushed the docs/migrate-jobs-model-docs branch from a7d1b09 to bfcb3db Compare June 10, 2026 04:56
@0xgleb 0xgleb changed the base branch from feat/jobs-examples-docs to graphite-base/20 June 10, 2026 05:28
@0xgleb 0xgleb force-pushed the docs/migrate-jobs-model-docs branch from bfcb3db to 1760f55 Compare June 10, 2026 06:00
@0xgleb 0xgleb force-pushed the graphite-base/20 branch from 2e99de9 to 48ee433 Compare June 10, 2026 06:00
@0xgleb 0xgleb changed the base branch from graphite-base/20 to feat/jobs-examples-docs June 10, 2026 06:00

@findolor findolor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved.

@0xgleb 0xgleb force-pushed the feat/jobs-examples-docs branch from 48ee433 to 500ca31 Compare June 10, 2026 17:39
@0xgleb 0xgleb force-pushed the docs/migrate-jobs-model-docs branch from 1760f55 to 6cc8e9f Compare June 10, 2026 17:39
@graphite-app graphite-app Bot force-pushed the feat/jobs-examples-docs branch from 500ca31 to d6cd320 Compare June 10, 2026 19:20
@graphite-app graphite-app Bot force-pushed the docs/migrate-jobs-model-docs branch from 6cc8e9f to f2752ab Compare June 10, 2026 19:21
@0xgleb 0xgleb force-pushed the feat/jobs-examples-docs branch from d6cd320 to a8f14b3 Compare June 12, 2026 19:45
@0xgleb 0xgleb force-pushed the docs/migrate-jobs-model-docs branch 2 times, most recently from 9947e4e to 9d1a600 Compare June 12, 2026 21:16
@0xgleb 0xgleb force-pushed the feat/jobs-examples-docs branch from a8f14b3 to 4947d61 Compare June 12, 2026 21:16
@0xgleb 0xgleb force-pushed the feat/jobs-examples-docs branch from 4947d61 to 718b565 Compare June 12, 2026 21:55
@0xgleb 0xgleb force-pushed the docs/migrate-jobs-model-docs branch from 9d1a600 to 95a21bd Compare June 12, 2026 21:55
@graphite-app graphite-app Bot force-pushed the feat/jobs-examples-docs branch from 718b565 to 8d31830 Compare June 15, 2026 19:30
@graphite-app graphite-app Bot force-pushed the docs/migrate-jobs-model-docs branch from 95a21bd to 3cfa702 Compare June 15, 2026 19:30
@0xgleb 0xgleb force-pushed the docs/migrate-jobs-model-docs branch from 3cfa702 to ec562c0 Compare June 26, 2026 20:28
@0xgleb 0xgleb force-pushed the feat/jobs-examples-docs branch from 8d31830 to cdaabcd Compare June 26, 2026 20:28
Co-authored-by: Cursor <cursoragent@cursor.com>

@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 `@docs/cqrs.md`:
- Around line 245-311: The worker example is converting the job backend to
storage twice, because build_supervised_worker! already handles the storage
conversion internally. Update the jobs worker example that uses
JobBackend::<PlaceOrder> so it passes backend directly instead of
backend.into_storage(), while keeping the existing Job, WORKER_NAME, KIND, and
label() usage unchanged.
🪄 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

Run ID: 22f5855f-44b1-4067-b2e5-11dae74f55d4

📥 Commits

Reviewing files that changed from the base of the PR and between 1f2408b and 2d6d324.

📒 Files selected for processing (6)
  • AGENTS.md
  • README.md
  • SPEC.md
  • docs/cqrs.md
  • docs/domain.md
  • examples/simple/README.md
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Graphite / mergeability_check
🧰 Additional context used
📓 Path-based instructions (5)
README.md

📄 CodeRabbit inference engine (AGENTS.md)

Update README.md when project structure, features, commands, or architecture change.

Files:

  • README.md
*

⚙️ CodeRabbit configuration file

Focus on providing constructive criticism. Whenever you see a suboptimal approach, suggest more idiomatic or robust alternative(s). Flag potential footguns. Suggest FP alternatives to mutable/imperative code. Point out architectural flaws like leaky abstractions, tight coupling, wrong level of abstraction, poor type modeling, over-abstraction, unclear domain boundaries. Code should generally be organized based on business concerns rather than technical aspects - suggest improvements if you find violations. Point out gaps in test coverage but suggest tests that are not too coupled to the implementation and actually test domain invariants and business logic

Files:

  • README.md
  • AGENTS.md
  • SPEC.md
**/*.md

⚙️ CodeRabbit configuration file

Focus on the contents of the docs and not on cosmetic things like markdown formatting. We use markdown files for various docs including but not limited to guidelines for AI contributors (AGENTS.md), project overview and instructions for human contributors (README.md), and topic-focused references under docs/ (cqrs.md, sqlx.md, ttdd.md). Think about the target audience of a document when deciding what comment to leave. For instructions, suggest better rules and guidelines and point out missing instructions. For topic references, suggest improvements that would make non-obvious framework behavior or pitfalls easier to discover. In all cases, flag needless bloat, prefer clear concise writing, and consider the structure of the document and order of the sections

Files:

  • README.md
  • AGENTS.md
  • docs/domain.md
  • examples/simple/README.md
  • SPEC.md
  • docs/cqrs.md
AGENTS.md

📄 CodeRabbit inference engine (CLAUDE.md)

Refer to AGENTS.md documentation for agent-specific guidelines and requirements

When editing AGENTS.md, keep the file under 40,000 characters and use wc -c AGENTS.md to check the size; if it exceeds the limit, condense explanations rather than removing guidelines.

Files:

  • AGENTS.md
docs/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Update or add documentation under docs/ when research or trial-and-error reveals non-obvious patterns, pitfalls, or framework behavior; prioritize documenting framework idioms, integration gotchas, and failures like "X doesn't work because Y".

Files:

  • docs/domain.md
  • docs/cqrs.md
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Before doing any work, read `SPEC.md` and `docs/domain.md`; read `docs/cqrs.md`, `docs/sqlx.md`, and `docs/ttdd.md` when they are relevant to the task.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Treat `SPEC.md` as the source of truth: new features must be spec'ed there first, and if a change contradicts the spec, update the spec first with user approval or change the implementation approach.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Follow the project document hierarchy: SPEC.md first, then ROADMAP.md/GitHub issues, then planning, then tests, then implementation.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Organize planning around the goal and decompose epics by coupling boundaries so each branch is independently valid, with shared dependencies extracted first and integration deferred to the end.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Every pull request must be associated with at least one Linear issue, and split PRs must have split issues/sub-issues that each PR references or closes.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Keep pull requests small: prefer under 500 additions, allow up to 1,000 only when splitting would be artificial, and split larger work when possible.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Keep a granular task list for the current request and remove completed tasks from the active list as work progresses.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: All new or modified logic must have corresponding test coverage before moving on.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Before implementing, deeply understand the task by reading relevant docs and source, forming and critiquing an initial approach, and keeping the resulting diff small and reviewable.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: If the user asks a question or a new approach is proposed, answer first and do not silently change direction; ask for confirmation before changing approach unless the user already clearly told you to proceed.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: When the user points out a bug or problem, fix it immediately and re-evaluate the rest of the session work for similar issues.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: If user action is required and the task is blocked, stop after stating what you need; if not blocked, continue but clearly state the request when stopping.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: If a significant architectural decision is not already covered by docs, write an ADR under `adrs/$INDEX-$PROPOSAL_NAME.md`, summarize it for the user, and stop for review before proceeding.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Before handing over, self-review the diff, revert unjustified changes, and remove any scope creep.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Use `cargo check`, `cargo nextest run`, `cargo clippy`, and `cargo fmt` as the normal verification flow; do not use `cargo build` for routine verification.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Never manually create migration files; use `sqlx migrate add <migration_name>` instead, and do not add further migrations to the `events` table after the initial one.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Never manually edit `Cargo.toml` to add dependencies; use `cargo add` so version resolution and features are handled correctly.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Do not run commands just to show output, do not run speculative binaries, and do not write ad-hoc scripts for debugging or automation.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: In consuming applications, each aggregate must have exactly one `SqliteCqrs<A>` instance created once at startup; do not construct it per request except in tests, CLI, or migration code.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Never write directly to the `events` table; always emit events through `CqrsFramework::execute()` or `execute_with_metadata()`.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Use cqrs-es services for side effects in aggregate `handle()` methods so event emission and side effects remain atomic.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Log command execution in the aggregate's `handle()` method, not at the call site.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Model invalid states in types: use ADTs/enums, newtypes, and typestate rather than runtime validation when possible.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Accept domain newtypes and convert to SDK primitives inside the callee, except at cross-crate boundaries where the callee cannot depend on caller domain types.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Keep schemas consistent with type modeling: avoid contradictory columns and avoid denormalized columns that can be computed from other data.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Prefer functional/ADT patterns, iterators, and pattern matching over imperative loops unless complexity increases.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Follow the import organization rule: external imports first, then workspace imports, then crate-internal imports; no function-level imports except enum-variant imports inside function bodies.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Use top-of-module imports only, qualify imports only when needed to prevent ambiguity, and keep test-module imports inside the test module itself.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Do not use `unwrap()` or `.expect()` in production code; they are acceptable in test code only.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Design error types without opaque `String` payloads; prefer typed variants, `#[from]`, `?`, `#[source]`, and context-preserving error handling.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Always log a warning or error before an early return in `let-else` or similar patterns that would otherwise fail silently.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Keep visibility as restrictive as possible, preferring private items over `pub(crate)` over `pub`.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Only add type aliases when clippy requires them for type complexity; otherwise prefer the full type or use newtypes to distinguish concepts.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Never silently mask numeric failures: no capping, fallback defaults, precision truncation, or `unwrap_or*` on numeric values; use explicit error handling and checked conversions.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Never read files containing secrets or sensitive configuration without explicit user permission; treat `.env*`, key/cert files, and sensitive databases as protected.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Test strategy: use in-memory SQLite databases via `sqlite_es::testing::create_test_pool()`, cover edge cases, and keep most coverage in unit tests.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Tests must assert correct behavior, not document known gaps; do not delete, skip, or bypass existing tests to ease a refactor.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Prefer property-based testing with `proptest` when invariants, roundtrips, boundaries, or numeric edge cases are a good fit.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Use `assert_eq!` with exact values in tests; avoid `assert!(is_some())`, `assert!(is_err())`, and `assert!(is_ok())`, and assert serialized output against literals like `json!()`.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: In production code, prefer exhaustive `match` over `matches!` so the compiler catches new variants; `matches!` is acceptable in tests.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Use ASCII in identifiers, comments, log messages, and config keys; use unicode only in user-facing string literals when it improves readability.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Do not use single-letter variable names, arguments, or generic type parameters except for short, unambiguous closures.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Keep modules flat by default, put public API before private implementation and tests, and add a `//!` docstring to every module.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Keep doc comment and long macro string lines under 100 characters.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Use no one-line helpers; inline single-expression helpers unless they encapsulate multi-step logic.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Do not split simple-but-long pattern matches into tiny helpers; keep a single match when arms are trivial, even if it exceeds line-count lints, and ask for permission before suppressing such lints.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: During development, scope checks to the active package first, then run full workspace checks before handover.
Learnt from: CR
Repo: ST0x-Technology/event-sorcery

Timestamp: 2026-06-27T03:19:38.104Z
Learning: Never bypass, disable, or suppress quality-control mechanisms without explicit permission; if a lint seems intentional, request permission before suppressing it.
🪛 LanguageTool
examples/simple/README.md

[grammar] ~5-~5: Use a hyphen to join words.
Context: ...d a materialized view backed by a SQLite generated column for filtered queries. ...

(QB_NEW_EN_HYPHEN)

🔇 Additional comments (19)
SPEC.md (4)

89-90: LGTM!


102-106: LGTM!


200-224: LGTM!


146-171: No issue JobBackend<J> is the worker-side apalis storage wrapper for a single job type, so the description is accurate.

docs/cqrs.md (3)

72-77: LGTM!


89-92: LGTM!


683-707: LGTM!

docs/domain.md (3)

60-67: LGTM!


130-143: LGTM!


195-207: LGTM!

AGENTS.md (4)

31-31: LGTM!


126-132: LGTM!


229-229: LGTM!


325-328: No issue: nushell is already included in the dev shell, so the scripting policy matches the project tooling.

			> Likely an incorrect or invalid review comment.
README.md (1)

38-38: LGTM!

examples/simple/README.md (4)

4-5: 🎯 Functional Correctness | ⚡ Quick win

Ambiguous phrasing: "commands carry... a materialized view"

Line 5 parses as if the commands carry both a timestamp and a materialized view, which is impossible. The "whose" antecedent (SupportTicket aggregate) should distribute clearly across two predicates. Insert a comma before "and" or restructure:

-`Open -> Pending -> Closed`, whose commands carry their own timestamp and a
-materialized view backed by a SQLite generated column for filtered queries.
+`Open -> Pending -> Closed`, whose commands carry their own timestamp, with a
+materialized view backed by a SQLite generated column for filtered queries.

Or more explicitly:

-`Open -> Pending -> Closed`, whose commands carry their own timestamp and a
-materialized view backed by a SQLite generated column for filtered queries.
+`Open -> Pending -> Closed`. Commands carry their own timestamp; a
+materialized view backed by a SQLite generated column enables filtered queries.

22-23: LGTM!


51-57: 🎯 Functional Correctness | ⚡ Quick win

Broken inline code span across line break.

Lines 54-55 split `Open { subject, and at }` across two lines. Most Markdown renderers will break the inline code span at the newline or render it incorrectly. Keep each code fragment on one line:

-`Open { subject,
-at }`, `Close { at }`. Production passes `chrono::Utc::now()`;
+`Open { subject, at }`, `Close { at }`. Production passes `chrono::Utc::now()`;

Also consider mentioning AwaitCustomer { at } since it completes the Open -> Pending -> Closed flow described in the opening.


59-63: jobs![...] matches the crate macro syntax.

Comment thread docs/cqrs.md
Comment on lines +245 to +311
## Jobs Pattern

Handlers are sync and pure: they must not call external systems. Side-effecting
work is enqueued as a durable job and runs in a separate worker. The enqueue
commits in the same SQLite transaction as the events that triggered it, so a job
exists iff its events do.

The worker retries `perform` on failure and re-runs it after a crash, so jobs
are delivered **at-least-once** -- `perform` must be idempotent. Carry any dedup
key in the job payload or `Input`.

Declare a job and the entity's job list:

```rust
#[derive(Serialize, Deserialize)]
struct PlaceOrder { order_id: OrderId, quantity: u32 }

impl Job for PlaceOrder {
type Input = Arc<dyn OrderPlacer>; // dependency bundle, injected by the worker
type Output = ();
type Error = PlaceOrderError;

Inject external dependencies into command handlers:
const WORKER_NAME: &'static str = "place-order";
const KIND: &'static str = "PlaceOrder";

fn label(&self) -> Label { Label(format!("place-order:{}", self.order_id)) }

async fn perform(&self, placer: &Self::Input) -> Result<(), Self::Error> {
placer.place_order(self.order_id, self.quantity).await
}
}
```

```rust
type Services = Arc<dyn OrderPlacer>;
type Jobs = jobs![PlaceOrder]; // Nil if the entity dispatches none
```

async fn transition(
Enqueue from a handler through the `jobs` handle. `push` is synchronous and
buffers; the framework flushes the buffer at commit. `push::<J>` only compiles
when `J` is in the entity's `Jobs` list (`HasJob<J>`):

```rust
fn transition(
&self,
command: Self::Command,
services: &Self::Services,
jobs: &mut JobQueue<Self::Jobs>,
) -> Result<Vec<Self::Event>, Self::Error> {
let result = services.place_order(/* ... */).await?;
Ok(vec![MyEvent::OrderPlaced { /* ... */ }])
jobs.push(PlaceOrder { order_id: self.id, quantity: command.quantity });
Ok(vec![MyEvent::OrderRequested { /* ... */ }])
}
```

Pass services when building the `Store`:
A queued row is never observable mid-handler -- the push is buffered, not a live
`INSERT`. Reads a handler once did via `Services` (clock, config, idempotency
keys) move into the `Command`; the caller supplies them at dispatch time.

Run the jobs in a worker, wired with the shared retry/backoff/circuit-breaker
policy. `Input` is the only context handed in:

```rust
let store = StoreBuilder::<MyEntity>::new(pool)
.build(services)
.await?;
```
let placer: Arc<dyn OrderPlacer> = Arc::new(/* ... */);
let backend = JobBackend::<PlaceOrder>::new(&pool);

For entities that don't need services, use `type Services = ()`.
Monitor::new().register(build_supervised_worker!(
::<PlaceOrder>, 0, backend.into_storage(), placer, fail_stop, failure_notify,
));
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify Job trait definition and its required items
rg -n "trait Job" --type=rust -A 30
rg -n "WORKER_NAME|TERMINAL_FAILURE_MSG|fn label" --type=rust

Repository: ST0x-Technology/event-sorcery

Length of output: 167


🏁 Script executed:

#!/bin/bash
# Verify build_supervised_worker! macro definition and usage
rg -n "macro_rules! build_supervised_worker" --type=rust -A 20

Repository: ST0x-Technology/event-sorcery

Length of output: 167


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the repository and locate relevant Rust/doc files
git ls-files | sed -n '1,220p'

Repository: ST0x-Technology/event-sorcery

Length of output: 1924


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the Job trait and the worker helper definitions/usages
sed -n '1,240p' crates/event-sorcery/src/job.rs
printf '\n---\n'
rg -n "build_supervised_worker|supervised_worker|Worker" crates/event-sorcery crates/sqlite-es examples docs -S -g '!target'

Repository: ST0x-Technology/event-sorcery

Length of output: 9922


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the build_supervised_worker! macro definition and nearby usage
sed -n '420,560p' crates/event-sorcery/src/job.rs
printf '\n---\n'
sed -n '800,850p' crates/event-sorcery/src/job.rs
printf '\n---\n'
sed -n '280,320p' docs/cqrs.md

Repository: ST0x-Technology/event-sorcery

Length of output: 8036


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect JobBackend::into_storage and the surrounding API
rg -n "fn into_storage|into_storage\\(" crates/event-sorcery/src/job.rs -A 8 -B 8

Repository: ST0x-Technology/event-sorcery

Length of output: 1210


Fix the worker example to pass JobBackend directly.
Job, WORKER_NAME, KIND, TERMINAL_FAILURE_MSG, and label() match the API, but build_supervised_worker! already calls .into_storage() internally. Pass backend, not backend.into_storage(), or the example will try to convert the storage twice. docs/cqrs.md:304-311

🤖 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 `@docs/cqrs.md` around lines 245 - 311, The worker example is converting the
job backend to storage twice, because build_supervised_worker! already handles
the storage conversion internally. Update the jobs worker example that uses
JobBackend::<PlaceOrder> so it passes backend directly instead of
backend.into_storage(), while keeping the existing Job, WORKER_NAME, KIND, and
label() usage unchanged.

@0xgleb 0xgleb marked this pull request as draft June 27, 2026 04:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants