Skip to content

chore(storage): generalize virtual stream readers#331

Merged
yordis merged 1 commit into
masterfrom
yordis/chore-virtual-stream-reader
May 13, 2026
Merged

chore(storage): generalize virtual stream readers#331
yordis merged 1 commit into
masterfrom
yordis/chore-virtual-stream-reader

Conversation

@yordis

@yordis yordis commented May 13, 2026

Copy link
Copy Markdown
Member
  • Keep storage read plumbing extensible as internal virtual streams grow beyond the current in-memory node streams.
  • Avoid treating virtual-stream ownership as a hard-coded stream-name prefix so future readers can opt in explicitly.
  • Reduce duplicate subscription/read-state handling before the larger storage and indexing tracks continue.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@cursor

cursor Bot commented May 13, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes the read/subscription dispatch path for special $mem-* streams by replacing hard-coded prefix routing with an extensible IVirtualStreamReader interface and async reads; bugs here could affect reads or subscriptions to virtual/system streams.

Overview
Replaces the old InMemoryStreamReader/IInMemoryStreamReader and $mem- prefix routing with a new extensible IVirtualStreamReader + VirtualStreamReader that selects a backing reader via CanReadStream, supports cancellation-aware async ReadForwards/ReadBackwards, and exposes GetLastEventNumber/GetLastIndexedPosition.

Updates storage read plumbing (ClusterVNode, StorageReaderService/StorageReaderWorker) and subscriptions (SubscriptionsService) to use the virtual reader for dispatch and initial subscription state, while GossipListenerService and NodeStateListenerService now expose their SingleEventInMemoryStream via a Stream property instead of implementing read interfaces directly. Tests are renamed/updated for async virtual reads and add coverage for unknown virtual streams returning NoStream.

Reviewed by Cursor Bugbot for commit 6ceee97. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented May 13, 2026

Copy link
Copy Markdown

Walkthrough

This PR replaces the synchronous IInMemoryStreamReader infrastructure with an asynchronous IVirtualStreamReader pattern. A new VirtualStreamReader aggregates stream readers and delegates to matching implementations by stream ID. Services are rewired to use the virtual reader with async/await patterns and cancellation support.

Changes

Virtual Stream Reader Infrastructure Refactoring

Layer / File(s) Summary
New async interface and implementations
src/EventStore.Core/Services/Storage/InMemory/IVirtualStreamReader.cs, src/EventStore.Core/Services/Storage/InMemory/VirtualStreamReader.cs, src/EventStore.Core/Services/Storage/InMemory/SingleEventInMemoryStream.cs
New IVirtualStreamReader interface defines async read methods via ValueTask, stream metadata queries, and readability checks. VirtualStreamReader selects and delegates to underlying readers by stream ID, returning standardized "no stream" responses when no reader matches. SingleEventInMemoryStream now implements IVirtualStreamReader with async methods.
Remove old sync interface
src/EventStore.Core/Services/Storage/InMemory/IInMemoryStreamReader.cs, src/EventStore.Core/Services/Storage/InMemory/InMemoryStreamReader.cs
Removed IInMemoryStreamReader interface and its InMemoryStreamReader implementation. This infrastructure is replaced by the virtual reader pattern.
Expose listener streams as public properties
src/EventStore.Core/Services/Storage/InMemory/GossipListenerService.cs, src/EventStore.Core/Services/Storage/InMemory/NodeStateListenerService.cs
GossipListenerService and NodeStateListenerService now expose underlying streams via public Stream properties. NodeStateListenerService drops IInMemoryStreamReader implementation and exposes its stream for composition into VirtualStreamReader.
Wire virtual reader in storage and subscriptions
src/EventStore.Core/ClusterVNode.cs, src/EventStore.Core/Services/Storage/StorageReaderService.cs, src/EventStore.Core/Services/Storage/StorageReaderWorker.cs, src/EventStore.Core/Services/SubscriptionsService.cs
ClusterVNode constructs VirtualStreamReader from gossip and node state listener streams and injects it into StorageReaderService and SubscriptionsService. StorageReaderWorker routes virtual-stream reads via IVirtualStreamReader.CanReadStream() checks, falling back to persistent storage when the virtual reader does not claim the stream. SubscriptionsService uses the virtual reader to initialize subscriptions and detect missed events.
Remove in-memory stream detection helper
src/EventStore.Core/Services/SystemNames.cs
Removes SystemStreams.IsInMemoryStream() static method. Stream type detection now uses IVirtualStreamReader.CanReadStream() instead. Adds ScavengePointsStream and AuthorizationPolicyRegistryStream constants.
Update tests to async virtual reader
src/EventStore.Core.Tests/Services/Storage/when_cancelling_storage_reader_worker.cs, src/EventStore.Core.XUnit.Tests/Services/Storage/InMemory/VirtualStreamReaderTests.cs
Test fixtures inject StubVirtualStreamReader and test methods are converted to async Task with ValueTask-based read calls and CancellationToken.None. New MissingReaderTests verify "no stream" behavior when no reader claims a stream ID.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant StorageReaderWorker
    participant VirtualStreamReader
    participant SingleEventInMemoryStream as NodeState/Gossip<br/>Stream
    participant PersistentStorage

    Client->>StorageReaderWorker: ReadStreamEventsForward(streamId)
    StorageReaderWorker->>VirtualStreamReader: CanReadStream(streamId)
    alt Virtual Stream
        VirtualStreamReader->>SingleEventInMemoryStream: Match found
        StorageReaderWorker->>VirtualStreamReader: ReadForwards(msg, token)
        VirtualStreamReader->>SingleEventInMemoryStream: ReadForwards(msg, token)
        SingleEventInMemoryStream-->>VirtualStreamReader: ValueTask<ReadStreamEventsForwardCompleted>
        VirtualStreamReader-->>StorageReaderWorker: forwarded result
    else Persistent Stream
        StorageReaderWorker->>PersistentStorage: ReadStreamEventsForward(streamId)
        PersistentStorage-->>StorageReaderWorker: result
    end
    StorageReaderWorker-->>Client: ReadStreamEventsForwardCompleted
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • TrogonStack/TrogonEventStore#236: Both PRs modify StorageReaderWorker.cs request handling logic; this PR introduces virtual reader routing, while the related PR addresses cancellation token multiplexing in the same methods.

Poem

A rabbit hops through streams of virtual delight,
Async readers now delegate with grace,
Old sync methods fade into the night,
ValueTasks spring forth in every place! 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: introducing a generalized virtual stream readers abstraction to replace hard-coded in-memory stream handling.
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.
Description check ✅ Passed The PR description clearly relates to the changeset, outlining the refactoring goals: generalizing virtual stream readers, avoiding hard-coded stream-name prefixes, and reducing duplication.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 yordis/chore-virtual-stream-reader

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 and usage tips.

@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 (2)
src/EventStore.Core/Services/Storage/StorageReaderService.cs (1)

34-67: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add parameter validation for virtualStreamReader.

The constructor validates most injected dependencies with Ensure.NotNull(), but virtualStreamReader is missing this check. For consistency and to fail fast with a clear error message, add validation at line 52:

✨ Proposed fix
 		Ensure.NotNull(bus, "bus");
 		Ensure.NotNull(subscriber, "subscriber");
 		Ensure.NotNull(readIndex, "readIndex");
 		Ensure.NotNull(systemStreams, nameof(systemStreams));
 		Ensure.Positive(threadCount, "threadCount");
 		Ensure.NotNull(writerCheckpoint, "writerCheckpoint");
+		Ensure.NotNull(virtualStreamReader, nameof(virtualStreamReader));
🤖 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 `@src/EventStore.Core/Services/Storage/StorageReaderService.cs` around lines 34
- 67, The constructor StorageReaderService is missing validation for the
virtualStreamReader parameter; add a null-check using
Ensure.NotNull(virtualStreamReader, "virtualStreamReader") (matching the style
of other deps) near the top of the StorageReaderService constructor so the
injected IVirtualStreamReader is validated and fails fast with a clear message.
src/EventStore.Core/Services/Storage/StorageReaderWorker.cs (1)

57-76: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add parameter validation for virtualStreamReader.

The constructor validates several injected dependencies with Ensure.NotNull(), but virtualStreamReader is missing this check. For consistency and to fail fast with a clear error message, add validation after line 68:

✨ Proposed fix
 		Ensure.NotNull(publisher, "publisher");
 		Ensure.NotNull(readIndex, "readIndex");
 		Ensure.NotNull(systemStreams, nameof(systemStreams));
 		Ensure.NotNull(writerCheckpoint, "writerCheckpoint");
+		Ensure.NotNull(virtualStreamReader, nameof(virtualStreamReader));
 
 		_publisher = publisher;
 		_readIndex = readIndex;
 		_systemStreams = systemStreams;
 		_writerCheckpoint = writerCheckpoint;
 		_queueId = queueId;
 		_virtualStreamReader = virtualStreamReader;
🤖 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 `@src/EventStore.Core/Services/Storage/StorageReaderWorker.cs` around lines 57
- 76, Add a null-check for the virtualStreamReader parameter in the
StorageReaderWorker constructor by calling Ensure.NotNull(virtualStreamReader,
nameof(virtualStreamReader)) alongside the other Ensure.NotNull checks so the
constructor fails fast with a clear error when virtualStreamReader is null.
🧹 Nitpick comments (6)
src/EventStore.Core/Services/Storage/InMemory/SingleEventInMemoryStream.cs (4)

30-32: ⚡ Quick win

Unused CancellationToken parameter.

The token parameter is accepted but never checked. Even for synchronous operations wrapped in ValueTask.FromResult, consider adding token.ThrowIfCancellationRequested() at the method start to respect caller cancellation requests.

♻️ Proposed fix to respect cancellation
 public ValueTask<ClientMessage.ReadStreamEventsForwardCompleted> ReadForwards(
 	ClientMessage.ReadStreamEventsForward msg,
 	CancellationToken token)
 {
+	token.ThrowIfCancellationRequested();
 
 	ReadStreamResult result;
🤖 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 `@src/EventStore.Core/Services/Storage/InMemory/SingleEventInMemoryStream.cs`
around lines 30 - 32, The ReadForwards method accepts a CancellationToken
parameter (token) but never checks it; add an early cancellation check at the
start of ReadForwards by calling token.ThrowIfCancellationRequested() so the
method honors caller cancellation requests before constructing/returning the
ClientMessage.ReadStreamEventsForwardCompleted ValueTask; reference the
ReadForwards method and the ClientMessage.ReadStreamEventsForwardCompleted
return type and ensure the token.ThrowIfCancellationRequested() call is placed
before any work or returning ValueTask.FromResult.

136-136: ⚡ Quick win

Missing streamId validation in GetLastEventNumber.

The method accepts a streamId parameter but doesn't validate that it matches _streamName. While the VirtualStreamReader should only call this after CanReadStream returns true, defensive programming suggests adding a guard to prevent incorrect results if called with an unowned stream ID.

🛡️ Proposed fix to add validation
-public long GetLastEventNumber(string streamId) => _lastEvent?.EventNumber ?? ExpectedVersion.NoStream;
+public long GetLastEventNumber(string streamId)
+{
+	if (streamId != _streamName)
+		throw new ArgumentException($"Stream '{streamId}' is not owned by this reader", nameof(streamId));
+	return _lastEvent?.EventNumber ?? ExpectedVersion.NoStream;
+}
🤖 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 `@src/EventStore.Core/Services/Storage/InMemory/SingleEventInMemoryStream.cs`
at line 136, GetLastEventNumber currently ignores the streamId parameter which
can return incorrect data if called for a different stream; add a guard at the
start of GetLastEventNumber(string streamId) to validate that streamId equals
the instance's _streamName (or throw
ArgumentException/ArgumentOutOfRangeException) and only then return
_lastEvent?.EventNumber ?? ExpectedVersion.NoStream; this ensures the method
refuses or fails fast on unowned stream IDs.

138-138: ⚡ Quick win

Missing streamId validation in GetLastIndexedPosition.

The method accepts a streamId parameter but doesn't validate that it matches _streamName. Consider adding the same defensive guard as suggested for GetLastEventNumber.

🛡️ Proposed fix to add validation
-public long GetLastIndexedPosition(string streamId) => -1;
+public long GetLastIndexedPosition(string streamId)
+{
+	if (streamId != _streamName)
+		throw new ArgumentException($"Stream '{streamId}' is not owned by this reader", nameof(streamId));
+	return -1;
+}
🤖 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 `@src/EventStore.Core/Services/Storage/InMemory/SingleEventInMemoryStream.cs`
at line 138, GetLastIndexedPosition currently ignores the streamId parameter;
add the same defensive validation used in GetLastEventNumber to ensure streamId
equals _streamName (and throw the same exception type/message used there) before
returning the position, so the method validates input consistency with the
in-memory stream implementation.

82-84: ⚡ Quick win

Unused CancellationToken parameter.

The token parameter is accepted but never checked. Even for synchronous operations wrapped in ValueTask.FromResult, consider adding token.ThrowIfCancellationRequested() at the method start to respect caller cancellation requests.

♻️ Proposed fix to respect cancellation
 public ValueTask<ClientMessage.ReadStreamEventsBackwardCompleted> ReadBackwards(
 	ClientMessage.ReadStreamEventsBackward msg,
 	CancellationToken token)
 {
+	token.ThrowIfCancellationRequested();
 
 	ReadStreamResult result;
🤖 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 `@src/EventStore.Core/Services/Storage/InMemory/SingleEventInMemoryStream.cs`
around lines 82 - 84, The ReadBackwards method accepts a CancellationToken
parameter (token) but never observes it; update the
ClientMessage.ReadStreamEventsBackward ReadBackwards method to check for
cancellation immediately (e.g., call token.ThrowIfCancellationRequested() at the
start of the method) before any synchronous work or returning
ValueTask.FromResult so the caller's cancellation request is respected.
src/EventStore.Core/Services/Storage/InMemory/VirtualStreamReader.cs (2)

43-66: ⚡ Quick win

Consider checking CancellationToken in fallback path.

When no reader claims the stream, the fallback returns a synchronous result without checking the token. For consistency with the delegated path, consider adding token.ThrowIfCancellationRequested() before the fallback return.

♻️ Proposed fix to check cancellation in fallback
 public ValueTask<ClientMessage.ReadStreamEventsBackwardCompleted> ReadBackwards(
 	ClientMessage.ReadStreamEventsBackward msg,
 	CancellationToken token)
 {
 	if (TryGetReader(msg.EventStreamId, out var reader))
 	{
 		return reader.ReadBackwards(msg, token);
 	}
+	token.ThrowIfCancellationRequested();
 
 	return ValueTask.FromResult(new ClientMessage.ReadStreamEventsBackwardCompleted(
🤖 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 `@src/EventStore.Core/Services/Storage/InMemory/VirtualStreamReader.cs` around
lines 43 - 66, The fallback path in VirtualStreamReader.ReadBackwards returns a
synchronous ValueTask without honoring the CancellationToken; update
ReadBackwards so that if TryGetReader(msg.EventStreamId, out var reader) is
false it first calls token.ThrowIfCancellationRequested() (or checks
token.IsCancellationRequested and returns a canceled ValueTask) before returning
the new ClientMessage.ReadStreamEventsBackwardCompleted result, ensuring
behavior matches the delegated reader.ReadBackwards(msg, token) path.

18-41: ⚡ Quick win

Consider checking CancellationToken in fallback path.

When no reader claims the stream, the fallback returns a synchronous result without checking the token. For consistency with the delegated path, consider adding token.ThrowIfCancellationRequested() before the fallback return.

♻️ Proposed fix to check cancellation in fallback
 public ValueTask<ClientMessage.ReadStreamEventsForwardCompleted> ReadForwards(
 	ClientMessage.ReadStreamEventsForward msg,
 	CancellationToken token)
 {
 	if (TryGetReader(msg.EventStreamId, out var reader))
 	{
 		return reader.ReadForwards(msg, token);
 	}
+	token.ThrowIfCancellationRequested();
 
 	return ValueTask.FromResult(new ClientMessage.ReadStreamEventsForwardCompleted(
🤖 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 `@src/EventStore.Core/Services/Storage/InMemory/VirtualStreamReader.cs` around
lines 18 - 41, The ReadForwards method currently returns a synchronous fallback
ValueTask when TryGetReader fails but doesn't honor the CancellationToken;
before returning the fallback ValueTask.FromResult in ReadForwards, call
token.ThrowIfCancellationRequested() so cancellation is handled consistently
with the delegated reader path (refer to ReadForwards, TryGetReader,
CancellationToken token and the fallback ValueTask.FromResult).
🤖 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 `@src/EventStore.Core/Services/Storage/StorageReaderService.cs`:
- Around line 34-67: The constructor StorageReaderService is missing validation
for the virtualStreamReader parameter; add a null-check using
Ensure.NotNull(virtualStreamReader, "virtualStreamReader") (matching the style
of other deps) near the top of the StorageReaderService constructor so the
injected IVirtualStreamReader is validated and fails fast with a clear message.

In `@src/EventStore.Core/Services/Storage/StorageReaderWorker.cs`:
- Around line 57-76: Add a null-check for the virtualStreamReader parameter in
the StorageReaderWorker constructor by calling
Ensure.NotNull(virtualStreamReader, nameof(virtualStreamReader)) alongside the
other Ensure.NotNull checks so the constructor fails fast with a clear error
when virtualStreamReader is null.

---

Nitpick comments:
In `@src/EventStore.Core/Services/Storage/InMemory/SingleEventInMemoryStream.cs`:
- Around line 30-32: The ReadForwards method accepts a CancellationToken
parameter (token) but never checks it; add an early cancellation check at the
start of ReadForwards by calling token.ThrowIfCancellationRequested() so the
method honors caller cancellation requests before constructing/returning the
ClientMessage.ReadStreamEventsForwardCompleted ValueTask; reference the
ReadForwards method and the ClientMessage.ReadStreamEventsForwardCompleted
return type and ensure the token.ThrowIfCancellationRequested() call is placed
before any work or returning ValueTask.FromResult.
- Line 136: GetLastEventNumber currently ignores the streamId parameter which
can return incorrect data if called for a different stream; add a guard at the
start of GetLastEventNumber(string streamId) to validate that streamId equals
the instance's _streamName (or throw
ArgumentException/ArgumentOutOfRangeException) and only then return
_lastEvent?.EventNumber ?? ExpectedVersion.NoStream; this ensures the method
refuses or fails fast on unowned stream IDs.
- Line 138: GetLastIndexedPosition currently ignores the streamId parameter; add
the same defensive validation used in GetLastEventNumber to ensure streamId
equals _streamName (and throw the same exception type/message used there) before
returning the position, so the method validates input consistency with the
in-memory stream implementation.
- Around line 82-84: The ReadBackwards method accepts a CancellationToken
parameter (token) but never observes it; update the
ClientMessage.ReadStreamEventsBackward ReadBackwards method to check for
cancellation immediately (e.g., call token.ThrowIfCancellationRequested() at the
start of the method) before any synchronous work or returning
ValueTask.FromResult so the caller's cancellation request is respected.

In `@src/EventStore.Core/Services/Storage/InMemory/VirtualStreamReader.cs`:
- Around line 43-66: The fallback path in VirtualStreamReader.ReadBackwards
returns a synchronous ValueTask without honoring the CancellationToken; update
ReadBackwards so that if TryGetReader(msg.EventStreamId, out var reader) is
false it first calls token.ThrowIfCancellationRequested() (or checks
token.IsCancellationRequested and returns a canceled ValueTask) before returning
the new ClientMessage.ReadStreamEventsBackwardCompleted result, ensuring
behavior matches the delegated reader.ReadBackwards(msg, token) path.
- Around line 18-41: The ReadForwards method currently returns a synchronous
fallback ValueTask when TryGetReader fails but doesn't honor the
CancellationToken; before returning the fallback ValueTask.FromResult in
ReadForwards, call token.ThrowIfCancellationRequested() so cancellation is
handled consistently with the delegated reader path (refer to ReadForwards,
TryGetReader, CancellationToken token and the fallback ValueTask.FromResult).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a6ac1d07-52e0-4e2a-81b6-b015272db955

📥 Commits

Reviewing files that changed from the base of the PR and between ec8ec72 and 6ceee97.

📒 Files selected for processing (14)
  • src/EventStore.Core.Tests/Services/Storage/when_cancelling_storage_reader_worker.cs
  • src/EventStore.Core.XUnit.Tests/Services/Storage/InMemory/VirtualStreamReaderTests.cs
  • src/EventStore.Core/ClusterVNode.cs
  • src/EventStore.Core/Services/Storage/InMemory/GossipListenerService.cs
  • src/EventStore.Core/Services/Storage/InMemory/IInMemoryStreamReader.cs
  • src/EventStore.Core/Services/Storage/InMemory/IVirtualStreamReader.cs
  • src/EventStore.Core/Services/Storage/InMemory/InMemoryStreamReader.cs
  • src/EventStore.Core/Services/Storage/InMemory/NodeStateListenerService.cs
  • src/EventStore.Core/Services/Storage/InMemory/SingleEventInMemoryStream.cs
  • src/EventStore.Core/Services/Storage/InMemory/VirtualStreamReader.cs
  • src/EventStore.Core/Services/Storage/StorageReaderService.cs
  • src/EventStore.Core/Services/Storage/StorageReaderWorker.cs
  • src/EventStore.Core/Services/SubscriptionsService.cs
  • src/EventStore.Core/Services/SystemNames.cs
💤 Files with no reviewable changes (3)
  • src/EventStore.Core/Services/Storage/InMemory/IInMemoryStreamReader.cs
  • src/EventStore.Core/Services/Storage/InMemory/InMemoryStreamReader.cs
  • src/EventStore.Core/Services/SystemNames.cs

@yordis yordis merged commit cf178a9 into master May 13, 2026
22 checks passed
@yordis yordis deleted the yordis/chore-virtual-stream-reader branch May 13, 2026 05:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant