diff --git a/src/EventTests/AllDatabasesDefaultTests.cs b/src/EventTests/AllDatabasesDefaultTests.cs new file mode 100644 index 0000000..566ff3b --- /dev/null +++ b/src/EventTests/AllDatabasesDefaultTests.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.Metrics; +using System.Threading; +using System.Threading.Tasks; +using JasperFx.Descriptors; +using JasperFx.Events; +using JasperFx.Events.Daemon; +using JasperFx.Events.Descriptors; +using Microsoft.Extensions.Logging; +using Shouldly; + +namespace EventTests; + +public class AllDatabasesDefaultTests +{ + // A bare IEventStore that does NOT override AllDatabases(), so the call below exercises the + // default interface implementation added for jasperfx#387 (the "return empty array" stand-in + // for stores that don't yet expose their databases store-agnostically). Everything else throws — + // those members are never invoked here. + private sealed class BareEventStore : IEventStore + { + public Task TryCreateUsage(CancellationToken token) => throw new NotImplementedException(); + public Uri Subject => throw new NotImplementedException(); + + public ValueTask BuildProjectionDaemonAsync( + string? tenantIdOrDatabaseIdentifier = null, ILogger? logger = null) + => throw new NotImplementedException(); + + public ValueTask BuildProjectionDaemonAsync(DatabaseId id) + => throw new NotImplementedException(); + + public Meter Meter => throw new NotImplementedException(); + public ActivitySource ActivitySource => throw new NotImplementedException(); + public string MetricsPrefix => throw new NotImplementedException(); + public DatabaseCardinality DatabaseCardinality => throw new NotImplementedException(); + public bool HasMultipleTenants => throw new NotImplementedException(); + public EventStoreIdentity Identity => throw new NotImplementedException(); + public IReadOnlyEventStore OpenReadOnlyEventStore() => throw new NotImplementedException(); + + public Task CompactStreamAsync(Guid streamId, CancellationToken token = default) + => throw new NotImplementedException(); + + public Task CompactStreamAsync(string streamKey, CancellationToken token = default) + => throw new NotImplementedException(); + } + + private readonly IEventStore theStore = new BareEventStore(); + + [Fact] + public async Task all_databases_default_returns_empty() + { + var databases = await theStore.AllDatabases(); + databases.ShouldBeEmpty(); + } +} diff --git a/src/JasperFx.Events/IEventStore.cs b/src/JasperFx.Events/IEventStore.cs index 31af392..3d3f8ff 100644 --- a/src/JasperFx.Events/IEventStore.cs +++ b/src/JasperFx.Events/IEventStore.cs @@ -36,7 +36,18 @@ ValueTask BuildProjectionDaemonAsync( DatabaseCardinality DatabaseCardinality { get; } bool HasMultipleTenants { get; } - + + /// + /// Resolve every backing this event store, store-agnostically. + /// This is the store-neutral counterpart to Marten's IMartenStorage.AllDatabases() — it lets + /// monitoring/tooling code (e.g. CritterWatch) obtain an to call the read + /// abstractions (AllProjectionProgress, FetchDeadLetterCountsAsync, CountDeadLetterEventsAsync) + /// without referencing concrete store types. The default implementation returns an empty array as a + /// stand-in; event stores should override this to return their real databases. See jasperfx#387. + /// + ValueTask> AllDatabases() + => ValueTask.FromResult>([]); + /// /// Identifies the event store within an application ///