Skip to content

Commit 8f4a47a

Browse files
committed
Hacked in a "fix" so you can use sticky connection when still using the verbose event tracing connection lifetime. Closes GH-3911
1 parent 706868e commit 8f4a47a

File tree

2 files changed

+70
-14
lines changed

2 files changed

+70
-14
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Threading;
2+
using Marten.Testing.Harness;
3+
using System.Threading.Tasks;
4+
using Marten.Services;
5+
using Xunit;
6+
7+
namespace CoreTests.Bugs;
8+
9+
public class Bug_3911_use_sticky_connections_when_otel_connection_tracking_is_on : BugIntegrationContext
10+
{
11+
[Fact]
12+
public async Task do_not_blow_up()
13+
{
14+
StoreOptions(opts => opts.OpenTelemetry.TrackConnections = TrackLevel.Verbose);
15+
16+
using var conn = theSession.Connection;
17+
}
18+
19+
[Fact]
20+
public async Task do_not_blow_up_starting_an_async_transaction()
21+
{
22+
StoreOptions(opts => opts.OpenTelemetry.TrackConnections = TrackLevel.Verbose);
23+
24+
await theSession.BeginTransactionAsync(CancellationToken.None);
25+
26+
}
27+
}

src/Marten/Internal/Sessions/EventTracingConnectionLifetime.cs

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Linq;
77
using System.Threading;
88
using System.Threading.Tasks;
9+
using ImTools;
910
using JasperFx;
1011
using JasperFx.Descriptors;
1112
using Marten.Events.Operations;
@@ -17,14 +18,14 @@
1718
namespace Marten.Internal.Sessions;
1819

1920
internal class EventTracingConnectionLifetime:
20-
IConnectionLifetime
21+
IConnectionLifetime, ITransactionStarter
2122
{
2223
private const string MartenCommandExecutionStarted = "marten.command.execution.started";
2324
private const string MartenBatchExecutionStarted = "marten.batch.execution.started";
2425
private const string MartenBatchPagesExecutionStarted = "marten.batch.pages.execution.started";
25-
private readonly IConnectionLifetime _innerConnectionLifetime;
2626
private readonly OpenTelemetryOptions _telemetryOptions;
2727
private readonly Activity? _databaseActivity;
28+
private readonly string _tenantId;
2829

2930
public EventTracingConnectionLifetime(IConnectionLifetime innerConnectionLifetime, string tenantId,
3031
OpenTelemetryOptions telemetryOptions)
@@ -38,24 +39,36 @@ public EventTracingConnectionLifetime(IConnectionLifetime innerConnectionLifetim
3839

3940
Logger = innerConnectionLifetime.Logger;
4041
CommandTimeout = innerConnectionLifetime.CommandTimeout;
41-
_innerConnectionLifetime = innerConnectionLifetime;
42+
InnerConnectionLifetime = innerConnectionLifetime;
4243
_telemetryOptions = telemetryOptions;
4344

4445
var currentActivity = Activity.Current ?? null;
45-
var tags = new ActivityTagsCollection(new[] { new KeyValuePair<string, object?>(OtelConstants.TenantId, tenantId) });
46+
var tags = new ActivityTagsCollection([new KeyValuePair<string, object?>(OtelConstants.TenantId, tenantId)]);
4647
_databaseActivity = MartenTracing.StartConnectionActivity(currentActivity, tags);
48+
49+
_tenantId = tenantId;
4750
}
4851

52+
public EventTracingConnectionLifetime(OpenTelemetryOptions telemetryOptions, Activity? databaseActivity, IConnectionLifetime innerConnectionLifetime, IMartenSessionLogger logger)
53+
{
54+
_telemetryOptions = telemetryOptions;
55+
_databaseActivity = databaseActivity;
56+
InnerConnectionLifetime = innerConnectionLifetime;
57+
Logger = logger;
58+
}
59+
60+
public IConnectionLifetime InnerConnectionLifetime { get; }
61+
4962
public ValueTask DisposeAsync()
5063
{
5164
_databaseActivity?.Stop();
52-
return _innerConnectionLifetime.DisposeAsync();
65+
return InnerConnectionLifetime.DisposeAsync();
5366
}
5467

5568
public void Dispose()
5669
{
5770
_databaseActivity?.Stop();
58-
_innerConnectionLifetime.Dispose();
71+
InnerConnectionLifetime.Dispose();
5972
}
6073

6174
public IMartenSessionLogger Logger { get; set; }
@@ -66,7 +79,7 @@ public int Execute(NpgsqlCommand cmd)
6679

6780
try
6881
{
69-
return _innerConnectionLifetime.Execute(cmd);
82+
return InnerConnectionLifetime.Execute(cmd);
7083
}
7184
catch (Exception e)
7285
{
@@ -82,7 +95,7 @@ public int Execute(NpgsqlCommand cmd)
8295

8396
try
8497
{
85-
return await _innerConnectionLifetime.ExecuteAsync(command, token).ConfigureAwait(false);
98+
return await InnerConnectionLifetime.ExecuteAsync(command, token).ConfigureAwait(false);
8699
}
87100
catch (Exception e)
88101
{
@@ -98,7 +111,7 @@ public DbDataReader ExecuteReader(NpgsqlCommand command)
98111

99112
try
100113
{
101-
return _innerConnectionLifetime.ExecuteReader(command);
114+
return InnerConnectionLifetime.ExecuteReader(command);
102115
}
103116
catch (Exception e)
104117
{
@@ -114,7 +127,7 @@ public async Task<DbDataReader> ExecuteReaderAsync(NpgsqlCommand command, Cancel
114127

115128
try
116129
{
117-
return await _innerConnectionLifetime.ExecuteReaderAsync(command, token).ConfigureAwait(false);
130+
return await InnerConnectionLifetime.ExecuteReaderAsync(command, token).ConfigureAwait(false);
118131
}
119132
catch (Exception e)
120133
{
@@ -130,7 +143,7 @@ public DbDataReader ExecuteReader(NpgsqlBatch batch)
130143

131144
try
132145
{
133-
return _innerConnectionLifetime.ExecuteReader(batch);
146+
return InnerConnectionLifetime.ExecuteReader(batch);
134147
}
135148
catch (Exception e)
136149
{
@@ -146,7 +159,7 @@ public async Task<DbDataReader> ExecuteReaderAsync(NpgsqlBatch batch, Cancellati
146159

147160
try
148161
{
149-
return await _innerConnectionLifetime.ExecuteReaderAsync(batch, token).ConfigureAwait(false);
162+
return await InnerConnectionLifetime.ExecuteReaderAsync(batch, token).ConfigureAwait(false);
150163
}
151164
catch (Exception e)
152165
{
@@ -162,7 +175,7 @@ public void ExecuteBatchPages(IReadOnlyList<OperationPage> pages, List<Exception
162175

163176
try
164177
{
165-
_innerConnectionLifetime.ExecuteBatchPages(pages, exceptions);
178+
InnerConnectionLifetime.ExecuteBatchPages(pages, exceptions);
166179
writeVerboseEvents(pages);
167180
}
168181
catch (AggregateException e)
@@ -185,7 +198,7 @@ public async Task ExecuteBatchPagesAsync(IReadOnlyList<OperationPage> pages, Lis
185198

186199
try
187200
{
188-
await _innerConnectionLifetime.ExecuteBatchPagesAsync(pages, exceptions, token).ConfigureAwait(false);
201+
await InnerConnectionLifetime.ExecuteBatchPagesAsync(pages, exceptions, token).ConfigureAwait(false);
189202

190203
writeVerboseEvents(pages);
191204
}
@@ -223,4 +236,20 @@ private void writeVerboseEvents(IReadOnlyList<OperationPage> pages)
223236
}
224237
}
225238
}
239+
240+
public IAlwaysConnectedLifetime Start()
241+
{
242+
if (InnerConnectionLifetime is ITransactionStarter starter) return starter.Start();
243+
244+
throw new InvalidOperationException(
245+
$"The inner connection lifetime {InnerConnectionLifetime} does not implement {nameof(ITransactionStarter)}");
246+
}
247+
248+
public Task<IAlwaysConnectedLifetime> StartAsync(CancellationToken token)
249+
{
250+
if (InnerConnectionLifetime is ITransactionStarter starter) return starter.StartAsync(token);
251+
252+
throw new InvalidOperationException(
253+
$"The inner connection lifetime {InnerConnectionLifetime} does not implement {nameof(ITransactionStarter)}");
254+
}
226255
}

0 commit comments

Comments
 (0)