in extension/WebJobs.Extensions.RabbitMQ/Trigger/RabbitMQTriggerBinding.cs [18:104]
internal class RabbitMQTriggerBinding(IRabbitMQService service, string queueName, ILogger logger, Type parameterType, ushort prefetchCount, IDrainModeManager drainModeManager) : ITriggerBinding
{
private readonly IRabbitMQService service = service;
private readonly ILogger logger = logger;
private readonly Type parameterType = parameterType;
private readonly string queueName = queueName;
private readonly ushort prefetchCount = prefetchCount;
private readonly IDrainModeManager drainModeManager = drainModeManager;
public Type TriggerValueType => typeof(BasicDeliverEventArgs);
public IReadOnlyDictionary<string, Type> BindingDataContract { get; } = CreateBindingDataContract();
public Task<ITriggerData> BindAsync(object value, ValueBindingContext context)
{
var message = (BasicDeliverEventArgs)value;
IReadOnlyDictionary<string, object> bindingData = CreateBindingData(message);
return Task.FromResult<ITriggerData>(new TriggerData(new BasicDeliverEventArgsValueProvider(message, this.parameterType), bindingData));
}
public Task<IListener> CreateListenerAsync(ListenerFactoryContext context)
{
_ = context ?? throw new ArgumentNullException(nameof(context), "Missing listener context");
return Task.FromResult<IListener>(new RabbitMQListener(
this.service.Model,
context.Executor,
this.logger,
context.Descriptor.Id,
this.queueName,
this.prefetchCount,
this.drainModeManager));
}
public ParameterDescriptor ToParameterDescriptor()
{
return new RabbitMQTriggerParameterDescriptor
{
QueueName = this.queueName,
};
}
internal static IReadOnlyDictionary<string, Type> CreateBindingDataContract()
{
var contract = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase)
{
["ConsumerTag"] = typeof(string),
["DeliveryTag"] = typeof(ulong),
["Redelivered"] = typeof(bool),
["Exchange"] = typeof(string),
["RoutingKey"] = typeof(string),
["BasicProperties"] = typeof(IBasicProperties),
["Body"] = typeof(ReadOnlyMemory<byte>),
};
return contract;
}
internal static IReadOnlyDictionary<string, object> CreateBindingData(BasicDeliverEventArgs value)
{
var bindingData = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
SafeAddValue(() => bindingData.Add(nameof(value.ConsumerTag), value.ConsumerTag));
SafeAddValue(() => bindingData.Add(nameof(value.DeliveryTag), value.DeliveryTag));
SafeAddValue(() => bindingData.Add(nameof(value.Redelivered), value.Redelivered));
SafeAddValue(() => bindingData.Add(nameof(value.Exchange), value.Exchange));
SafeAddValue(() => bindingData.Add(nameof(value.RoutingKey), value.RoutingKey));
SafeAddValue(() => bindingData.Add(nameof(value.BasicProperties), value.BasicProperties));
SafeAddValue(() => bindingData.Add(nameof(value.Body), value.Body));
return bindingData;
}
private static void SafeAddValue(Action addValue)
{
try
{
addValue();
}
catch (ArgumentException)
{
// some message property getters can throw, based on the
// state of the message
}
}
}