/// <summary> /// Registers task and starts consuming messages /// </summary> /// <typeparam name="T"></typeparam> /// <param name="queueName"></param> /// <param name="OnConsume"></param> public void ConsumeTask <T>(string queueName, Func <T, TaskParameters, ClientActiveTasks, Task> OnConsume, Func <ClientActiveTasks, int> PostConsumeCleanup, ushort concurrency) { // Caution. The queue is also declard inside PublishTask above _logger.LogInformation("Prefetch concurrency count {0}", concurrency); lock (_channel) { _channel.QueueDeclare(queue: queueName, durable: true, exclusive: false, autoDelete: false, arguments: null); // See https://www.rabbitmq.com/consumer-prefetch.html // See https://stackoverflow.com/questions/59493540/what-is-prefetchsize-in-rabbitmq _channel.BasicQos(prefetchSize: 0, prefetchCount: concurrency, global: false); } _logger.LogInformation(" [*] Waiting for messages, queueName - {0}", queueName); var consumer = new EventingBasicConsumer(_channel); consumer.Received += async(model, ea) => { // This object exists so that we can wrap all OnConsumes with a try-finally here // And during the finally block remove the task from the set of active tasks // At this level of the code we don't have the specific task information // Instead the specific task my register a task by calling register ClientActiveTasks clientCleanup = new ClientActiveTasks(); var taskObject = CommonUtils.BytesToMessage <TaskObject <T> >(ea.Body); _logger.LogInformation(" [x] {0} Received {1}", queueName, taskObject.ToString()); // TODO: Update JobStatus table here (started timestamp) try { await OnConsume(taskObject.Data, taskObject.TaskParameters, clientCleanup); } catch (Exception e) { _logger.LogError(e, "Error occured in RabbitMQConnection {0} for message {1}", queueName, taskObject.ToString()); } finally { PostConsumeCleanup(clientCleanup); } _logger.LogInformation(" [x] {0} Done {1}", queueName, taskObject.ToString()); // TODO Update JobStatus table here (including timestamp + result + exception if it occurred) lock (_channel) { _channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false); } }; lock (_channel) { _channel.BasicConsume(queue: queueName, autoAck: false, consumer: consumer); } }
public ClientActiveTasks(ClientActiveTasks source) : base(source) { }