Skip to content

Commit 3769afa

Browse files
IEnvironment XML doc (#105)
* `IEnvironment` XML doc * Minor refactor to remove ability to get all connections from `IEnvironment`, since that's just used for tests. * * XML doc for `AmqpEnvironment` --------- Co-authored-by: Gabriele Santomaggio <[email protected]>
1 parent 9bf380d commit 3769afa

File tree

5 files changed

+78
-37
lines changed

5 files changed

+78
-37
lines changed

RabbitMQ.AMQP.Client/IEnvironment.cs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,42 @@
22
// and the Mozilla Public License, version 2.0.
33
// Copyright (c) 2017-2024 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
44

5-
using System.Collections.ObjectModel;
65
using System.Threading.Tasks;
76

87
namespace RabbitMQ.AMQP.Client
98
{
109
/// <summary>
11-
/// Interface to create IConnections and manage them.
10+
/// <para>
11+
/// The <see cref="IEnvironment"/> is the main entry point to a node or a cluster of nodes.
12+
/// </para>
13+
/// <para>
14+
/// The <see cref="CreateConnectionAsync()"/> method allows creating <see cref="IConnection"/> instances.
15+
/// An application is expected to maintain a single <see cref="IEnvironment"/> instance and to close that instance
16+
/// upon application exit.
17+
/// </para>
18+
/// <para>
19+
/// <see cref="IEnvironment"/> instances are expected to be thread-safe.
20+
/// </para>
1221
/// </summary>
1322
public interface IEnvironment
1423
{
1524
/// <summary>
16-
/// Create a new connection with the given connection settings.
25+
/// Create a new <see cref="IConnection"/> with the given connection settings.
1726
/// </summary>
1827
/// <param name="connectionSettings"></param>
19-
/// <returns>IConnection</returns>
28+
/// <returns><see cref="Task{IConnection}"/> instance.</returns>
2029
public Task<IConnection> CreateConnectionAsync(ConnectionSettings connectionSettings);
2130

2231
/// <summary>
23-
/// Create a new connection with the default connection settings.
32+
/// Create a new <see cref="IConnection"/> with the default connection settings.
2433
/// </summary>
25-
/// <returns>IConnection</returns>
34+
/// <returns><see cref="Task{IConnection}"/> instance.</returns>
2635
public Task<IConnection> CreateConnectionAsync();
2736

2837
/// <summary>
29-
/// Get all connections.
38+
/// Close this environment and its resources.
3039
/// </summary>
31-
public ReadOnlyCollection<IConnection> GetConnections();
32-
33-
/// <summary>
34-
/// Close all connections.
35-
/// </summary>
36-
/// <returns></returns>
40+
/// <returns><see cref="Task"/></returns>
3741
// TODO cancellation token
3842
Task CloseAsync();
3943
}

RabbitMQ.AMQP.Client/Impl/AmqpEnvironment.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,21 @@
33
// Copyright (c) 2017-2024 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
44

55
using System.Collections.Concurrent;
6-
using System.Collections.ObjectModel;
6+
using System.Collections.Generic;
77
using System.Linq;
88
using System.Threading;
99
using System.Threading.Tasks;
1010

1111
namespace RabbitMQ.AMQP.Client.Impl
1212
{
13+
/// <summary>
14+
/// <para>
15+
/// <see cref="AmqpEnvironment"/> is the implementation of <see cref="IEnvironment"/>.
16+
/// </para>
17+
/// <para>
18+
/// The <see cref="CreateConnectionAsync()"/> method allows creating <see cref="IConnection"/> instances.
19+
/// </para>
20+
/// </summary>
1321
public class AmqpEnvironment : IEnvironment
1422
{
1523
private ConnectionSettings ConnectionSettings { get; }
@@ -23,12 +31,24 @@ private AmqpEnvironment(ConnectionSettings connectionSettings, IMetricsReporter?
2331
_metricsReporter = metricsReporter;
2432
}
2533

26-
// TODO to play nicely with IoC containers, we should not have static Create methods
34+
/// <summary>
35+
/// Create a new <see cref="IEnvironment"/> instance, using the provided <see cref="ConnectionSettings"/>
36+
/// and optional <see cref="IMetricsReporter"/>
37+
/// </summary>
38+
/// <param name="connectionSettings"></param>
39+
/// <param name="metricsReporter"></param>
40+
/// <returns><see cref="IEnvironment"/> instance.</returns>
2741
public static IEnvironment Create(ConnectionSettings connectionSettings, IMetricsReporter? metricsReporter = default)
2842
{
43+
// TODO to play nicely with IoC containers, we should not have static Create methods
2944
return new AmqpEnvironment(connectionSettings, metricsReporter);
3045
}
3146

47+
/// <summary>
48+
/// Create a new <see cref="IConnection"/> instance, using the provided <see cref="ConnectionSettings"/>.
49+
/// </summary>
50+
/// <param name="connectionSettings"></param>
51+
/// <returns><see cref="Task{IConnection}"/> instance.</returns>
3252
public async Task<IConnection> CreateConnectionAsync(ConnectionSettings connectionSettings)
3353
{
3454
IConnection c = await AmqpConnection.CreateAsync(connectionSettings, _metricsReporter).ConfigureAwait(false);
@@ -49,6 +69,10 @@ public async Task<IConnection> CreateConnectionAsync(ConnectionSettings connecti
4969
return c;
5070
}
5171

72+
/// <summary>
73+
/// Create a new <see cref="IConnection"/> instance, using the <see cref="IEnvironment"/> <see cref="ConnectionSettings"/>.
74+
/// </summary>
75+
/// <returns><see cref="Task{IConnection}"/> instance.</returns>
5276
public Task<IConnection> CreateConnectionAsync()
5377
{
5478
if (ConnectionSettings is null)
@@ -59,13 +83,16 @@ public Task<IConnection> CreateConnectionAsync()
5983
return CreateConnectionAsync(ConnectionSettings);
6084
}
6185

62-
public ReadOnlyCollection<IConnection> GetConnections() =>
63-
new(_connections.Values.ToList());
64-
86+
/// <summary>
87+
/// Close this environment and its resources.
88+
/// </summary>
89+
/// <returns><see cref="Task"/></returns>
6590
// TODO cancellation token
6691
public Task CloseAsync()
6792
{
6893
return Task.WhenAll(_connections.Values.Select(c => c.CloseAsync()));
6994
}
95+
96+
internal IList<IConnection> Connections => _connections.Values.ToList();
7097
}
7198
}

RabbitMQ.AMQP.Client/PublicAPI.Unshipped.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,6 @@ RabbitMQ.AMQP.Client.IEnvironment
217217
RabbitMQ.AMQP.Client.IEnvironment.CloseAsync() -> System.Threading.Tasks.Task!
218218
RabbitMQ.AMQP.Client.IEnvironment.CreateConnectionAsync() -> System.Threading.Tasks.Task<RabbitMQ.AMQP.Client.IConnection!>!
219219
RabbitMQ.AMQP.Client.IEnvironment.CreateConnectionAsync(RabbitMQ.AMQP.Client.ConnectionSettings! connectionSettings) -> System.Threading.Tasks.Task<RabbitMQ.AMQP.Client.IConnection!>!
220-
RabbitMQ.AMQP.Client.IEnvironment.GetConnections() -> System.Collections.ObjectModel.ReadOnlyCollection<RabbitMQ.AMQP.Client.IConnection!>!
221220
RabbitMQ.AMQP.Client.IExchangeSpecification
222221
RabbitMQ.AMQP.Client.IExchangeSpecification.Argument(string! key, object! value) -> RabbitMQ.AMQP.Client.IExchangeSpecification!
223222
RabbitMQ.AMQP.Client.IExchangeSpecification.Arguments(System.Collections.Generic.Dictionary<string!, object!>! arguments) -> RabbitMQ.AMQP.Client.IExchangeSpecification!
@@ -365,7 +364,6 @@ RabbitMQ.AMQP.Client.Impl.AmqpEnvironment
365364
RabbitMQ.AMQP.Client.Impl.AmqpEnvironment.CloseAsync() -> System.Threading.Tasks.Task!
366365
RabbitMQ.AMQP.Client.Impl.AmqpEnvironment.CreateConnectionAsync() -> System.Threading.Tasks.Task<RabbitMQ.AMQP.Client.IConnection!>!
367366
RabbitMQ.AMQP.Client.Impl.AmqpEnvironment.CreateConnectionAsync(RabbitMQ.AMQP.Client.ConnectionSettings! connectionSettings) -> System.Threading.Tasks.Task<RabbitMQ.AMQP.Client.IConnection!>!
368-
RabbitMQ.AMQP.Client.Impl.AmqpEnvironment.GetConnections() -> System.Collections.ObjectModel.ReadOnlyCollection<RabbitMQ.AMQP.Client.IConnection!>!
369367
RabbitMQ.AMQP.Client.Impl.AmqpExchangeSpecification
370368
RabbitMQ.AMQP.Client.Impl.AmqpExchangeSpecification.AmqpExchangeSpecification(RabbitMQ.AMQP.Client.Impl.AmqpManagement! management) -> void
371369
RabbitMQ.AMQP.Client.Impl.AmqpExchangeSpecification.Argument(string! key, object! value) -> RabbitMQ.AMQP.Client.IExchangeSpecification!

Tests/ClusterTests.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,17 @@ public async Task CreateConnectionWithEnvironmentAndMultipleUris()
3333
ConnectionSettings connectionSettings = connectionSettingBuilder.Build();
3434

3535
IEnvironment env = AmqpEnvironment.Create(connectionSettings);
36+
var amqpEnv = (AmqpEnvironment)env;
3637

3738
// Note: by using _connection, the test will dispose the object on teardown
3839
_connection = await env.CreateConnectionAsync();
3940
Assert.NotNull(_connection);
40-
Assert.NotEmpty(env.GetConnections());
41+
42+
Assert.NotEmpty(amqpEnv.Connections);
4143

4244
await env.CloseAsync();
4345

4446
Assert.Equal(State.Closed, _connection.State);
45-
Assert.Empty(env.GetConnections());
47+
Assert.Empty(amqpEnv.Connections);
4648
}
4749
}

Tests/EnvironmentTests.cs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,82 +18,92 @@ public class EnvironmentTests(ITestOutputHelper testOutputHelper)
1818
public async Task CreateAConnectionWithEnvironment()
1919
{
2020
IEnvironment env = AmqpEnvironment.Create(ConnectionSettingsBuilder.Create().Build());
21+
var amqpEnv = (AmqpEnvironment)env;
22+
2123
IConnection connection = await env.CreateConnectionAsync();
24+
2225
Assert.NotNull(connection);
23-
Assert.NotEmpty(env.GetConnections());
26+
Assert.NotEmpty(amqpEnv.Connections);
2427
await env.CloseAsync();
2528
Assert.Equal(State.Closed, connection.State);
26-
Assert.Empty(env.GetConnections());
29+
Assert.Empty(amqpEnv.Connections);
2730
}
2831

2932
[Fact]
3033
public async Task CreateMoreConnectionsWithDifferentParametersEnvironment()
3134
{
3235
string envConnectionName = "EnvironmentConnection_" + Guid.NewGuid();
36+
3337
IEnvironment env = AmqpEnvironment.Create(
3438
ConnectionSettingsBuilder.Create().ContainerId(envConnectionName).Build());
39+
var amqpEnv = (AmqpEnvironment)env;
3540

3641
IConnection connection = await env.CreateConnectionAsync();
42+
3743
Assert.NotNull(connection);
3844
await WaitUntilConnectionIsOpen(envConnectionName);
39-
Assert.NotEmpty(env.GetConnections());
40-
Assert.Single(env.GetConnections());
45+
Assert.NotEmpty(amqpEnv.Connections);
46+
Assert.Single(amqpEnv.Connections);
4147

4248
string envConnectionName2 = "EnvironmentConnection2_" + Guid.NewGuid();
4349

4450
IConnection connection2 = await env.CreateConnectionAsync(
4551
ConnectionSettingsBuilder.Create().ContainerId(envConnectionName2).Build());
4652
Assert.NotNull(connection2);
47-
Assert.Equal(2, env.GetConnections().Count);
53+
Assert.Equal(2, amqpEnv.Connections.Count);
4854
await WaitUntilConnectionIsOpen(envConnectionName2);
4955

5056
await env.CloseAsync();
5157
Assert.Equal(State.Closed, connection.State);
5258
Assert.Equal(State.Closed, connection2.State);
53-
Assert.Empty(env.GetConnections());
59+
Assert.Empty(amqpEnv.Connections);
5460
}
5561

5662
[Fact]
5763
public async Task CloseConnectionsIndividually()
5864
{
5965
string envConnectionName = "EnvironmentConnection_" + Guid.NewGuid();
66+
6067
IEnvironment env = AmqpEnvironment.Create(
6168
ConnectionSettingsBuilder.Create().ContainerId(envConnectionName).Build());
69+
var amqpEnv = (AmqpEnvironment)env;
70+
6271
IConnection connection = await env.CreateConnectionAsync();
72+
6373
await WaitUntilConnectionIsOpen(envConnectionName);
64-
Assert.Single(env.GetConnections());
65-
Assert.Equal(1, env.GetConnections()[0].Id);
74+
Assert.Single(amqpEnv.Connections);
75+
Assert.Equal(1, amqpEnv.Connections[0].Id);
6676

6777
string envConnectionName2 = "EnvironmentConnection2_" + Guid.NewGuid().ToString();
6878
IConnection connection2 = await env.CreateConnectionAsync(
6979
ConnectionSettingsBuilder.Create().ContainerId(envConnectionName2).Build());
70-
Assert.Equal(2, env.GetConnections().Count);
71-
Assert.Equal(2, env.GetConnections()[1].Id);
80+
Assert.Equal(2, amqpEnv.Connections.Count);
81+
Assert.Equal(2, amqpEnv.Connections[1].Id);
7282
await WaitUntilConnectionIsOpen(envConnectionName2);
7383

7484
string envConnectionName3 = "EnvironmentConnection3_" + Guid.NewGuid().ToString();
7585
IConnection connection3 = await env.CreateConnectionAsync(
7686
ConnectionSettingsBuilder.Create().ContainerId(envConnectionName3).Build());
77-
Assert.Equal(3, env.GetConnections().Count);
78-
Assert.Equal(3, env.GetConnections()[2].Id);
87+
Assert.Equal(3, amqpEnv.Connections.Count);
88+
Assert.Equal(3, amqpEnv.Connections[2].Id);
7989
await WaitUntilConnectionIsOpen(envConnectionName3);
8090

8191
// closing
8292
await connection.CloseAsync();
8393
Assert.Equal(State.Closed, connection.State);
84-
Assert.Equal(2, env.GetConnections().Count);
94+
Assert.Equal(2, amqpEnv.Connections.Count);
8595

8696
await WaitUntilConnectionIsClosed(envConnectionName);
8797
await connection2.CloseAsync();
8898
Assert.Equal(State.Closed, connection2.State);
89-
Assert.Single(env.GetConnections());
99+
Assert.Single(amqpEnv.Connections);
90100
await WaitUntilConnectionIsClosed(envConnectionName2);
91101

92102
await connection3.CloseAsync();
93103
Assert.Equal(State.Closed, connection3.State);
94104
await WaitUntilConnectionIsClosed(envConnectionName3);
95105

96-
Assert.Empty(env.GetConnections());
106+
Assert.Empty(amqpEnv.Connections);
97107
await env.CloseAsync();
98108
}
99109
}

0 commit comments

Comments
 (0)