Skip to content

Group the event store storage by Bounded Context - #1673

Merged
alexander-yevsyukov merged 8 commits into
masterfrom
event-store-context-prefix
Aug 27, 2026
Merged

Group the event store storage by Bounded Context#1673
alexander-yevsyukov merged 8 commits into
masterfrom
event-store-context-prefix

Conversation

@alexander-yevsyukov

Copy link
Copy Markdown
Contributor

This PR makes the event store of each Bounded Context land in its own physical
storage when the application runs on a storage backend which keys physical
storages by the record specification, such as jdbc-storage or gcloud-jvm.

Problem

All Bounded Contexts of an application share one StorageFactory.
DefaultEventStore created its record storage with no StorageGroup, and
its record specification is the same for every context (EventIdEvent).
Backends deriving the physical storage identity from the specification alone
therefore put the events of all contexts into one table
(spine_core_Event in jdbc-storage) or one Datastore kind
(spine.core.Event in gcloud-jvm):

  • events of all contexts (plus System contexts with persistEvents())
    intermingle in one physical store;
  • CatchUpProcess reads via EventStore.read(..) filtered by event type —
    when two contexts share an event proto type, catch-up in one context replays
    the events of the other;
  • there is no physical boundary for per-context data lifecycle.

InMemoryStorageFactory is unaffected only by accident: each
createRecordStorage(..) call returns a fresh, instance-isolated storage.
This is why tests never caught the issue.

Fix

DefaultEventStore now creates its record storage under a StorageGroup
named after the Bounded Context, via the new
StorageGroup.of(BoundedContextName) factory:

  • StorageGroup's documented purpose is exactly this: differentiating
    storages holding records of the same type, so a vendor does not conflate
    them — per-entity histories already use it.
  • Both group-honoring backends are fixed with no backend changes:
    jdbc-storage derives the Billing_Event table, gcloud-jvm the
    Billing-Event kind, through their existing grouped-naming paths.
  • InMemoryStorageFactory ignores groups — no behavior change in tests.

The follow-up work in jdbc-storage and gcloud-jvm (custom-name /
custom-layout API for context-grouped storages, migration notes) is planned in
.agents/tasks/event-store-context-prefix.md
and will be addressed in separate PRs after this one lands.

Migration note (release notes material)

On group-honoring backends the event log moves to a new per-context physical
storage. Existing deployments keep their data in the old shared storage
(spine_core_Event / kind spine.core.Event); operators split it by the
type column/property using each context's event-type set. Detailed guidance
is part of the planned jdbc-storage / gcloud-jvm follow-ups.

Testing

  • New EventStoreIdentitySpec asserts, at the createRecordStorage(..)
    vendor seam, that the event store arrives with the (group, recordType)
    identity (<context name>, Event), that two contexts produce two distinct
    identities, and that the group passes through SystemAwareStorageFactory
    intact.
  • New StorageGroupSpec (a ClassTest) covers both of(..) factories and
    null-checks the static API.
  • Full ./gradlew build dokkaGenerate passes locally, including the
    behavioral InMemoryDefaultEventStoreTest and the delivery/catch-up suites.

🤖 Generated with Claude Code

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9892f1d834

ℹ️ About Codex in GitHub

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

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

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

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

Comment thread server/src/main/kotlin/io/spine/server/storage/StorageGroup.kt
@alexander-yevsyukov alexander-yevsyukov self-assigned this Aug 26, 2026
@alexander-yevsyukov alexander-yevsyukov moved this to 🏗 In progress in v2.0 Aug 26, 2026
@alexander-yevsyukov
alexander-yevsyukov requested a lite review from Copilot August 26, 2026 23:48
@alexander-yevsyukov alexander-yevsyukov moved this from 🏗 In progress to In Review in v2.0 Aug 26, 2026

Copilot AI 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.

Pull request overview

This PR isolates DefaultEventStore persistence per Bounded Context by assigning the event store’s underlying record storage to a StorageGroup derived from the context name, preventing storage backends that key by record spec from conflating multiple contexts into a single physical store.

Changes:

  • Pass a context-derived StorageGroup when creating the event store record storage in DefaultEventStore.
  • Extend StorageGroup with of(BoundedContextName) and update its documentation to cover context-scoped grouping.
  • Add tests asserting the (group, recordType) identity reaching the StorageFactory.createRecordStorage(..) seam, plus a small StorageGroup factory spec.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
version.gradle.kts Bumps published snapshot version.
server/src/main/kotlin/io/spine/server/storage/StorageGroup.kt Adds of(BoundedContextName) for context-based grouping and updates KDoc.
server/src/main/java/io/spine/server/event/store/DefaultEventStore.java Creates event store record storage under a context-derived StorageGroup.
server/src/test/kotlin/io/spine/server/storage/StorageGroupSpec.kt Verifies StorageGroup factories for entity class and context name.
server/src/test/kotlin/io/spine/server/event/store/EventStoreIdentitySpec.kt Asserts event store storage identity is grouped by context and survives SystemAwareStorageFactory wrapping.
server/src/test/kotlin/io/spine/server/entity/storage/HistoryStorageIdentitySpec.kt Minor punctuation fix in KDoc.
docs/dependencies/pom.xml Updates generated dependencies POM version.
docs/dependencies/dependencies.md Updates generated dependency report version/timestamp.
.agents/tasks/event-store-context-prefix.md Task notes / follow-up plan (not reviewed per repo guidelines).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread server/src/main/kotlin/io/spine/server/storage/StorageGroup.kt
Copilot AI review requested due to automatic review settings August 26, 2026 23:52

Copilot AI 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.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings August 26, 2026 23:55

Copilot AI 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.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.82%. Comparing base (2df13c1) to head (5084bf8).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1673      +/-   ##
==========================================
- Coverage   87.87%   87.82%   -0.05%     
==========================================
  Files        1067     1067              
  Lines       22466    22468       +2     
  Branches     1090     1090              
==========================================
- Hits        19741    19733       -8     
- Misses       2346     2354       +8     
- Partials      379      381       +2     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Base automatically changed from encapsulate-abstract-entity-repository to master August 27, 2026 13:02
alexander-yevsyukov and others added 8 commits August 27, 2026 16:02
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`DefaultEventStore` now creates its record storage under a `StorageGroup`
named after the context, via the new `StorageGroup.of(BoundedContextName)`.
The event stores of all contexts of an application store records of the same
type, so the group is what keeps the event log of each context in its own
physical storage in vendors which map equal record specifications to one
table or kind.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A Codex review on the PR flagged that JDBC's dot-replacement table naming
aliases distinct group names (`Sales.EU` vs `Sales_EU`). The encoding fix
belongs to the planned `jdbc-storage` step; `StorageGroup`'s KDoc now
states the injective-mapping requirement as the SPI contract, and the task
plan details a collision-free scheme preserving existing table names.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…me)`

Normalization of the group name is deliberately a vendor concern: naming
rules differ per backend (SQL identifiers vs. Datastore kinds), and any
framework-level normalization would alias distinct names for all backends
at once. The factory KDoc now says so explicitly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@alexander-yevsyukov
alexander-yevsyukov force-pushed the event-store-context-prefix branch from 1b6de3e to 5084bf8 Compare August 27, 2026 13:02
@alexander-yevsyukov
alexander-yevsyukov merged commit f9a7dfe into master Aug 27, 2026
10 checks passed
@alexander-yevsyukov
alexander-yevsyukov deleted the event-store-context-prefix branch August 27, 2026 13:57
@github-project-automation github-project-automation Bot moved this from In Review to ✅ Done in v2.0 Aug 27, 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.

3 participants