Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ public async ValueTask InitializeAsync()
_runtime = _host.Services.GetRequiredService<IWolverineRuntime>();
}

ValueTask IAsyncDisposable.DisposeAsync() => ValueTask.CompletedTask;
// GH-3965: IHost.Dispose() does not run StopAsync, so a synchronous teardown left this
// class's Rabbit consumers attached to a SHARED, fixed queue name and stealing later
// tests' messages. Stop the hosts for real.
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (_host != null) await _host.StopAsync();
}

[Fact]
public void handler_queue_is_bound_to_every_handled_message_exchange()
Expand Down Expand Up @@ -127,7 +133,13 @@ public async ValueTask InitializeAsync()
_runtime = _host.Services.GetRequiredService<IWolverineRuntime>();
}

ValueTask IAsyncDisposable.DisposeAsync() => ValueTask.CompletedTask;
// GH-3965: IHost.Dispose() does not run StopAsync, so a synchronous teardown left this
// class's Rabbit consumers attached to a SHARED, fixed queue name and stealing later
// tests' messages. Stop the hosts for real.
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (_host != null) await _host.StopAsync();
}

[Fact]
public void user_custom_binding_is_not_double_added_by_the_convention()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ public async ValueTask InitializeAsync()
_runtime = _host.Services.GetRequiredService<IWolverineRuntime>();
}

ValueTask IAsyncDisposable.DisposeAsync() => ValueTask.CompletedTask;
// GH-3965: IHost.Dispose() does not run StopAsync, so a synchronous teardown left this
// class's Rabbit consumers attached to a SHARED, fixed queue name and stealing later
// tests' messages. Stop the hosts for real.
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (_host != null) await _host.StopAsync();
}

[Fact]
public void both_the_saga_and_the_regular_handler_get_listener_queues()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,16 @@ public static class ConventionalRoutingTestDefaults
}


public abstract class ConventionalRoutingContext : IDisposable
/// <summary>
/// GH-3965. Note the async disposal. Every conventionally routed <see cref="ConventionallyRoutedMessage" />
/// lands on one FIXED queue -- the type carries <c>[MessageIdentity("routed")]</c>, so the queue is
/// literally <c>routed</c> -- and several classes in this namespace stand up listeners on it.
/// <see cref="IHost.Dispose" /> does NOT run <c>IHostedService.StopAsync</c>, so disposing synchronously
/// left those consumers attached to the broker after the test finished, and a later test's message was
/// delivered to a leaked consumer belonging to an already-completed class. That shows up as a tracked
/// session containing <c>Sent</c> and no <c>Received</c> at all.
/// </summary>
public abstract class ConventionalRoutingContext : IDisposable, IAsyncDisposable
{
private IHost _host = null!;

Expand Down Expand Up @@ -55,6 +64,22 @@ public void Dispose()
_host?.Dispose();
}

public ValueTask DisposeAsync() => DisposeHostAsync();

/// <summary>
/// Stops the host so its Rabbit consumers are actually cancelled, then disposes it. Derived classes
/// that implement <c>IAsyncLifetime</c> shadow the interface implementation above, so they must call
/// this from their own <c>DisposeAsync</c> rather than returning a completed ValueTask.
/// </summary>
protected async ValueTask DisposeHostAsync()
{
if (_host == null) return;

await _host.StopAsync();
_host.Dispose();
_host = null!;
}

internal async Task ConfigureConventions(Action<RabbitMqMessageRoutingConvention> configure)
{
_host = await WolverineHost.ForAsync(opts =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@ public async ValueTask InitializeAsync()
});
}

ValueTask IAsyncDisposable.DisposeAsync() => ValueTask.CompletedTask;
// GH-3965: IHost.Dispose() does not run StopAsync, so a synchronous teardown left this
// class's Rabbit consumers attached to a SHARED, fixed queue name and stealing later
// tests' messages. Stop the hosts for real.
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (_sender != null) await _sender.StopAsync();
if (_receiver != null) await _receiver.StopAsync();
}

public void Dispose()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,14 @@ public async ValueTask InitializeAsync()

}

ValueTask IAsyncDisposable.DisposeAsync() => ValueTask.CompletedTask;
// GH-3965: IHost.Dispose() does not run StopAsync, so a synchronous teardown left this
// class's Rabbit consumers attached to a SHARED, fixed queue name and stealing later
// tests' messages. Stop the hosts for real.
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (_sender != null) await _sender.StopAsync();
if (_receiver != null) await _receiver.StopAsync();
}

public void Dispose()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@ public async ValueTask InitializeAsync()
});
}

ValueTask IAsyncDisposable.DisposeAsync() => ValueTask.CompletedTask;
// GH-3965: IHost.Dispose() does not run StopAsync, so a synchronous teardown left this
// class's Rabbit consumers attached to a SHARED, fixed queue name and stealing later
// tests' messages. Stop the hosts for real.
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (_sender != null) await _sender.StopAsync();
if (_receiver != null) await _receiver.StopAsync();
}

public void Dispose()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ public async ValueTask InitializeAsync()
theEndpoint = (await theRuntime()).Endpoints.EndpointFor(theExpectedUri).ShouldBeOfType<RabbitMqQueue>();
}

ValueTask IAsyncDisposable.DisposeAsync() => ValueTask.CompletedTask;
// GH-3965: shadows ConventionalRoutingContext.DisposeAsync -- must stop the host itself.
ValueTask IAsyncDisposable.DisposeAsync() => DisposeHostAsync();

[Fact]
public void endpoint_should_be_a_listener()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ await ConfigureConventions(c =>
theEndpoint = (await theRuntime()).Endpoints.EndpointFor(theExpectedUri).ShouldBeOfType<RabbitMqQueue>();
}

ValueTask IAsyncDisposable.DisposeAsync() => ValueTask.CompletedTask;
// GH-3965: shadows ConventionalRoutingContext.DisposeAsync -- must stop the host itself.
ValueTask IAsyncDisposable.DisposeAsync() => DisposeHostAsync();

[Fact]
public void endpoint_should_be_a_listener()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public async ValueTask InitializeAsync()
theRoute = ((await PublishingRoutesFor<ConventionallyRoutedMessage>()).Single() as MessageRoute)!;
}

ValueTask IAsyncDisposable.DisposeAsync() => ValueTask.CompletedTask;
// GH-3965: shadows ConventionalRoutingContext.DisposeAsync -- must stop the host itself.
ValueTask IAsyncDisposable.DisposeAsync() => DisposeHostAsync();

[Fact]
public void should_have_exactly_one_route()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ public async ValueTask InitializeAsync()
_runtime = _host.Services.GetRequiredService<IWolverineRuntime>();
}

ValueTask IAsyncDisposable.DisposeAsync() => ValueTask.CompletedTask;
// GH-3965: IHost.Dispose() does not run StopAsync, so a synchronous teardown left this
// class's Rabbit consumers attached to a SHARED, fixed queue name and stealing later
// tests' messages. Stop the hosts for real.
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (_host != null) await _host.StopAsync();
}

[Fact]
public void listener_endpoint_should_be_named_after_handler_type()
Expand Down
Loading