public void CommandReturnsProperException(string message) { // Arrange using var busContext = new RabbitMqContextBuilder() .WithExchange("TestExchange") .WithConnectionString("amqp://*****:*****@localhost") .CreateContext(); using var host = new MicroserviceHostBuilder() .WithBusContext(busContext) .WithQueueName("QueueName2") .AddEventListener <ErrorEventListener>() .CreateHost(); host.Start(); var command = new DummyCommand(message); var publisher = new CommandPublisher(busContext); // Act Task <DummyCommand> Act() => publisher.PublishAsync <DummyCommand>(command); // Arrange var exception = Assert.ThrowsExceptionAsync <DestinationQueueException>(Act); Assert.AreEqual("Received error command from queue Test.Command.Listener", exception.Result.Message); }
public void CreateContextCreatesProperContext(string connectionUrl, string exchangeName) { // Arrange var builder = new RabbitMqContextBuilder(); var connectionFactoryMock = new Mock <IConnectionFactory>(); connectionFactoryMock.SetupProperty(e => e.Uri, new Uri("amqp://localhost")); var connectionMock = new Mock <IConnection>(); connectionFactoryMock.Setup(e => e.CreateConnection()) .Returns(connectionMock.Object); var modelMock = new Mock <IModel>(); connectionMock.Setup(e => e.CreateModel()) .Returns(modelMock.Object); // Act builder.WithConnectionString(connectionUrl) .WithExchange(exchangeName) .CreateContext(connectionFactoryMock.Object); // Assert Assert.AreEqual(connectionUrl, connectionFactoryMock.Object.Uri.ToString()); modelMock.Verify(e => e.ExchangeDeclare(exchangeName, ExchangeType.Topic, false, false, null)); }
public void CatEventDoesNotTriggerPersonEvent(string name) { // Arrange using var busContext = new RabbitMqContextBuilder() .WithExchange("TestExchange") .WithConnectionString("amqp://*****:*****@localhost") .CreateContext(); using var host = new MicroserviceHostBuilder() .WithBusContext(busContext) .AddEventListener <PersonEventListener>() .AddEventListener <CatEventListener>() .CreateHost(); host.Start(); var publisher = new EventPublisher(busContext); var catEvent = new CatAddedEvent { Cat = new Cat { Name = name } }; // Act publisher.Publish(catEvent); Thread.Sleep(WaitTime); // Assert Assert.IsNull(PersonEventListener.ResultEvent); Assert.AreEqual(catEvent, CatEventListener.ResultEvent); }
public void EventListenerHandlesMultipleEvents(params string[] names) { // Arrange using var busContext = new RabbitMqContextBuilder() .WithExchange("TestExchange") .WithConnectionString("amqp://*****:*****@localhost") .CreateContext(); using var host = new MicroserviceHostBuilder() .WithBusContext(busContext) .WithQueueName("QueueName3") .AddEventListener <SpamEventListener>() .CreateHost(); host.Start(); var publisher = new EventPublisher(busContext); var catEvents = names.Select(e => new CatAddedEvent { Cat = new Cat { Name = e } }).ToList(); // Act foreach (var @event in catEvents) { publisher.Publish(@event); } Thread.Sleep(WaitTime); CollectionAssert.AreEquivalent(catEvents, SpamEventListener.ResultEvents); }
public void CallbackIsCalledOnReceivedEvent(string queue, string message) { // Arrange using var context = new RabbitMqContextBuilder() .WithConnectionString("amqp://*****:*****@localhost") .WithExchange("HelloExchange") .CreateContext(); bool messageReceived = false; using var receiver = context.CreateMessageReceiver(queue, new [] { "#" }); receiver.StartReceivingMessages(); receiver.StartHandlingMessages(e => messageReceived = true); var eventMessage = new EventMessage { Body = Encoding.Unicode.GetBytes(message), Timestamp = 10, CorrelationId = Guid.NewGuid(), Topic = "irrelevant", EventType = "TestEvent" }; // Act var sender = context.CreateMessageSender(); sender.SendMessage(eventMessage); Thread.Sleep(WaitTime); // Assert Assert.AreEqual(true, messageReceived); }
public static void UseMicroserviceHost(this IServiceCollection services) { Enum.TryParse(Environment.GetEnvironmentVariable("LOG_LEVEL"), out LogLevel logLevel); var contextBuilder = new RabbitMqContextBuilder().ReadFromEnvironmentVariables(); var context = Policy.Handle <BrokerUnreachableException>() .WaitAndRetryForever(sleepDurationProvider => TimeSpan.FromSeconds(5)) .Execute(contextBuilder.CreateContext); var loggerFactory = LoggerFactory.Create(configure => { configure.AddConsole().SetMinimumLevel(logLevel); }); var microserviceHost = new MicroserviceHostBuilder() .SetLoggerFactory(loggerFactory) .RegisterDependencies(services) .WithQueueName(Environment.GetEnvironmentVariable("BROKER_QUEUE_NAME")) .WithBusContext(context) .UseConventions() .CreateHost(); services.AddLogging(builder => builder.AddConsole().SetMinimumLevel(logLevel)); services.AddSingleton(context); services.AddSingleton(microserviceHost); services.AddHostedService <Miffy>(); }
public void CallbackIsCalledOnReceivedEventWithSpecificTopic(string topicPattern, string topic, bool expected) { // Arrange using IBusContext <IConnection> context = new RabbitMqContextBuilder() .WithConnectionString("amqp://*****:*****@localhost") .WithExchange("HelloExchange") .CreateContext(); bool messageReceived = false; using var receiver = context.CreateMessageReceiver("topic.queue.test", new [] { topicPattern }); receiver.StartReceivingMessages(); receiver.StartHandlingMessages(e => messageReceived = true); var eventMessage = new EventMessage { Body = Encoding.Unicode.GetBytes("TestMessage"), Timestamp = 10, CorrelationId = Guid.NewGuid(), Topic = topic, EventType = "TestEvent" }; // Act var sender = context.CreateMessageSender(); sender.SendMessage(eventMessage); Thread.Sleep(WaitTime); // Assert Assert.AreEqual(messageReceived, expected); }
public void EventListenerReceivesMessageAsync(string firstName, string lastName, string email, string phone) { // Arrange using var busContext = new RabbitMqContextBuilder() .WithExchange("TestExchange") .WithConnectionString("amqp://*****:*****@localhost") .CreateContext(); using var host = new MicroserviceHostBuilder() .WithBusContext(busContext) .AddEventListener <PersonEventListener>() .CreateHost(); host.Start(); var publisher = new EventPublisher(busContext); var personEvent = new PersonAddedEvent { Person = new Person { FirstName = firstName, LastName = lastName, Email = email, PhoneNumber = phone } }; // Act publisher.PublishAsync(personEvent); Thread.Sleep(WaitTime); // Assert Assert.AreEqual(personEvent, PersonEventListener.ResultEvent); }
public void PausePausesReceivingMessages(long timestamp) { // Arrange using IBusContext <IConnection> context = new RabbitMqContextBuilder() .WithConnectionString("amqp://*****:*****@localhost") .WithExchange("HelloExchange") .CreateContext(); bool messageReceived = false; using var receiver = context.CreateMessageReceiver("topic.queue.test", new [] { "test" }); receiver.StartReceivingMessages(); receiver.StartHandlingMessages(e => messageReceived = true); var eventMessage = new EventMessage { Body = Encoding.Unicode.GetBytes("TestMessage"), Timestamp = timestamp, CorrelationId = Guid.NewGuid(), Topic = "test", EventType = "TestEvent" }; // Act receiver.Pause(); var sender = context.CreateMessageSender(); sender.SendMessage(eventMessage); Thread.Sleep(WaitTime); // Assert Assert.AreEqual(false, messageReceived); }
/// <summary> /// Entrypoint /// </summary> static void Main(string[] args) { /** * Logging is important, so first set up a logger factory */ using var loggerFactory = LoggerFactory.Create(configure => { configure.AddConsole().SetMinimumLevel(LogLevel.Information); }); /** * Set up a context using environment variables */ using var context = new RabbitMqContextBuilder() .ReadFromEnvironmentVariables() .CreateContext(); /** * Build a host using the loggerfactory, context and register any event listeners in the package. */ using var hostBuilder = new MicroserviceReplayHostBuilder() .SetLoggerFactory(loggerFactory) .WithBusContext(context) .UseConventions(); /** * Now create the host and start it */ using IMicroserviceReplayHost host = (MicroserviceReplayHost)hostBuilder.CreateHost(); host.Start(); /** * Start spamming events to the auditlogger as a demonstration */ StartSpammingEvents(context); /** * Now let's start replaying, first create a replay command */ Guid processId = Guid.NewGuid(); ReplayEventsCommand replayEventsCommand = new ReplayEventsCommand(DateTime.Now.ToFileTimeUtc(), processId) { Types = new List <string> { "AnimalAddedEvent" } }; /** * Create the publishers */ ICommandPublisher publisher = new CommandPublisher(context); IReplayCommandPublisher replayCommandPublisher = new ReplayCommandPublisher(host, publisher, loggerFactory); /** * Commence a replay! */ replayCommandPublisher.Initiate(replayEventsCommand); }
public void WithExchangeSetsExchangeName(string exchange) { // Arrange var builder = new RabbitMqContextBuilder(); // Act builder.WithExchange(exchange); // Assert Assert.AreEqual(exchange, builder.ExchangeName); }
public void WithConnectionStringSetsConnectionStringUri(string connectionString) { // Arrange var builder = new RabbitMqContextBuilder(); // Act builder.WithConnectionString(connectionString); // Assert Assert.AreEqual(new Uri(connectionString), builder.ConnectionString); }
public static void UseRabbitMq(this IServiceCollection services) { var contextBuilder = new RabbitMqContextBuilder().ReadFromEnvironmentVariables(); var context = Policy.Handle <BrokerUnreachableException>() .WaitAndRetryForever(sleepDurationProvider => TimeSpan.FromSeconds(5)) .Execute(contextBuilder.CreateContext); services.AddSingleton(context); services.AddTransient <IModuleService, ModuleService>(); services.AddSingleton <ICommandPublisher, CommandPublisher>(); services.AddSingleton <ICsvLoader, CsvLoader>(); }
public void PersonFullNamerIsProperlyReceived(string destQueue, string firstName, string lastName) { // arrange using var context = new RabbitMqContextBuilder() .WithConnectionString("amqp://*****:*****@localhost") .WithExchange("HelloExchange") .CreateContext(); using var receiver = context.CreateCommandReceiver(destQueue); receiver.DeclareCommandQueue(); var sender = context.CreateCommandSender(); var nameObject = new Person { FirstName = firstName, LastName = lastName }; var command = new CommandMessage { DestinationQueue = destQueue, Timestamp = 294859, CorrelationId = Guid.NewGuid(), ReplyQueue = "ReplyQueue", Body = Encoding.Unicode.GetBytes(JsonConvert.SerializeObject(nameObject)) }; // Act receiver.StartReceivingCommands(commandMessage => { Person person = JsonConvert.DeserializeObject <Person>(Encoding.Unicode.GetString(commandMessage.Body)); person.FullName = $"{person.FirstName} {person.LastName}"; string jsonResponse = JsonConvert.SerializeObject(person); return(new CommandMessage { CorrelationId = commandMessage.CorrelationId, Timestamp = commandMessage.Timestamp, Body = Encoding.Unicode.GetBytes(jsonResponse) }); }); var result = sender.SendCommandAsync(command); // Assert var stringResult = Encoding.Unicode.GetString(result.Result.Body); var personResult = JsonConvert.DeserializeObject <Person>(stringResult); Assert.AreEqual($"{firstName} {lastName}", personResult.FullName); }
public void ReadFromEnvironmentVariablesWorks(string connectionString, string exchangeName) { // Arrange var builder = new RabbitMqContextBuilder(); Environment.SetEnvironmentVariable(EnvVarNames.BrokerConnectionString, connectionString); Environment.SetEnvironmentVariable(EnvVarNames.BrokerExchangeName, exchangeName); // Act builder.ReadFromEnvironmentVariables(); // Assert Assert.AreEqual(new Uri(connectionString), builder.ConnectionString); Assert.AreEqual(exchangeName, builder.ExchangeName); }
public void ReadFromEnvironmentVariablesThrowsExceptionOnMissingExchangeName() { // Arrange var builder = new RabbitMqContextBuilder(); Environment.SetEnvironmentVariable(EnvVarNames.BrokerConnectionString, "amqp://*****:*****@localhost"); Environment.SetEnvironmentVariable(EnvVarNames.BrokerExchangeName, null); // Act void Act() => builder.ReadFromEnvironmentVariables(); // Assert var exception = Assert.ThrowsException <BusConfigurationException>(Act); Assert.AreEqual($"{EnvVarNames.BrokerExchangeName} env variable not set", exception.Message); }
static async Task Main(string[] args) { Console.Write("Enter RabbitMQ connection string: "); var connectionString = Console.ReadLine(); Console.WriteLine($"Using RabbitMQ connection string: '{connectionString}'"); Environment.SetEnvironmentVariable("BROKER_CONNECTION_STRING", connectionString); Console.WriteLine(); Console.Write("Enter MSSQL connection string: "); connectionString = Console.ReadLine(); Console.WriteLine($"Using MSSQL connection string: '{connectionString}'"); Environment.SetEnvironmentVariable("DB_CONNECTION_STRING", connectionString); Console.WriteLine(); using var loggerFactory = LoggerFactory.Create(configure => { configure.AddConsole().SetMinimumLevel(LogLevel.Debug); }); MiffyLoggerFactory.LoggerFactory = loggerFactory; RabbitMqLoggerFactory.LoggerFactory = loggerFactory; using var context = new RabbitMqContextBuilder() .ReadFromEnvironmentVariables() .CreateContext(); // using var host = new MicroserviceHostBuilder() // .SetLoggerFactory(loggerFactory) // .WithBusContext(context) // .WithQueueName(QueueName) // .UseConventions() // .CreateHost(); // host.Start(); ICommandPublisher commandPublisher = new CommandPublisher(context); var klantId = new Guid("979F7437-F7F3-4662-7485-08D80D5821EA"); // Export(); await ImportDataIntoSystemFromFile(commandPublisher, klantId, @"C:\Users\Dirk-Jan\Dropbox\S6\prestaties beide.txt"); }
public void CommandIsProperlySentThrough(string destQueue, string message) { // arrange using var context = new RabbitMqContextBuilder() .WithConnectionString("amqp://*****:*****@localhost") .WithExchange("HelloExchange") .CreateContext(); using var receiver = context.CreateCommandReceiver(destQueue); receiver.DeclareCommandQueue(); var sender = context.CreateCommandSender(); var nameObject = new NameMessage(message); var command = new CommandMessage { DestinationQueue = destQueue, Timestamp = 294859, CorrelationId = Guid.NewGuid(), ReplyQueue = "ReplyQueue", Body = Encoding.Unicode.GetBytes(JsonConvert.SerializeObject(nameObject)) }; // Act receiver.StartReceivingCommands(commandMessage => { NameMessage name = JsonConvert.DeserializeObject <NameMessage>(Encoding.Unicode.GetString(commandMessage.Body)); return(new CommandMessage { CorrelationId = commandMessage.CorrelationId, Timestamp = commandMessage.Timestamp, Body = Encoding.Unicode.GetBytes($"Hallo {name.Name}") }); }); var result = sender.SendCommandAsync(command); // Assert var stringResult = Encoding.Unicode.GetString(result.Result.Body); Assert.AreEqual($"Hallo {message}", stringResult); }
static void Main(string[] args) { using ILoggerFactory loggerFactory = LoggerFactory.Create(configure => { string logLevelString = Environment.GetEnvironmentVariable(EnvVarNames.LogLevel) ?? "Information"; LogLevel logLevel = Enum.Parse <LogLevel>(logLevelString); configure.AddConsole().SetMinimumLevel(logLevel); }); MiffyLoggerFactory.LoggerFactory = loggerFactory; RabbitMqLoggerFactory.LoggerFactory = loggerFactory; using IBusContext <IConnection> context = new RabbitMqContextBuilder() .ReadFromEnvironmentVariables() .CreateContext(); using IMicroserviceHost host = new MicroserviceHostBuilder() .SetLoggerFactory(loggerFactory) .WithBusContext(context) .RegisterDependencies(services => { services.AddDbContext <AuditLogContext>(config => { config.UseMySql(Environment.GetEnvironmentVariable(EnvVarNames.DatabaseConnectionString)); config.UseLoggerFactory(loggerFactory); }, ServiceLifetime.Singleton); services.AddTransient <IAuditLogItemRepository, AuditLogItemRepository>(); services.AddTransient <IEventPublisher, EventPublisher>(); using var serviceScope = services.BuildServiceProvider().GetRequiredService <IServiceScopeFactory>().CreateScope(); var auditLogContext = serviceScope.ServiceProvider.GetService <AuditLogContext>(); auditLogContext.Database.Migrate(); }) .UseConventions() .CreateHost(); host.Start(); // Keep app running new ManualResetEvent(false).WaitOne(); }
public void ResumeResumesReceivingMessagesAfterItWasPaused(long timestamp) { // Arrange using IBusContext <IConnection> context = new RabbitMqContextBuilder() .WithConnectionString("amqp://*****:*****@localhost") .WithExchange("HelloExchange") .CreateContext(); bool messageReceived = false; using var receiver = context.CreateCommandReceiver("topic.queue.test"); receiver.DeclareCommandQueue(); receiver.StartReceivingCommands(e => { messageReceived = true; return(null); }); var eventMessage = new CommandMessage { Body = Encoding.Unicode.GetBytes("TestMessage"), Timestamp = timestamp, CorrelationId = Guid.NewGuid(), DestinationQueue = "topic.queue.test", EventType = "TestEvent" }; receiver.Pause(); // Act var sender = context.CreateCommandSender(); sender.SendCommandAsync(eventMessage); receiver.Resume(); // Assert Thread.Sleep(WaitTime); Assert.AreEqual(true, messageReceived); }
public void EventListenerDoesCallListenerOnInvalidJson(string body) { // Arrange using var busContext = new RabbitMqContextBuilder() .WithExchange("TestExchange") .WithConnectionString("amqp://*****:*****@localhost") .CreateContext(); using var host = new MicroserviceHostBuilder() .WithBusContext(busContext) .AddEventListener <PersonEventListener>() .CreateHost(); host.Start(); EventPublisher publisher = new EventPublisher(busContext); // Act publisher.Publish(242424, "PeopleApp.Persons.New", Guid.NewGuid(), "PersonEvent", body); Thread.Sleep(WaitTime); // Assert Assert.IsNull(PersonEventListener.ResultEvent); }
/** * An example implementation on how to set up a * MicroserviceHost with RabbitMQ in the Main method * * Setting up a functioning RabbitMQ instance with docker is as easy as running: * docker run -d -p 15672:15672 -p 5672:5672 rabbitmq:3-management */ static void Main(string[] args) { /* * Logging is quite important, for this reason we first create * a loggerfactory that will be used in the rest of the application * * This one outputs to the console */ using ILoggerFactory loggerFactory = LoggerFactory.Create(configure => { configure.AddConsole().SetMinimumLevel(LogLevel.Error); }); /* * To reach the library classes, a static class has been put in place * to register a logger */ MiffyLoggerFactory.LoggerFactory = loggerFactory; RabbitMqLoggerFactory.LoggerFactory = loggerFactory; /* * Now that the logger is done, let's create a RabbitMq context with * an exchange called MVM.EventExchange and a connection string * that connects to a local RabbitMQ instance */ RabbitMqContextBuilder contextBuilder = new RabbitMqContextBuilder() .WithExchange("MVM.EventExchange") .WithConnectionString("amqp://*****:*****@localhost"); /* * Now instantiate the context and ensure that it's disposed of by using a * 'using' statement. */ using IBusContext <IConnection> context = contextBuilder.CreateContext(); /** * Create a dummy database context for testing with an in-memory database */ PolisContext databaseContext = new PolisContext(); /** * Now create a builder that will build our microservice host. * * First, register our logger by setting the logger factory, * next we register any dependencies we might need, like a DBContext * that is injected into our CommandListeners and EventListeners * * Since most of the inner workings of this framework are asynchronous, we * strongly urge you to set up a loggerfactory to quickly find any errors going over the bus. * * Then, throw our context into the builder and lastly, ensure that * all our event/command listeners are registered by calling UseConventions(). * * UseConventions could be replaced by multiple AddEventListener calls. */ MicroserviceHostBuilder builder = new MicroserviceHostBuilder() .SetLoggerFactory(loggerFactory) // This method also accepts a service collection as input .RegisterDependencies(services => { services.AddSingleton(databaseContext); }) .WithQueueName("ExampleService.Queue") .WithBusContext(context) .UseConventions(); /** * Lastly, instantiate a host and ensure it starts */ using IMicroserviceHost host = builder.CreateHost(); host.Start(); /** * Let's add a C# event listener for fun */ host.EventMessageReceived += (message, eventArgs) => { Console.WriteLine("Received a EventMessage!"); }; /** * Now let's pretend this service is running somewhere in a cluster * and is receiving events, let's fire some events at it */ string[] names = { "Jack", "Jake", "Penny", "Robin", "Rick", "Vinny", "Spencer" }; IEventPublisher publisher = new EventPublisher(context, loggerFactory); foreach (string name in names) { PolisToegevoegdEvent toegevoegdEvent = new PolisToegevoegdEvent { Polis = new Polis { Klantnaam = name } }; publisher.PublishAsync(toegevoegdEvent); } /** * Now let's wait 1 second for all the events to arrive and be processed */ Thread.Sleep(2000); /** * Now let's fire a command and retrieve a list of polissen */ ICommandPublisher commandPublisher = new CommandPublisher(context, loggerFactory); HaalPolissenOpCommand command = new HaalPolissenOpCommand(); HaalPolissenOpCommandResult commandResult = commandPublisher.PublishAsync <HaalPolissenOpCommandResult>(command).Result; /** * Now, print the result! */ foreach (Polis polis in commandResult.Polissen) { Console.WriteLine($"Found polis for {polis.Klantnaam} with ID {polis.Id}"); } /** * Now let's see what happens if we send a mangled json event * * This should log a critical error in the console and tell you how you might be able to diagnose the problem. */ publisher.Publish(0, "MVM.Polisbeheer.PolisToegevoegd", Guid.Empty, "PolisToegevoegdEvent", "{[somerandomjson}]"); /** * Lastly, let's see how the queue deals with exceptions on the other side */ ExceptionCommand exceptionCommand = new ExceptionCommand(); try { /** * This will throw an exception in the receiver */ _ = commandPublisher.PublishAsync <ExceptionCommand>(exceptionCommand).Result; } catch (AggregateException expectedException) { DestinationQueueException destinationQueueException = expectedException.InnerExceptions.First() as DestinationQueueException; /** * Now the expectedException.Innerexception will reveal all the info we need */ Console.WriteLine($"{destinationQueueException?.InnerException?.GetType().Name} {destinationQueueException?.InnerException?.Message}"); Console.WriteLine($"Destination queue: {destinationQueueException?.DestinationQueueName}, " + $"Reply queue: {destinationQueueException?.ReplyQueueName}, " + $"Id: {destinationQueueException?.CorrelationId}"); } }