diff --git a/src/Paramore.Brighter.MessagingGateway.AWSSQS/SnsMessageProducerFactory.cs b/src/Paramore.Brighter.MessagingGateway.AWSSQS/SnsMessageProducerFactory.cs new file mode 100644 index 0000000000..b6a5dbecd5 --- /dev/null +++ b/src/Paramore.Brighter.MessagingGateway.AWSSQS/SnsMessageProducerFactory.cs @@ -0,0 +1,62 @@ +#region Licence +/* The MIT License (MIT) +Copyright © 2024 Dominic Hickie + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ +#endregion + +using System.Collections.Generic; + +namespace Paramore.Brighter.MessagingGateway.AWSSQS +{ + public class SnsMessageProducerFactory : IAmAMessageProducerFactory + { + private readonly AWSMessagingGatewayConnection _connection; + private readonly IEnumerable _snsPublications; + + /// + /// Creates a collection of SNS message producers from the SNS publication information + /// + /// The Connection to use to connect to AWS + /// The publications describing the SNS topics that we want to use + public SnsMessageProducerFactory( + AWSMessagingGatewayConnection connection, + IEnumerable snsPublications) + { + _connection = connection; + _snsPublications = snsPublications; + } + + /// + public Dictionary Create() + { + var producers = new Dictionary(); + foreach (var p in _snsPublications) + { + var producer = new SqsMessageProducer(_connection, p); + if (producer.ConfirmTopicExists()) + producers[p.Topic] = producer; + else + throw new ConfigurationException($"Missing SNS topic: {p.Topic}"); + } + + return producers; + } + } +} diff --git a/src/Paramore.Brighter.MessagingGateway.AWSSQS/SnsProducerRegistryFactory.cs b/src/Paramore.Brighter.MessagingGateway.AWSSQS/SnsProducerRegistryFactory.cs index fb5c05f623..61e92126f2 100644 --- a/src/Paramore.Brighter.MessagingGateway.AWSSQS/SnsProducerRegistryFactory.cs +++ b/src/Paramore.Brighter.MessagingGateway.AWSSQS/SnsProducerRegistryFactory.cs @@ -22,8 +22,6 @@ THE SOFTWARE. */ #endregion using System.Collections.Generic; -using Amazon; -using Amazon.Runtime; namespace Paramore.Brighter.MessagingGateway.AWSSQS { @@ -51,18 +49,9 @@ public SnsProducerRegistryFactory( /// public IAmAProducerRegistry Create() { - var producers = new Dictionary(); - foreach (var p in _snsPublications) - { - var producer = new SqsMessageProducer(_connection, p); - if (producer.ConfirmTopicExists()) - producers[p.Topic] = producer; - else - throw new ConfigurationException($"Missing SNS topic: {p.Topic}"); + var producerFactory = new SnsMessageProducerFactory(_connection, _snsPublications); - } - - return new ProducerRegistry(producers); + return new ProducerRegistry(producerFactory.Create()); } } } diff --git a/src/Paramore.Brighter.MessagingGateway.AzureServiceBus/AzureServiceBusMessageProducerFactory.cs b/src/Paramore.Brighter.MessagingGateway.AzureServiceBus/AzureServiceBusMessageProducerFactory.cs index 57017c28e1..b88b9f29e1 100644 --- a/src/Paramore.Brighter.MessagingGateway.AzureServiceBus/AzureServiceBusMessageProducerFactory.cs +++ b/src/Paramore.Brighter.MessagingGateway.AzureServiceBus/AzureServiceBusMessageProducerFactory.cs @@ -1,43 +1,67 @@ -using Paramore.Brighter.MessagingGateway.AzureServiceBus.AzureServiceBusWrappers; +using System.Collections.Generic; +using Paramore.Brighter.MessagingGateway.AzureServiceBus.AzureServiceBusWrappers; using Paramore.Brighter.MessagingGateway.AzureServiceBus.ClientProvider; namespace Paramore.Brighter.MessagingGateway.AzureServiceBus { /// - /// Factory class for creating instances of + /// Factory class for creating dictionary of instances of + /// indexed by topic name /// - internal static class AzureServiceBusMessageProducerFactory + public class AzureServiceBusMessageProducerFactory : IAmAMessageProducerFactory { + private readonly IServiceBusClientProvider _clientProvider; + private readonly IEnumerable _publications; + private readonly int _bulkSendBatchSize; + /// - /// Factory to create an Azure Service Bus Producer + /// Factory to create a dictionary of Azure Service Bus Producers indexed by topic name /// - /// The configuration to connect to - /// Describes the parameters for the producer - /// A Message Producer - public static AzureServiceBusMessageProducer Get( + /// The configuration of the connection to ASB + /// A set of publications - topics on the server - to configure + public AzureServiceBusMessageProducerFactory( AzureServiceBusConfiguration configuration, - AzureServiceBusPublication asbPublication) + IEnumerable publications) { - var clientProvider = new ServiceBusConnectionStringClientProvider(configuration.ConnectionString); - return Get(clientProvider, asbPublication, configuration.BulkSendBatchSize); + _clientProvider = new ServiceBusConnectionStringClientProvider(configuration.ConnectionString); + _publications = publications; + _bulkSendBatchSize = configuration.BulkSendBatchSize; } /// - /// Factory to create an Azure Service Bus Producer + /// Factory to create a dictionary of Azure Service Bus Producers indexed by topic name /// /// The connection to ASB - /// Describes the parameters for the producer - /// When sending more than one message using the MessageProducer, the max amount to send in a single transmission. - /// - public static AzureServiceBusMessageProducer Get( + /// A set of publications - topics on the server - to configure + /// The maximum size to chunk messages when dispatching to ASB + public AzureServiceBusMessageProducerFactory( IServiceBusClientProvider clientProvider, - AzureServiceBusPublication asbPublication, - int bulkSendBatchSize = 10) + IEnumerable publications, + int bulkSendBatchSize) { - var nameSpaceManagerWrapper = new AdministrationClientWrapper(clientProvider); - var topicClientProvider = new ServiceBusSenderProvider(clientProvider); - - return new AzureServiceBusMessageProducer(nameSpaceManagerWrapper, topicClientProvider, asbPublication, bulkSendBatchSize); + _clientProvider = clientProvider; + _publications = publications; + _bulkSendBatchSize = bulkSendBatchSize; } + + /// + public Dictionary Create() + { + var nameSpaceManagerWrapper = new AdministrationClientWrapper(_clientProvider); + var topicClientProvider = new ServiceBusSenderProvider(_clientProvider); + + var producers = new Dictionary(); + foreach (var publication in _publications) + { + var producer = new AzureServiceBusMessageProducer( + nameSpaceManagerWrapper, + topicClientProvider, + publication, + _bulkSendBatchSize); + producers.Add(publication.Topic, producer); + } + + return producers; + } } } diff --git a/src/Paramore.Brighter.MessagingGateway.AzureServiceBus/AzureServiceBusProducerRegistryFactory.cs b/src/Paramore.Brighter.MessagingGateway.AzureServiceBus/AzureServiceBusProducerRegistryFactory.cs index 88219b1e25..2bb5b510c6 100644 --- a/src/Paramore.Brighter.MessagingGateway.AzureServiceBus/AzureServiceBusProducerRegistryFactory.cs +++ b/src/Paramore.Brighter.MessagingGateway.AzureServiceBus/AzureServiceBusProducerRegistryFactory.cs @@ -45,13 +45,9 @@ public AzureServiceBusProducerRegistryFactory( /// A has of middleware clients by topic, for sending messages to the middleware public IAmAProducerRegistry Create() { - var producers = new Dictionary(); - foreach (var publication in _asbPublications) - { - producers[publication.Topic] = AzureServiceBusMessageProducerFactory.Get(_clientProvider, publication, _bulkSendBatchSize); - } + var producerFactory = new AzureServiceBusMessageProducerFactory(_clientProvider, _asbPublications, _bulkSendBatchSize); - return new ProducerRegistry(producers); + return new ProducerRegistry(producerFactory.Create()); } } } diff --git a/src/Paramore.Brighter.MessagingGateway.Kafka/KafkaMessageProducerFactory.cs b/src/Paramore.Brighter.MessagingGateway.Kafka/KafkaMessageProducerFactory.cs new file mode 100644 index 0000000000..4cf7f37c47 --- /dev/null +++ b/src/Paramore.Brighter.MessagingGateway.Kafka/KafkaMessageProducerFactory.cs @@ -0,0 +1,85 @@ +#region Licence +/* The MIT License (MIT) +Copyright © 2024 Dominic Hickie + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ +#endregion + +using System; +using System.Collections.Generic; +using Confluent.Kafka; + +namespace Paramore.Brighter.MessagingGateway.Kafka +{ + /// + /// Creates a dictionary of instances indexed by topic from a collection of instances + /// Note that we only return the interface and is internal as the underlying type is not needed + /// + public class KafkaMessageProducerFactory : IAmAMessageProducerFactory + { + private readonly KafkaMessagingGatewayConfiguration _globalConfiguration; + private readonly IEnumerable _publications; + private Action _configHook; + + /// + /// This constructs a which can be used to create a dictionary of + /// instances indexed by topic name. + /// It takes a dependency on a to connect to the broker, and a collection of + /// instances that determine how we publish to Kafka and the parameters of any topics if required. + /// + /// Configures how we connect to the broker + /// The list of topics that we want to publish to + public KafkaMessageProducerFactory( + KafkaMessagingGatewayConfiguration globalConfiguration, + IEnumerable publications) + { + _globalConfiguration = globalConfiguration; + _publications = publications; + _configHook = null; + } + + /// + public Dictionary Create() + { + var publicationsByTopic = new Dictionary(); + foreach (var publication in _publications) + { + + var producer = new KafkaMessageProducer(_globalConfiguration, publication); + if (_configHook != null) + producer.ConfigHook(_configHook); + producer.Init(); + publicationsByTopic[publication.Topic] = producer; + } + + return publicationsByTopic; + } + + /// + /// Set a configuration hook to set properties not exposed by KafkaMessagingGatewayConfiguration or KafkaPublication + /// Intended as 'get out of gaol free' this couples us to the Confluent .NET Kafka client. Bear in mind that a future release + /// might drop the Confluent client, and this hook + /// + /// + public void SetConfigHook(Action hook) + { + _configHook = hook; + } + } +} diff --git a/src/Paramore.Brighter.MessagingGateway.Kafka/KafkaProducerRegistryFactory.cs b/src/Paramore.Brighter.MessagingGateway.Kafka/KafkaProducerRegistryFactory.cs index b68f01f77a..57e1cf256e 100644 --- a/src/Paramore.Brighter.MessagingGateway.Kafka/KafkaProducerRegistryFactory.cs +++ b/src/Paramore.Brighter.MessagingGateway.Kafka/KafkaProducerRegistryFactory.cs @@ -28,7 +28,7 @@ THE SOFTWARE. */ namespace Paramore.Brighter.MessagingGateway.Kafka { /// - /// Creates a from a + /// Creates a registry of instances from instances /// Note that we only return the interface and is internal as the underlying type is not needed /// public class KafkaProducerRegistryFactory : IAmAProducerRegistryFactory @@ -38,9 +38,9 @@ public class KafkaProducerRegistryFactory : IAmAProducerRegistryFactory private Action _configHook; /// - /// This constructs a which can be used to create a . - /// It takes a dependency on a to connect to the broker, and a - /// that determines how we publish to Kafka and the parameters of any topic if required. + /// This constructs a which can be used to create a of instances. + /// It takes a dependency on a to connect to the broker, and a collection of instances + /// that determine how we publish to Kafka and the parameters of any topics if required. /// /// Configures how we connect to the broker /// How do we publish, both producer parameters and topic configuration @@ -54,24 +54,16 @@ public KafkaProducerRegistryFactory( } /// - /// Create a message producer from tne and supplied + /// Create a producer registry from the and instances supplied /// to the constructor /// /// An that represents a collection of Kafka Message Producers public IAmAProducerRegistry Create() { - var publicationsByTopic = new Dictionary(); - foreach (var publication in _publications) - { + var producerFactory = new KafkaMessageProducerFactory(_globalConfiguration, _publications); + producerFactory.SetConfigHook(_configHook); - var producer = new KafkaMessageProducer(_globalConfiguration, publication); - if (_configHook != null) - producer.ConfigHook(_configHook); - producer.Init(); - publicationsByTopic[publication.Topic] = producer; - } - - return new ProducerRegistry(publicationsByTopic); + return new ProducerRegistry(producerFactory.Create()); } /// diff --git a/src/Paramore.Brighter.MessagingGateway.MsSql/MsSqlMessageProducerFactory.cs b/src/Paramore.Brighter.MessagingGateway.MsSql/MsSqlMessageProducerFactory.cs new file mode 100644 index 0000000000..dde4bf7132 --- /dev/null +++ b/src/Paramore.Brighter.MessagingGateway.MsSql/MsSqlMessageProducerFactory.cs @@ -0,0 +1,64 @@ +#region Licence +/* The MIT License (MIT) +Copyright © 2024 Dominic Hickie + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ +#endregion + +using System; +using System.Collections.Generic; +using Paramore.Brighter.MsSql; + +namespace Paramore.Brighter.MessagingGateway.MsSql +{ + public class MsSqlMessageProducerFactory : IAmAMessageProducerFactory + { + private readonly MsSqlConfiguration _msSqlConfiguration; + private readonly IEnumerable _publications; + + /// + /// Creates a collection of MsSQL message producers from the MsSQL publication information + /// + /// The connection to use to connect to MsSQL + /// The publications describing the MySQL topics that we want to use + public MsSqlMessageProducerFactory( + MsSqlConfiguration msSqlConfiguration, + IEnumerable publications) + { + _msSqlConfiguration = + msSqlConfiguration ?? throw new ArgumentNullException(nameof(msSqlConfiguration)); + if (string.IsNullOrEmpty(msSqlConfiguration.QueueStoreTable)) + throw new ArgumentNullException(nameof(msSqlConfiguration.QueueStoreTable)); + _publications = publications; + } + + /// + public Dictionary Create() + { + var producers = new Dictionary(); + + foreach (var publication in _publications) + { + producers[publication.Topic] = new MsSqlMessageProducer(_msSqlConfiguration, publication); + } + + return producers; + } + } +} diff --git a/src/Paramore.Brighter.MessagingGateway.MsSql/MsSqlProducerRegistryFactory.cs b/src/Paramore.Brighter.MessagingGateway.MsSql/MsSqlProducerRegistryFactory.cs index 9d311b5068..e1632e614b 100644 --- a/src/Paramore.Brighter.MessagingGateway.MsSql/MsSqlProducerRegistryFactory.cs +++ b/src/Paramore.Brighter.MessagingGateway.MsSql/MsSqlProducerRegistryFactory.cs @@ -27,14 +27,9 @@ public IAmAProducerRegistry Create() { s_logger.LogDebug("MsSqlMessageProducerFactory: create producer"); - var producers = new Dictionary(); + var producerFactory = new MsSqlMessageProducerFactory(_msSqlConfiguration, _publications); - foreach (var publication in _publications) - { - producers[publication.Topic] = new MsSqlMessageProducer(_msSqlConfiguration, publication); - } - - return new ProducerRegistry(producers); + return new ProducerRegistry(producerFactory.Create()); } } } diff --git a/src/Paramore.Brighter.MessagingGateway.RMQ/RmqMessageProducerFactory.cs b/src/Paramore.Brighter.MessagingGateway.RMQ/RmqMessageProducerFactory.cs new file mode 100644 index 0000000000..85b0fc0755 --- /dev/null +++ b/src/Paramore.Brighter.MessagingGateway.RMQ/RmqMessageProducerFactory.cs @@ -0,0 +1,57 @@ +#region Licence +/* The MIT License (MIT) +Copyright © 2024 Dominic Hickie + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ +#endregion + +using System.Collections.Generic; + +namespace Paramore.Brighter.MessagingGateway.RMQ +{ + public class RmqMessageProducerFactory + : IAmAMessageProducerFactory + { + private readonly RmqMessagingGatewayConnection _connection; + private readonly IEnumerable _publications; + + /// + /// Creates a collection of RabbitMQ message producers from the RabbitMQ publication information + /// + /// The connection to use to connect to RabbitMQ + /// The publications describing the RabbitMQ topics that we want to use + public RmqMessageProducerFactory(RmqMessagingGatewayConnection connection, IEnumerable publications) + { + _connection = connection; + _publications = publications; + } + + /// + public Dictionary Create() + { + var producers = new Dictionary(); + foreach (var publication in _publications) + { + producers[publication.Topic] = new RmqMessageProducer(_connection, publication); + } + + return producers; + } + } +} diff --git a/src/Paramore.Brighter.MessagingGateway.RMQ/RmqProducerRegistryFactory.cs b/src/Paramore.Brighter.MessagingGateway.RMQ/RmqProducerRegistryFactory.cs index b3a7aabc91..f11e2beb49 100644 --- a/src/Paramore.Brighter.MessagingGateway.RMQ/RmqProducerRegistryFactory.cs +++ b/src/Paramore.Brighter.MessagingGateway.RMQ/RmqProducerRegistryFactory.cs @@ -25,13 +25,9 @@ public RmqProducerRegistryFactory( /// A has of middleware clients by topic, for sending messages to the middleware public IAmAProducerRegistry Create() { - var producers = new Dictionary(); - foreach (var publication in _publications) - { - producers[publication.Topic] = new RmqMessageProducer(_connection, publication); - } + var producerFactory = new RmqMessageProducerFactory(_connection, _publications); - return new ProducerRegistry(producers); + return new ProducerRegistry(producerFactory.Create()); } } } diff --git a/src/Paramore.Brighter.MessagingGateway.Redis/RedisMessageProducerFactory.cs b/src/Paramore.Brighter.MessagingGateway.Redis/RedisMessageProducerFactory.cs new file mode 100644 index 0000000000..bec3e49baf --- /dev/null +++ b/src/Paramore.Brighter.MessagingGateway.Redis/RedisMessageProducerFactory.cs @@ -0,0 +1,59 @@ +#region Licence +/* The MIT License (MIT) +Copyright © 2024 Dominic Hickie + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ +#endregion + +using System.Collections.Generic; + +namespace Paramore.Brighter.MessagingGateway.Redis +{ + public class RedisMessageProducerFactory : IAmAMessageProducerFactory + { + private readonly RedisMessagingGatewayConfiguration _redisConfiguration; + private readonly IEnumerable _publications; + + /// + /// Creates a collection of Redis message producers from the Redis publication information + /// + /// The connection to use to connect to Redis + /// The publications describing the Redis topics that we want to use + public RedisMessageProducerFactory( + RedisMessagingGatewayConfiguration redisConfiguration, + IEnumerable publications) + { + _redisConfiguration = redisConfiguration; + _publications = publications; + } + + /// + public Dictionary Create() + { + var producers = new Dictionary(); + + foreach (var publication in _publications) + { + producers[publication.Topic] = new RedisMessageProducer(_redisConfiguration, publication); + } + + return producers; + } + } +} diff --git a/src/Paramore.Brighter.MessagingGateway.Redis/RedisProducerRegistryFactory.cs b/src/Paramore.Brighter.MessagingGateway.Redis/RedisProducerRegistryFactory.cs index ed96c42d26..a098fe4667 100644 --- a/src/Paramore.Brighter.MessagingGateway.Redis/RedisProducerRegistryFactory.cs +++ b/src/Paramore.Brighter.MessagingGateway.Redis/RedisProducerRegistryFactory.cs @@ -21,14 +21,9 @@ public RedisProducerRegistryFactory( /// A has of middleware clients by topic, for sending messages to the middleware public IAmAProducerRegistry Create() { - var producers = new Dictionary(); + var producerFactory = new RedisMessageProducerFactory(_redisConfiguration, _publications); - foreach (var publication in _publications) - { - producers[publication.Topic] = new RedisMessageProducer(_redisConfiguration, publication); - } - - return new ProducerRegistry(producers); + return new ProducerRegistry(producerFactory.Create()); } } } diff --git a/src/Paramore.Brighter/CombinedProducerRegistryFactory.cs b/src/Paramore.Brighter/CombinedProducerRegistryFactory.cs new file mode 100644 index 0000000000..7e1791a76d --- /dev/null +++ b/src/Paramore.Brighter/CombinedProducerRegistryFactory.cs @@ -0,0 +1,55 @@ +#region Licence +/* The MIT License (MIT) +Copyright © 2024 Dominic Hickie + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ +#endregion + +using System.Linq; + +namespace Paramore.Brighter +{ + public class CombinedProducerRegistryFactory : IAmAProducerRegistryFactory + { + private readonly IAmAMessageProducerFactory[] _messageProducerFactories; + + /// + /// Creates a combined producer registry of the message producers created by a set of message + /// producer factories. + /// + /// The set of message producer factories from which to create the combined registry + public CombinedProducerRegistryFactory(params IAmAMessageProducerFactory[] messageProducerFactories) + { + _messageProducerFactories = messageProducerFactories; + } + + /// + /// Create a combined producer registry of the producers created by the message producer factories, + /// under the key of each topic + /// + /// + public IAmAProducerRegistry Create() + { + var producers = _messageProducerFactories + .SelectMany(x => x.Create()) + .ToDictionary(x => x.Key, x => x.Value); + return new ProducerRegistry(producers); + } + } +} diff --git a/src/Paramore.Brighter/IAmAMessageProducerFactory.cs b/src/Paramore.Brighter/IAmAMessageProducerFactory.cs new file mode 100644 index 0000000000..e5692194a1 --- /dev/null +++ b/src/Paramore.Brighter/IAmAMessageProducerFactory.cs @@ -0,0 +1,40 @@ +#region Licence +/* The MIT License (MIT) +Copyright © 2024 Dominic Hickie + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ + +#endregion + +using System.Collections.Generic; + +namespace Paramore.Brighter +{ + /// + /// Interface IAmAMessageProducerFactory + /// + public interface IAmAMessageProducerFactory + { + /// + /// Creates message producers. + /// + /// A dictionary of middleware clients by topic, for sending messages to the middleware + Dictionary Create(); + } +} diff --git a/src/Paramore.Brighter/IAmAProducerRegistryFactory.cs b/src/Paramore.Brighter/IAmAProducerRegistryFactory.cs index a304074fb4..7df7c8b017 100644 --- a/src/Paramore.Brighter/IAmAProducerRegistryFactory.cs +++ b/src/Paramore.Brighter/IAmAProducerRegistryFactory.cs @@ -22,20 +22,17 @@ THE SOFTWARE. */ #endregion -using System.Collections.Generic; - namespace Paramore.Brighter { /// - /// Interface IAmAMessageProducerFactory + /// Interface IAmAProducerRegistryFactory /// public interface IAmAProducerRegistryFactory { /// - /// Creates message producers. + /// Creates a message producer registry. /// - /// A has of middleware clients by topic, for sending messages to the middleware + /// A registry of middleware clients by topic, for sending messages to the middleware IAmAProducerRegistry Create(); - } } diff --git a/tests/Paramore.Brighter.Core.Tests/MessagingGateway/When_Constructing_A_Combined_Producer_Registry.cs b/tests/Paramore.Brighter.Core.Tests/MessagingGateway/When_Constructing_A_Combined_Producer_Registry.cs new file mode 100644 index 0000000000..3b50869c0c --- /dev/null +++ b/tests/Paramore.Brighter.Core.Tests/MessagingGateway/When_Constructing_A_Combined_Producer_Registry.cs @@ -0,0 +1,40 @@ +using System.Linq; +using FluentAssertions; +using Paramore.Brighter.Core.Tests.TestHelpers; +using Xunit; + +namespace Paramore.Brighter.Core.Tests.MessagingGateway; + +public class CombinedProducerRegistryTests +{ + [Fact] + public void When_constructing_a_combined_producer_registry() + { + var firstProducers = new[] + { + new Publication + { + Topic = new RoutingKey("FirstTopic") + } + }; + var secondProducers = new[] + { + new Publication + { + Topic = new RoutingKey("SecondTopic") + } + }; + + var firstProducerFactory = new DummyMessageProducerFactory(firstProducers); + var secondProducerFactory = new DummyMessageProducerFactory(secondProducers); + + var combinedRegistryFactory = new CombinedProducerRegistryFactory(firstProducerFactory, secondProducerFactory); + var producerRegistry = combinedRegistryFactory.Create(); + + // Producer registry should contain producers for both topics + var producers = producerRegistry.Producers.ToList(); + producers.Count.Should().Be(2); + producers.Count(x => ((DummyMessageProducer)x).Topic == "FirstTopic").Should().Be(1); + producers.Count(x => ((DummyMessageProducer)x).Topic == "SecondTopic").Should().Be(1); + } +} diff --git a/tests/Paramore.Brighter.Core.Tests/TestHelpers/DummyMessageProducer.cs b/tests/Paramore.Brighter.Core.Tests/TestHelpers/DummyMessageProducer.cs new file mode 100644 index 0000000000..79311a2d4e --- /dev/null +++ b/tests/Paramore.Brighter.Core.Tests/TestHelpers/DummyMessageProducer.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace Paramore.Brighter.Core.Tests.TestHelpers +{ + public class DummyMessageProducer : IAmAMessageProducer + { + public string Topic { get; } + public int MaxOutStandingMessages { get; set; } + public int MaxOutStandingCheckIntervalMilliSeconds { get; set; } + public Dictionary OutBoxBag { get; set; } + + public DummyMessageProducer(string topic) + { + Topic = topic; + } + + public void Dispose() + { + + } + } +} diff --git a/tests/Paramore.Brighter.Core.Tests/TestHelpers/DummyMessageProducerFactory.cs b/tests/Paramore.Brighter.Core.Tests/TestHelpers/DummyMessageProducerFactory.cs new file mode 100644 index 0000000000..72c1a2a77f --- /dev/null +++ b/tests/Paramore.Brighter.Core.Tests/TestHelpers/DummyMessageProducerFactory.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +namespace Paramore.Brighter.Core.Tests.TestHelpers +{ + public class DummyMessageProducerFactory : IAmAMessageProducerFactory + { + private readonly IEnumerable _publications; + + public DummyMessageProducerFactory(IEnumerable publications) + { + _publications = publications; + } + + public Dictionary Create() + { + var producers = new Dictionary(); + + foreach (var publication in _publications) + { + producers.Add(publication.Topic, new DummyMessageProducer(publication.Topic)); + } + + return producers; + } + } +}