Azure Function RabbitMq trigger stops receiving messages - c#

I have Azure Function with RabbitMq trigger and it stops receiving any messages after certain time. The function is deployed in Azure. When I stop and then start again the function, it starts pulling messages again, but after a while it stops. When I run it locally on my machine the problem never occurs. My code looks like this:
[FunctionName(nameof(Bets))]
public async Task Bets([RabbitMQTrigger(nameof(Bets), ConnectionStringSetting = "RabbitConnection")] BasicDeliverEventArgs args,
[RabbitMQ(ConnectionStringSetting = "RabbitConnection")] IModel client, ILogger log)
{
var myQueueItem = Encoding.UTF8.GetString(args.Body);
var logEntry = new Log()
{
date = DateTime.UtcNow,
status = SuccessStatus,
input = myQueueItem,
queue = nameof(Bets)
};
try
{
var input = JsonConvert.DeserializeObject<Bet[]>(myQueueItem);
await _context.BulkInsertOrUpdateAsync(input);
log.LogInformation($"Finished input save: {myQueueItem}");
}
catch (Exception e)
{
client.BasicNack(args.DeliveryTag, false, true);
logEntry.status = "Error";
logEntry.error = e.Message;
log.LogError(e, e.Message, myQueueItem);
}
await _context.logs.AddAsync(logEntry);
await _context.SaveChangesAsync();
}

Related

mqtt publisher not working in xamarin ios

i'm trying to make an android / ios app that publishes mqtt messages to a local server i'm using MQTTNET.
The Android version is working fine but when i try to run it on the ios one it just dosen't work
public async Task connect(string channel,string message)
{
try
{
var mqttFactory = new MqttFactory();
IMqttClient client = mqttFactory.CreateMqttClient();
var options = new MqttClientOptionsBuilder().WithClientId(Guid.NewGuid()
.ToString()).WithTcpServer("192.168.1.68").WithCleanSession().Build();
client.UseConnectedHandler(e =>
{
Console.WriteLine("connected to the server");
client.SubscribeAsync(new TopicFilterBuilder().WithTopic(channel).Build());
});
client.UseDisconnectedHandler(e =>
{
Console.WriteLine("disconnected to the server");
});
await client.ConnectAsync(options);
await PublishMessageAsync(client, message, channel);
await client.DisconnectAsync();
}catch (Exception ex)
{
var o = ex.Message.ToString();
}
}
static async Task PublishMessageAsync(IMqttClient client,string payload,string topic)
{
string messagePayload = payload;
var message = new MqttApplicationMessageBuilder().WithTopic(topic)
.WithPayload(messagePayload)
.WithAtLeastOnceQoS().Build();
if (client.IsConnected)
{
await client.PublishAsync(message);
}
}
No error is shown, the debugger stops at client.connectAsync().

Kafka consume message and then produce to another topic

I have to consume from a Kafka topic, get the message and do some json clean and filter job, then I need to produce the new message to another Kafka topic, my code is like this:
public static YamlMappingNode configs;
public static void Main(string[] args)
{
using (var reader = new StreamReader(Path.Combine(Directory.GetCurrentDirectory(), ".gitlab-ci.yml")))
{
var yaml = new YamlStream();
yaml.Load(reader);
//find variables
configs = (YamlMappingNode)yaml.Documents[0].RootNode;
configs = (YamlMappingNode)configs.Children.Where(k => k.Key.ToString() == "variables")?.FirstOrDefault().Value;
}
CancellationTokenSource cts = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) => {
e.Cancel = true; // prevent the process from terminating.
cts.Cancel();
};
Run_ManualAssign(configs, cts.Token);
}
public static async void Run_ManualAssign(YamlMappingNode configs, CancellationToken cancellationToken)
{
var brokerList = configs.Where(k => k.Key.ToString() == "kfk_broker")?.FirstOrDefault().Value.ToString();
var topics = configs.Where(k => k.Key.ToString() == "input_kfk_topic")?.FirstOrDefault().Value.ToString();
var config = new ConsumerConfig
{
// the group.id property must be specified when creating a consumer, even
// if you do not intend to use any consumer group functionality.
GroupId = new Guid().ToString(),
BootstrapServers = brokerList,
// partition offsets can be committed to a group even by consumers not
// subscribed to the group. in this example, auto commit is disabled
// to prevent this from occurring.
EnableAutoCommit = true
};
using (var consumer =
new ConsumerBuilder<Ignore, string>(config)
.SetErrorHandler((_, e) => Console.WriteLine($"Error: {e.Reason}"))
.Build())
{
//consumer.Assign(topics.Select(topic => new TopicPartitionOffset(topic, 0, Offset.Beginning)).ToList());
consumer.Assign(new TopicPartitionOffset(topics, 0, Offset.End));
//var producer = new ProducerBuilder<Null, string>(config).Build();
try
{
while (true)
{
try
{
var consumeResult = consumer.Consume(cancellationToken);
/// Note: End of partition notification has not been enabled, so
/// it is guaranteed that the ConsumeResult instance corresponds
/// to a Message, and not a PartitionEOF event.
//filter message
var result = ReadMessage(configs, consumeResult.Message.Value);
//send to kafka topic
await Run_ProducerAsync(configs, result);
}
catch (ConsumeException e)
{
Console.WriteLine($"Consume error: {e.Error.Reason}");
}
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Closing consumer.");
consumer.Close();
}
}
}
#endregion
#region Run_Producer
public static async Task Run_ProducerAsync(YamlMappingNode configs, string message)
{
var brokerList = configs.Where(k => k.Key.ToString() == "kfk_broker")?.FirstOrDefault().Value.ToString();
var topicName = configs.Where(k => k.Key.ToString() == "target_kafka_topic")?.FirstOrDefault().Value.ToString();
var config = new ProducerConfig {
BootstrapServers = brokerList,
};
using (var producer = new ProducerBuilder<Null, string>(config).Build())
{
try
{
/// Note: Awaiting the asynchronous produce request below prevents flow of execution
/// from proceeding until the acknowledgement from the broker is received (at the
/// expense of low throughput).
var deliveryReport = await producer.ProduceAsync(topicName, new Message<Null, string> { Value = message });
producer.Flush(TimeSpan.FromSeconds(10));
Console.WriteLine($"delivered to: {deliveryReport.TopicPartitionOffset}");
}
catch (ProduceException<string, string> e)
{
Console.WriteLine($"failed to deliver message: {e.Message} [{e.Error.Code}]");
}
}
}
#endregion
Am I doing something wrong here? The program existed immediately when executing var deliveryReport = await producer.ProduceAsync(topicName, new Message<Null, string> { Value = message });, no error message, no error code.
In the meanwhile I used Python and config the same for Producer, it works well.
Run_ManualAssign(configs, cts.Token);
For this line in the Main function, you are calling async without await in a sync function. Thus the program exit immediately after this invoke started (not finished as it is async)
You could have 2 options
Use async Main function and add await in front of this invoke.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-7.1/async-main
If you really want to call async function in sync function
Run_ManualAssign(configs, ts.Token).ConfigureAwait(false).GetAwaiter().GetResult();
I solved this problem but I don't know why actually. I opened an issue here.

Messages are not getting delayed in Botframework

I'm posting two messages back to the user as a reply as below,
static Timer t = new Timer(new TimerCallback(TimerEvent));
static Timer t1 = new Timer(new TimerCallback(TimerEventInActivity));
static int timeOut = Convert.ToInt32(ConfigurationManager.AppSettings["disableEndConversationTimer"]); //3600000
public static void CallTimer(int due) {
t.Change(due, Timeout.Infinite);
}
public static void CallTimerInActivity(int due) {
t1.Change(due, Timeout.Infinite);
}
public async static Task PostAsyncWithDelay(this IDialogContext ob, string text) {
try {
var message = ob.MakeMessage();
message.Type = Microsoft.Bot.Connector.ActivityTypes.Message;
message.Text = text;
await PostAsyncWithDelay(ob, message);
CallTimer(300000);
if ("true".Equals(ConfigurationManager.AppSettings["disableEndConversation"])) {
CallTimerInActivity(timeOut);
}
} catch (Exception ex) {
Trace.TraceInformation(ex.Message);
}
}
await context.PostAsyncWithDelay("Great!");
await context.PostAsyncWithDelay("I can help you with that.");
But, there is no delay between them when received. Both messages are received in one go.
How can I delay the second message with some time?
In Root Dialog
To delay your message you can use Task.Delay method. Change your PostAsyncWithDelay as:
public async static Task PostAsyncWithDelay(IDialogContext context, string text)
{
await Task.Delay(4000).ContinueWith(t =>
{
var message = context.MakeMessage();
message.Text = text;
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
var client = scope.Resolve<IConnectorClient>();
client.Conversations.ReplyToActivityAsync((Activity)message);
}
});
}
You can call PostAsyncWithDelay method when you want to delay a message, otherwise use context.PostAsync method to send your messages.
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
//Sending a message nomally
await context.PostAsync("Hi");
//Notify the user that the bot is typing
var typing = context.MakeMessage();
typing.Type = ActivityTypes.Typing;
await context.PostAsync(typing);
//The message you want to delay.
//NOTE: Do not use context.PostAsyncWithDelay instead simply call the method.
await PostAsyncWithDelay(context, "2nd Hi");
}
OUTPUT
How can I delay the second message with some time?
If you’d like to delay sending the second message, you can try the following code snippet:
await context.PostAsync($"You sent {activity.Text} at {DateTime.Now}");
Task.Delay(5000).ContinueWith(t =>
{
using (var scope = Microsoft.Bot.Builder.Dialogs.Internals.DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
var client = scope.Resolve<IConnectorClient>();
Activity reply = activity.CreateReply($"I can help you with that..");
client.Conversations.ReplyToActivityAsync(reply);
}
});
context.Wait(MessageReceivedAsync);
Besides, as others mentioned in comments, the method PostAsyncWithDelay seems not a built-in method in Bot Builder SDK. If you try to achieve the requirement and defined that custom method, you can post the code of that method.
To make all replies delay, you may insert this directly in the controller.
if (activity.Type == ActivityTypes.Message)
{
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity isTypingReply = activity.CreateReply();
isTypingReply.Type = ActivityTypes.Typing;
await connector.Conversations.ReplyToActivityAsync(isTypingReply);
var message = isTypingReply;
await Task.Delay(4000).ContinueWith(t =>
{
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
}
});
await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
}

MessagingEntityNotFoundException: The messaging entity 'ihsuprodsgres029dednamespace:eventhub:' could not be found

I am just trying to connect my device to cloud using Azure IOT Hub. But I am getting an error as below.
MessagingEntityNotFoundException: The messaging entity 'ihsuprodsgres029dednamespace:eventhub:iothub-ehub-' could not be found. TrackingId:4772b610-8ff3-4709-8ea9-ffcd5784fe1c_B4, SystemTracker:ihsuprodsgres029dednamespace:eventhub:iothub-ehub-sibeeshiot-176205-a588b66686~16383|team01, Timestamp:6/23/2017 3:07:54 PM TrackingId:41110b704d814af497fd9924da6714d8_G4, SystemTracker:gateway2, Timestamp:6/23/2017 3:07:55 PM, referenceId: 41110b704d814af497fd9924da6714d8_G4
Can you please help me with it, if you have ever faced the same issue. Below is the code I am trying.
static void Main(string[] args) {
Console.WriteLine("Receive messages. Ctrl-C to exit.\n");
eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, iotHubD2cEndpoint);
var d2cPartitions = eventHubClient.GetRuntimeInformation().PartitionIds;
CancellationTokenSource cts = new CancellationTokenSource();
System.Console.CancelKeyPress += (s, e) = >{
e.Cancel = true;
cts.Cancel();
Console.WriteLine("Exiting...");
};
var tasks = new List < Task > ();
foreach(string partition in d2cPartitions) {
tasks.Add(ReceiveMessagesFromDeviceAsync(partition, cts.Token));
}
Task.WaitAll(tasks.ToArray());
}
private static async Task ReceiveMessagesFromDeviceAsync(string partition, CancellationToken ct) {
var eventHubReceiver = eventHubClient.GetConsumerGroup("Team01").CreateReceiver(partition, DateTime.UtcNow);
while (true) {
if (ct.IsCancellationRequested) break;
EventData eventData = await eventHubReceiver.ReceiveAsync();
if (eventData == null) continue;
string data = Encoding.UTF8.GetString(eventData.GetBytes());
Console.WriteLine("Message received. Partition: {0} Data: '{1}'", partition, data);
}
}
It looks like your iotHubD2cEndpoint value is not correct Event Hub-compatible name (probably you are using the messages/events such as an Azure IoT Hub Endpoint).
The following screen snippet shows the Event Hub compatible endpoint for Events:
The other option is to use an Azure IoT Hub Connection string and Endpoint Events, see the following example:
iotHubD2cEndpoint = "messages/events"
connectionString = "HostName=*****.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=******"

Azure: How to Delete "DeadLettered" Messages from Service Bus queue

I would like to delete the Dead Lettered messages from the service bus queue. In particular, this value is called DeadLetterMessageCount and you can find out this by right-clicking the "Properties" of the SB queue in the Server Explorer of your project (in case of using a SB queue).
The reason I would like to do this is because I've set up an Autoscale of the cloud service. So, when the SB queue is quite big, it adds some more cores in order to proceed the messages faster (it enables more worker roles). I realized that when you set up the scaling depending on the number of messages in the queue, it counts the DeadLettered messages as well (messages that cannot be consumed).
So that's a waste of money, as more instances are enabled that are not needed.
Any queries, please let me know.
Thanks for your help
You read and delete messages from dead letter queue the same way you read from normal queues or subscriptions.
You can use this method to get the path of the queue: QueueClient.FormatDeadLetterPath(queuePath).
Also see this previous answer: How do I delete a DeadLetter message on an Azure Service Bus Topic
This is a code to delete a Dead-Letter messages from Queues.
public async void DeleteMessagesFromQueueAsync()
{
bool isDeadLetter=true;
long SequenceNumber = 12;
string queuePath='queue name';
string connectionString='connection string of ASB Namespace';
BrokeredMessage _srcMessage = null;
DeleteMessageResponse _msgDeletionStatus = new DeleteMessageResponse();
MessageReceiver fromQueueClient = null;
try
{
MessagingFactory factory = MessagingFactory.CreateFromConnectionString(connectionString);
string _fromEntityPath = !isDeadLetter ? queuePath : QueueClient.FormatDeadLetterPath(queuePath);
fromQueueClient = await factory.CreateMessageReceiverAsync(_fromEntityPath, ReceiveMode.PeekLock);
BrokeredMessage _message = await fromQueueClient.ReceiveAsync(SequenceNumber);
if (_message != null)
_srcMessage= _message;
if (_srcMessage != null )
{
await _srcMessage.CompleteAsync();
}
}
catch (Exception ex)
{
}
finally
{
if (fromQueueClient != null)
await fromQueueClient.CloseAsync();
}
}
You can use 'ReceiveAndDelete' mode and 'ReceiveBatchAsync' to delete quickly from DeadLetterQueue
private async void button1_Click(object sender, EventArgs e)
{
try
{
var DLQPath = "/$DeadLetterQueue"; ///**** Important - Pointing to DLQ'
var topicName = "message";
var sub = "message-subscription";
int batchSize = 100;
runProcess = true;
_subscriptionClient = SubscriptionClient.CreateFromConnectionString(connectionSt, topicName, sub + DLQPath, ReceiveMode.ReceiveAndDelete);
int cnt = 0;
do
{
var messages = await _subscriptionClient.ReceiveBatchAsync(batchSize);
var msgCount = messages.Count();
if (msgCount == 0)
{
break;
}
cnt += msgCount;
labelCount.Text = cnt.ToString();
}
while (runProcess);
_subscriptionClient.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.GetBaseException().Message);
return;
}
}

Categories