/// <summary> /// Finds and subscribes to the queue and sends response /// </summary> private async Task Subscribe(MqClient client, HorseMessage message) { HorseQueue queue = _server.FindQueue(message.Target); //if auto creation active, try to create queue if (queue == null && _server.Options.AutoQueueCreation) { QueueOptions options = QueueOptions.CloneFrom(_server.Options); queue = await _server.CreateQueue(message.Target, options, message, _server.DeliveryHandlerFactory, true, true); } if (queue == null) { if (message.WaitResponse) { await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound)); } return; } QueueClient found = queue.FindClient(client.UniqueId); if (found != null) { if (message.WaitResponse) { await client.SendAsync(message.CreateResponse(HorseResultCode.Ok)); } return; } QueueSubscriptionResult result = await queue.AddClient(client); if (message.WaitResponse) { switch (result) { case QueueSubscriptionResult.Success: await client.SendAsync(message.CreateResponse(HorseResultCode.Ok)); break; case QueueSubscriptionResult.Unauthorized: await client.SendAsync(message.CreateResponse(HorseResultCode.Unauthorized)); break; case QueueSubscriptionResult.Full: await client.SendAsync(message.CreateResponse(HorseResultCode.LimitExceeded)); break; } } }
public async Task Handle(MqClient client, HorseMessage message, bool fromNode) { try { HorseQueue queue = _server.FindQueue(message.Target); //if auto creation active, try to create queue if (queue == null && _server.Options.AutoQueueCreation) { QueueOptions options = QueueOptions.CloneFrom(_server.Options); queue = await _server.CreateQueue(message.Target, options, message, _server.DeliveryHandlerFactory, true, true); } if (queue == null) { if (!string.IsNullOrEmpty(message.MessageId)) { await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound)); } return; } await HandlePullRequest(client, message, queue); } catch (Exception e) { _server.SendError("PULL_REQUEST", e, $"QueueName:{message.Target}"); } }
/// <summary> /// Creates and returns persistent queue /// </summary> internal static async Task <HorseQueue> CreateQueue(HorseMq mq, string queueName, QueueOptions options, Func <DatabaseOptions, IPersistentDeliveryHandler> factory) { return(await mq.CreateQueue(queueName, options, async builder => { DatabaseOptions databaseOptions = ConfigurationFactory.Builder.CreateOptions(builder.Queue); IPersistentDeliveryHandler handler = factory(databaseOptions); await handler.Initialize(); return handler; })); }
/// <summary> /// Creates and returns persistent queue /// </summary> internal static async Task <HorseQueue> CreateQueue(HorseMq mq, string queueName, DeleteWhen deleteWhen, ProducerAckDecision producerAckDecision, QueueOptions options) { return(await mq.CreateQueue(queueName, options, async builder => { DatabaseOptions databaseOptions = ConfigurationFactory.Builder.CreateOptions(builder.Queue); PersistentDeliveryHandler handler = new PersistentDeliveryHandler(builder.Queue, databaseOptions, deleteWhen, producerAckDecision); await handler.Initialize(); return handler; })); }
/// <summary> /// Loads messages of queues in configuration /// </summary> public async Task LoadQueues(HorseMq server) { foreach (QueueConfiguration queueConfiguration in Config.Queues) { HorseQueue queue = server.FindQueue(queueConfiguration.Name); if (queue == null) { if (server.DeliveryHandlerFactory != null) { queue = await server.CreateQueue(queueConfiguration.Name, queueConfiguration.Configuration.ToOptions(), async builder => { builder.DeliveryHandlerHeader = queueConfiguration.DeliveryHandler; IMessageDeliveryHandler handler = await server.DeliveryHandlerFactory(builder); builder.OnAfterCompleted(b => { }); //don't trigger created events, it's already created and reloading return(handler); }); } else { queue = await Extensions.CreateQueue(server, queueConfiguration.Name, (DeleteWhen)queueConfiguration.DeleteWhen, (ProducerAckDecision)queueConfiguration.ProducerAck, queueConfiguration.Configuration.ToOptions()); } //queue creation not permitted, skip if (queue == null) { continue; } } else { if (queue.DeliveryHandler is IPersistentDeliveryHandler deliveryHandler) { await deliveryHandler.Initialize(); } } queueConfiguration.Queue = queue; } }
private async Task <HorseQueue> FindQueue(MqClient client, string name, HorseMessage message) { HorseQueue queue = _server.FindQueue(name); //if auto creation active, try to create queue if (queue == null && _server.Options.AutoQueueCreation) { QueueOptions options = QueueOptions.CloneFrom(_server.Options); queue = await _server.CreateQueue(name, options, message, _server.DeliveryHandlerFactory, true, true); } if (queue == null) { if (client != null && message != null && !string.IsNullOrEmpty(message.MessageId)) { await client.SendAsync(message.CreateResponse(HorseResultCode.NotFound)); } return(null); } return(queue); }
public async Task InPersistentHandler() { ConfigurationFactory.Destroy(); PersistentDeliveryHandler handler = null; HorseServer server = new HorseServer(); HorseMq mq = server.UseHorseMq(cfg => cfg .AddPersistentQueues(q => q.KeepLastBackup()) .UseDeliveryHandler(async builder => { DatabaseOptions options = new DatabaseOptions { Filename = "redelivery-test.tdb", InstantFlush = true, CreateBackupOnShrink = false, ShrinkInterval = TimeSpan.FromSeconds(60) }; handler = new PersistentDeliveryHandler(builder.Queue, options, DeleteWhen.AfterSend, ProducerAckDecision.None, true); await handler.Initialize(); return(handler); })); HorseQueue queue = await mq.CreateQueue("test"); HorseMessage message = new HorseMessage(MessageType.QueueMessage, "test"); message.SetMessageId("id"); message.SetStringContent("Hello, World!"); QueueMessage queueMessage = new QueueMessage(message); await handler.BeginSend(queue, queueMessage); List <KeyValuePair <string, int> > deliveries = handler.RedeliveryService.GetDeliveries(); Assert.Single(deliveries); Assert.Equal("id", deliveries[0].Key); Assert.Equal(1, deliveries[0].Value); string header = message.FindHeader(HorseHeaders.DELIVERY); Assert.Null(header); await handler.BeginSend(queue, queueMessage); deliveries = handler.RedeliveryService.GetDeliveries(); Assert.Single(deliveries); Assert.Equal("id", deliveries[0].Key); Assert.Equal(2, deliveries[0].Value); header = message.FindHeader(HorseHeaders.DELIVERY); Assert.NotNull(header); Assert.Equal(2, Convert.ToInt32(header)); queueMessage.MarkAsSent(); await handler.EndSend(queue, queueMessage); deliveries = handler.RedeliveryService.GetDeliveries(); Assert.Empty(deliveries); }
public async Task ReloadAfterRestart() { await Task.Delay(500); ConfigurationFactory.Destroy(); RedeliveryService service = new RedeliveryService("data/reload-test.tdb.delivery"); await service.Load(); await service.Clear(); await service.Set("id", 4); await service.Close(); if (System.IO.File.Exists("data/config.json")) { System.IO.File.Delete("data/config.json"); } if (System.IO.File.Exists("data/reload-test.tdb")) { System.IO.File.Delete("data/reload-test.tdb"); } if (System.IO.File.Exists("data/reload-test.tdb.delivery")) { System.IO.File.Delete("data/reload-test.tdb.delivery"); } HorseServer server = new HorseServer(); PersistentDeliveryHandler handler = null; Func <DeliveryHandlerBuilder, Task <IMessageDeliveryHandler> > fac = async builder => { DatabaseOptions options = new DatabaseOptions { Filename = "data/reload-test.tdb", InstantFlush = true, CreateBackupOnShrink = false, ShrinkInterval = TimeSpan.FromSeconds(60) }; handler = (PersistentDeliveryHandler)await builder.CreatePersistentDeliveryHandler(o => { return(new PersistentDeliveryHandler(builder.Queue, options, DeleteWhen.AfterSend, ProducerAckDecision.None, true)); }); return(handler); }; HorseMq mq = server.UseHorseMq(cfg => cfg .AddPersistentQueues(q => q.KeepLastBackup()) .UseDeliveryHandler(fac)); HorseQueue queue = await mq.CreateQueue("reload-test", o => o.Status = QueueStatus.Push); HorseMessage msg = new HorseMessage(MessageType.QueueMessage, "reload-test"); msg.SetMessageId("id"); msg.SetStringContent("Hello, World!"); await queue.Push(msg); QueueMessage queueMsg = queue.Messages.FirstOrDefault(); await handler.BeginSend(queue, queueMsg); await handler.RedeliveryService.Close(); ConfigurationFactory.Destroy(); mq = server.UseHorseMq(cfg => cfg .AddPersistentQueues(q => q.KeepLastBackup()) .UseDeliveryHandler(fac)); await mq.LoadPersistentQueues(); HorseQueue queue2 = mq.FindQueue("reload-test"); Assert.NotNull(queue2); Assert.NotEmpty(queue2.Messages); QueueMessage loadedMsg = queue2.Messages.FirstOrDefault(); Assert.NotNull(loadedMsg); Assert.Equal(1, loadedMsg.DeliveryCount); }