Repository navigation
Find aggregates by the contents of their unique keys - #536
Merged
erikrozendaal merged 5 commits intoOct 6, 2026
Merged
Conversation
find_aggregate_by_unique_key needs the whole key. Applications that keep a compound key, such as an employee and a period, also want every aggregate sharing part of it, and had to keep a view to find their ids. find_aggregates_by_unique_key_containing loads the aggregates whose key in a scope contains the given part, using jsonb's @>. An optional block receives each matching key and decides which aggregates are loaded, for conditions a containment check cannot express, such as a period range.
The unique key lookups only searched the committed keys, so within a unit of work an aggregate added moments earlier was not found by its key, and one whose key had changed was still found by its old key. A command creating an aggregate and then looking up its siblings by key would miss it. Both lookups now match the aggregates in the repository on their current keys, and leave out the committed keys of those aggregates, since the in-memory ones are the more recent. The containment check the fake event store used moves to UniqueKeys so the repository can use it as well.
find_aggregate_by_unique_key passed the event store the key normalized through JSON, which turned a date into a string. The database compares JSON so it did not mind, but the fake event store compares the key as given and no longer found an aggregate whose key holds a date. Only the in-memory match needs the normalized key.
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
In-memory containment does not mirror PostgreSQL for scalar values contained directly in JSON arrays.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Adds partial unique-key containment lookup across persisted and in-memory aggregates.
Changes:
- Adds repository and event-store containment APIs with optional filtering.
- Keeps real and fake event-store behavior aligned.
- Adds a concurrent GIN index migration and documentation.
| File | Description |
|---|---|
spec/lib/sequent/core/aggregate_unique_keys_spec.rb |
Tests unique-key lookup behavior. |
lib/sequent/test/command_handler_helpers.rb |
Implements containment for the fake store. |
lib/sequent/core/helpers/unique_keys.rb |
Adds key normalization and containment logic. |
lib/sequent/core/event_store.rb |
Queries contained JSONB keys. |
lib/sequent/core/aggregate_repository.rb |
Loads matching persisted and in-memory aggregates. |
db/structure.sql |
Records the extension and index. |
db/migrate/20260925120000_sequent_index_aggregate_unique_keys_by_scope_and_key.rb |
Creates the concurrent GIN index. |
CHANGELOG.md |
Documents the new API and migration. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
PostgreSQL's @> makes one exception to structural matching: an array at the top level contains a primitive that is one of its elements, so ['a', 'b'] is found by 'b'. UniqueKeys.contains? did not, so the aggregates in the repository and the fake event store missed array keys the database finds.
load_aggregates returns the aggregates already in the repository first, so the order of the keys was lost anyway. Say so instead of sorting for nothing.
erikrozendaal
deleted the
feature/find-aggregates-by-unique-key-containing
branch
October 6, 2026 14:14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

find_aggregate_by_unique_key needs the whole key. Applications that keep a compound key, such as an employee and a period, also want every aggregate sharing part of it, and had to keep a view to find their ids.
find_aggregates_by_unique_key_containing loads the aggregates whose key in a scope contains the given part, using jsonb's
@>operator. An optional block receives each matching key and decides which aggregates are loaded, for conditions a containment check cannot express, such as a period range.