private static ZyRabbitOptions GetTestOptions(ZyRabbitOptions options) { options = options ?? new ZyRabbitOptions(); options.ClientConfiguration = options.ClientConfiguration ?? ZyRabbitConfiguration.Local; options.ClientConfiguration.Queue.AutoDelete = true; options.ClientConfiguration.Exchange.AutoDelete = true; return(options); }
public async Task Should_Use_Custom_Policy() { var defaultCalled = false; var customCalled = false; var defaultPolicy = Policy .Handle <Exception>() .FallbackAsync(ct => { defaultCalled = true; return(Task.FromResult(0)); }); var declareQueuePolicy = Policy .Handle <OperationInterruptedException>() .RetryAsync(async(e, retryCount, ctx) => { customCalled = true; var defaultQueueCfg = ctx.GetPipeContext().GetClientConfiguration().Queue; var topology = ctx.GetTopologyProvider(); var queue = new QueueDeclaration(defaultQueueCfg) { Name = ctx.GetQueueName(), Durable = false }; await topology.DeclareQueueAsync(queue); }); var options = new ZyRabbitOptions { Plugins = p => p.UsePolly(c => c .UsePolicy(defaultPolicy) .UsePolicy(declareQueuePolicy, PolicyKeys.QueueBind) ) }; using (var client = ZyRabbitFactory.CreateTestClient(options)) { await client.SubscribeAsync <BasicMessage>( message => Task.FromResult(0), ctx => ctx.UseSubscribeConfiguration(cfg => cfg .Consume(c => c .FromQueue("does_not_exist")) )); } Assert.True(customCalled); Assert.False(defaultCalled, "The custom retry policy should be called"); }
public async Task Should_Support_Chained_Message_Sequences() { var sequenceOptions = new ZyRabbitOptions { Plugins = p => p .UseStateMachine() .UseMessageContext(context => new MessageContext { GlobalRequestId = Guid.NewGuid() }) .UseContextForwarding() .UseGlobalExecutionId() }; using (var serviceA = ZyRabbitFactory.CreateTestClient(sequenceOptions)) using (var serviceB = ZyRabbitFactory.CreateTestClient(sequenceOptions)) using (var serviceC = ZyRabbitFactory.CreateTestClient(sequenceOptions)) { /* Setup */ await serviceB.SubscribeAsync <FirstMessage>(async message => { var nestedSequence = serviceB.ExecuteSequence(s => s .PublishAsync(new SecondMessage()) .Complete <ThirdMessage>()); await nestedSequence.Task; await serviceB.PublishAsync(new ForthMessage()); } ); await serviceC.SubscribeAsync <SecondMessage>(message => { return(serviceC.PublishAsync(new ThirdMessage())); }); /* Test */ var mainSequence = serviceA.ExecuteSequence(s => s .PublishAsync(new FirstMessage()) .Complete <ForthMessage>() ); await mainSequence.Task; /* Assert */ Assert.True(true, "Shoud complete sequence"); } }
public async Task Should_Be_Able_To_Create_Unique_Queues_With_Naming_Suffix() { var options = new ZyRabbitOptions { Plugins = ioc => ioc .UseApplicationQueueSuffix() .UseQueueSuffix() }; using (var firstSubscriber = ZyRabbitFactory.CreateTestClient(options)) using (var secondSubscriber = ZyRabbitFactory.CreateTestClient(options)) using (var publisher = ZyRabbitFactory.CreateTestClient()) { /* Setup */ var firstTcs = new TaskCompletionSource <BasicMessage>(); var secondTcs = new TaskCompletionSource <BasicMessage>(); var message = new BasicMessage { Prop = "I'm delivered twice." }; await firstSubscriber.SubscribeAsync <BasicMessage>(msg => { firstTcs.TrySetResult(msg); return(Task.FromResult(0)); }, ctx => ctx.UseCustomQueueSuffix("first") ); await secondSubscriber.SubscribeAsync <BasicMessage>(msg => { secondTcs.TrySetResult(msg); return(Task.FromResult(0)); }, ctx => ctx.UseCustomQueueSuffix("second") ); /* Test */ await publisher.PublishAsync(message); await firstTcs.Task; await secondTcs.Task; /* Assert */ Assert.Equal(message.Prop, firstTcs.Task.Result.Prop); Assert.Equal(message.Prop, secondTcs.Task.Result.Prop); } }
public async Task Should_Be_Able_To_Override_Custom_Suffix() { var customSuffix = new ZyRabbitOptions { Plugins = p => p.UseCustomQueueSuffix("custom") }; using (var publisher = ZyRabbitFactory.CreateTestClient()) using (var firstClient = ZyRabbitFactory.CreateTestClient(customSuffix)) using (var secondClient = ZyRabbitFactory.CreateTestClient(customSuffix)) { /* Setup */ var firstTsc = new TaskCompletionSource <BasicMessage>(); var secondTsc = new TaskCompletionSource <BasicMessage>(); await firstClient.SubscribeAsync <BasicMessage>(message => { firstTsc.TrySetResult(message); return(Task.FromResult(0)); }); await secondClient.SubscribeAsync <BasicMessage>(message => { secondTsc.TrySetResult(message); return(Task.FromResult(0)); }, ctx => ctx.UseCustomQueueSuffix("special")); /* Test */ await publisher.PublishAsync(new BasicMessage()); await firstTsc.Task; await secondTsc.Task; /* Assert */ Assert.True(true, "Should be delivered to both subscribers"); } }
public async Task Should_Forward_For_Rpc() { var withGloblalExecutionId = new ZyRabbitOptions { Plugins = p => p.UseGlobalExecutionId() }; using (var requester = ZyRabbitFactory.CreateTestClient(withGloblalExecutionId)) using (var firstResponder = ZyRabbitFactory.CreateTestClient(withGloblalExecutionId)) using (var secondResponder = ZyRabbitFactory.CreateTestClient(withGloblalExecutionId)) using (var thridResponder = ZyRabbitFactory.CreateTestClient(withGloblalExecutionId)) using (var consumer = ZyRabbitFactory.CreateTestClient()) { /* Setup */ var taskCompletionSources = new List <TaskCompletionSource <BasicDeliverEventArgs> > { new TaskCompletionSource <BasicDeliverEventArgs>(), new TaskCompletionSource <BasicDeliverEventArgs>(), new TaskCompletionSource <BasicDeliverEventArgs>() }; await firstResponder.RespondAsync <FirstRequest, FirstResponse>(async message => { await firstResponder.PublishAsync(new SecondMessage()); return(new FirstResponse()); }); await secondResponder.SubscribeAsync <SecondMessage>(message => secondResponder.PublishAsync(new ThirdMessage())); await thridResponder.SubscribeAsync <ThirdMessage>(message => Task.FromResult(0)); await consumer.DeclareQueueAsync(new QueueDeclaration { AutoDelete = true, Name = "take_all", }); await consumer.BasicConsumeAsync(args => { var tsc = taskCompletionSources.First(t => !t.Task.IsCompleted); tsc.TrySetResult(args); return(Task.FromResult <Acknowledgement>(new Ack())); }, ctx => ctx .UseConsumeConfiguration(cfg => cfg .FromQueue("take_all") .OnExchange("zyrabbit.integrationtests.testmessages") .WithRoutingKey("#") ) ); /* Test */ await requester.RequestAsync <FirstRequest, FirstResponse>(); Task.WaitAll(taskCompletionSources.Select(t => t.Task).ToArray <Task>()); var results = new List <string>(); foreach (var tcs in taskCompletionSources) { var id = Encoding.UTF8.GetString(tcs.Task.Result.BasicProperties.Headers[ZyRabbit.Enrichers.GlobalExecutionId.PropertyHeaders.GlobalExecutionId] as byte[]); results.Add(id); } /* Assert */ Assert.NotNull(results[0]); Assert.Equal(results[0], results[1]); Assert.Equal(results[1], results[2]); } }
public static InstanceFactory CreateTestInstanceFactory(ZyRabbitOptions options = null) { return(Instantiation.ZyRabbitFactory.CreateInstanceFactory(GetTestOptions(options))); }
public static Instantiation.Disposable.BusClient CreateTestClient(ZyRabbitOptions options = null) { return(Instantiation.ZyRabbitFactory.CreateSingleton(GetTestOptions(options))); }
public static IServiceCollection AddZyRabbit(this IServiceCollection collection, ZyRabbitOptions options = null) { var adapter = new ServiceCollectionAdapter(collection ?? throw new ArgumentNullException(nameof(collection))); adapter.AddZyRabbit(options); return(collection); }
public static ContainerBuilder RegisterZyRabbit(this ContainerBuilder builder, ZyRabbitOptions options = null) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } var adapter = new ContainerBuilderAdapter(builder); adapter.AddZyRabbit(options); builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(type => type.Namespace.StartsWith(ZyRabbit))); return(builder); }
public static IDependencyRegister AddZyRabbit(this IDependencyRegister register, ZyRabbitOptions options = null) { register .AddSingleton(options?.ClientConfiguration ?? ZyRabbitConfiguration.Local) .AddSingleton <IConnectionFactory, ConnectionFactory>(provider => { var cfg = provider.GetService <ZyRabbitConfiguration>(); return(new ConnectionFactory { VirtualHost = cfg.VirtualHost, UserName = cfg.Username, Password = cfg.Password, Port = cfg.Port, HostName = cfg.Hostnames.FirstOrDefault() ?? string.Empty, AutomaticRecoveryEnabled = cfg.AutomaticRecovery, TopologyRecoveryEnabled = cfg.TopologyRecovery, NetworkRecoveryInterval = cfg.RecoveryInterval, ClientProperties = provider.GetService <IClientPropertyProvider>().GetClientProperties(cfg), Ssl = cfg.Ssl }); }) .AddSingleton <IChannelPoolFactory, AutoScalingChannelPoolFactory>() .AddSingleton(resolver => AutoScalingOptions.Default) .AddSingleton <IClientPropertyProvider, ClientPropertyProvider>() .AddSingleton <ISerializer>(resolver => new Serialization.JsonSerializer(new Newtonsoft.Json.JsonSerializer { TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple, Formatting = Formatting.None, CheckAdditionalContent = true, ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() }, ObjectCreationHandling = ObjectCreationHandling.Auto, DefaultValueHandling = DefaultValueHandling.Ignore, TypeNameHandling = TypeNameHandling.Auto, ReferenceLoopHandling = ReferenceLoopHandling.Serialize, MissingMemberHandling = MissingMemberHandling.Ignore, PreserveReferencesHandling = PreserveReferencesHandling.Objects, NullValueHandling = NullValueHandling.Ignore })) .AddSingleton <IConsumerFactory, ConsumerFactory>() .AddSingleton <IChannelFactory>(resolver => { var channelFactory = new ChannelFactory( resolver.GetService <IConnectionFactory>(), resolver.GetService <ZyRabbitConfiguration>(), resolver.GetService <ILogger <ChannelFactory> >()); channelFactory .ConnectAsync() .ConfigureAwait(false) .GetAwaiter() .GetResult(); return(channelFactory); }) .AddSingleton <ISubscriptionRepository, SubscriptionRepository>() .AddSingleton <ITopologyProvider, TopologyProvider>() .AddTransient <IPublisherConfigurationFactory, PublisherConfigurationFactory>() .AddTransient <IBasicPublishConfigurationFactory, BasicPublishConfigurationFactory>() .AddTransient <IConsumerConfigurationFactory, ConsumerConfigurationFactory>() .AddTransient <IConsumeConfigurationFactory, ConsumeConfigurationFactory>() .AddTransient <IExchangeDeclarationFactory, ExchangeDeclarationFactory>() .AddTransient <IQueueConfigurationFactory, QueueDeclarationFactory>() .AddSingleton <INamingConventions, NamingConventions>() .AddSingleton <IExclusiveLock, ExclusiveLock>() .AddSingleton <IBusClient, BusClient>() .AddSingleton <IResourceDisposer, ResourceDisposer>() .AddTransient <IInstanceFactory>(resolver => new InstanceFactory(resolver)) .AddSingleton <IPipeContextFactory, PipeContextFactory>() .AddTransient <IExtendedPipeBuilder, PipeBuilder>(resolver => new PipeBuilder(resolver)) .AddSingleton <IPipeBuilderFactory>(provider => new PipeBuilderFactory(provider)); var clientBuilder = new ClientBuilder(); options?.Plugins?.Invoke(clientBuilder); clientBuilder.DependencyInjection?.Invoke(register); register.AddSingleton(clientBuilder.PipeBuilderAction); options?.DependencyInjection?.Invoke(register); if (!register.IsRegistered(typeof(ILogger <>))) { register.AddSingleton(typeof(ILogger <>), typeof(Logger <>)); } if (!register.IsRegistered(typeof(ILogger))) { register.AddSingleton <ILogger, NullLogger>(resolver => NullLogger.Instance); } if (!register.IsRegistered(typeof(ILoggerFactory))) { register.AddSingleton <ILoggerFactory, NullLoggerFactory>(); } return(register); }