From 699470d640ebbd58cb2173f2c6d38667f473414a Mon Sep 17 00:00:00 2001 From: William Chong Date: Fri, 1 Nov 2024 20:52:15 +0400 Subject: [PATCH] Account for nullable events (#324) * Account for nullable events * Fix json vulnerability * Upgrade deprecated gh actions * Fix tests * Remove susbcribe_to_stream test --- .../Diagnostics/ActivitySourceExtensions.cs | 4 +- .../StreamsTracingInstrumentationTests.cs | 47 +++++++++++++++++++ .../Fixtures/DiagnosticsFixture.cs | 2 +- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/EventStore.Client/Common/Diagnostics/ActivitySourceExtensions.cs b/src/EventStore.Client/Common/Diagnostics/ActivitySourceExtensions.cs index 26bd00b44..28d336a85 100644 --- a/src/EventStore.Client/Common/Diagnostics/ActivitySourceExtensions.cs +++ b/src/EventStore.Client/Common/Diagnostics/ActivitySourceExtensions.cs @@ -1,3 +1,5 @@ +// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract + using System.Diagnostics; using EventStore.Diagnostics; using EventStore.Diagnostics.Telemetry; @@ -32,7 +34,7 @@ public static void TraceSubscriptionEvent( EventStoreClientSettings settings, UserCredentials? userCredentials ) { - if (source.HasNoActiveListeners()) + if (source.HasNoActiveListeners() || resolvedEvent.Event is null) return; var parentContext = resolvedEvent.Event.Metadata.ExtractPropagationContext(); diff --git a/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs b/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs index 4c23bfffa..5a19c6b0d 100644 --- a/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs +++ b/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs @@ -1,3 +1,5 @@ +// ReSharper disable ConditionalAccessQualifierIsNonNullableAccordingToAPIContract + using EventStore.Client.Diagnostics; using EventStore.Diagnostics.Tracing; @@ -171,4 +173,49 @@ async Task Subscribe(IAsyncEnumerator internalEnumerator) { } } } + + [Fact] + [Trait("Category", "Special cases")] + public async Task should_not_trace_when_event_is_null() { + var category = Guid.NewGuid().ToString("N"); + var streamName = category + "-123"; + + var seedEvents = Fixture.CreateTestEvents(type: $"{category}-{Fixture.GetStreamName()}").ToArray(); + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); + + await Fixture.Streams.DeleteAsync(streamName, StreamState.StreamExists); + + await using var subscription = Fixture.Streams.SubscribeToStream("$ce-" + category, FromStream.Start, resolveLinkTos: true); + + await using var enumerator = subscription.Messages.GetAsyncEnumerator(); + + Assert.True(await enumerator.MoveNextAsync()); + + Assert.IsType(enumerator.Current); + + await Subscribe().WithTimeout(); + + var appendActivities = Fixture + .GetActivitiesForOperation(TracingConstants.Operations.Append, streamName) + .ShouldNotBeNull(); + + var subscribeActivities = Fixture + .GetActivitiesForOperation(TracingConstants.Operations.Subscribe, "$ce-" + category) + .ToArray(); + + appendActivities.ShouldHaveSingleItem(); + subscribeActivities.ShouldBeEmpty(); + + return; + + async Task Subscribe() { + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not StreamMessage.Event(var resolvedEvent)) + continue; + + if (resolvedEvent.Event?.EventType is "$metadata") + return; + } + } + } } diff --git a/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs index f8cd5913b..549093654 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs @@ -11,7 +11,7 @@ namespace EventStore.Client.Tests; public class DiagnosticsFixture : EventStoreFixture { readonly ConcurrentDictionary<(string Operation, string Stream), List> _activities = []; - public DiagnosticsFixture() { + public DiagnosticsFixture() : base(x => x.RunProjections()) { var diagnosticActivityListener = new ActivityListener { ShouldListenTo = source => source.Name == EventStoreClientDiagnostics.InstrumentationName, Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllDataAndRecorded,