I see the following exception on app start, when using a SendEndpoint on Azure Service Bus. Cannot reproduce the issue on RabbitMQ; cannot reproduce on ASB when using Publish() instead of Send().
Microsoft.Azure.ServiceBus.MessagingEntityNotFoundException: Queue was not found
at Microsoft.Azure.ServiceBus.Management.QueueDescriptionExtensions.ParseFromContent(String xml) in C:\source\azure-service-bus-dotnet\src\Microsoft.Azure.ServiceBus\Management\QueueDescriptionExtensions.cs:69
at Microsoft.Azure.ServiceBus.Management.ManagementClient.GetQueueAsync(String queuePath, CancellationToken cancellationToken) in C:\source\azure-service-bus-dotnet\src\Microsoft.Azure.ServiceBus\Management\ManagementClient.cs:198
Following the stacktrace, queueName it's complaining about in GetQueueAsync() is GaldinsMac_dotnet_bus_dpfoyyr5d1ojub5kbdmqijse8g.
It's a simple console application. Here's my code:
static async Task Main()
{
var bus = Bus.Factory.CreateUsingAzureServiceBus(sbc =>
{
sbc.RequiresSession = false; // doesn't seem to help
var host = sbc.Host(
"Endpoint=sb://ns.servicebus.windows.net/;SharedAccessKeyName=localtesting;SharedAccessKey=key",
_ => { });
});
try
{
await bus.StartAsync();
// the exception is thrown here, but I can still continue and ignore the exception
var uri = new Uri(bus.Address, "queueName");
// debugger shows uri to be: sb://ns.servicebus.windows.net/queueName
var endpoint = await bus.GetSendEndpoint(uri);
await endpoint.Send(new SayHiCommand(
name: "Jane Doe"));
}
finally
{
await bus.StopAsync();
}
}
The code works with RabbitMQ but not with ASB, so I'm sure I'm missing something somewhere. Works with ASB if I use Publish<>() instead of Send<>(), but that's not what I want here.
Figured this out last week. The code is fine, like Chris stated in the comments.
Silly typo with the queue name. Which explains why it worked with Publish<>() but not with ISendEndpoint.Send<>(). It worked with RabbitMQ because a consumer with the typo-ed queue-name was running locally.
The exception only occurs when debugging. Something to do with Rider's Debugger and .NET SDK 2.2.300
Related
We have 3 different environments: test, cert and prod. These environments have topics configured using the offset explorer.
The problem is that I can send messages to cert and test, but I can't send to prod until the topic in prod is marked for deletion. As soon as I do this, the messages immediately begin to be sent. I tried to create new topics in test and cert. The problem persists until I put a mark on these topics for deletion, I did not succeed in sending a message.
This problem is happening when i call method ProduceAsync. This method work 5 minutes and finished with error :
Local: Message timed out.
If i use method Produce, the program goes next step but message in topic doesn't exist.
private readonly KafkaDependentProducer<Null, string> _producer;
private string topic;
private ILogger<SmsService> _logger;
public SmsService(KafkaDependentProducer<Null, string> producer, ILogger<SmsService> logger)
{
_producer = producer;
topic = config.GetSection("Kafka:Topic").Value;
_logger = logger;
}
public async Task<Guid?> SendMessage(InputMessageModel sms)
{
var message = new SmsModel(sms.text, sms.type);
var kafkaMessage = new Message<Null, string>();
kafkaMessage.Value = JsonConvert.SerializeObject(message);
try
{
await _producer.ProduceAsync(topic, kafkaMessage);
}
catch (Exception e)
{
Console.WriteLine($"Oops, something went wrong: {e}");
return null;
}
return message.messageId;
Class KafkaDependentProducer i take from official repo example https://github.com/confluentinc/confluent-kafka-dotnet/tree/master/examples/Web
I finded the solution. In my case i needed add "Acks" parameter in ProducerConfig. (Acks = Acks.Leader (equals 1))
Unfortunately the last version of Kafka.Confluent don't write exeption, i had to do version lower. ProduceAsync gave me exeption: Broker: Not enough in-sync replicas, when i just finded answer in internet.
Parameter: min.insync.replicas in problem topic equals 2.
I am writing a webjob using .NET Core 3.1 and my trigger looks like:
public async Task ProcessQueueMessage([ServiceBusTrigger("%ServiceBusProviderConfig:TopicName%", "%ServiceBusProviderConfig:TopicSubscriptionName%", Connection = "ServiceBusConnectionString")] Message message, MessageReceiver messageReceiver, TraceWriter log, TextWriter textWriter)
I am processing the message and calling complete / dead lettering as per the requirement in the following manner:
await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
await messageReceiver.DeadLetterAsync(message.SystemProperties.LockToken);
However, this is throwing the error:
The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue, or was received by a different receiver instance.
I understand that I need to somehow set the Autocomplete in MessageHandlerOptions to false for the webjob to not automatically complete it and remove from the queue.
But I am having difficulty setting this value. I tried:
setting this in the appsettings.json file as follows:
"extensions": {
"serviceBus": {
"messageHandlerOptions": {
"maxConcurrentCalls": 16,
"autoComplete": false
}
}
}
But on running, it is not picking the settings from this file. I am not sure why, how can I make the settings be read from local config file?
I also tried creating an object for MessageHandlerOptions but it the signature is missing a required param which makes it impossible to do this. Eg:
var messageHandlerOptions = new MessageHandlerOptions(ExceptionHandler)
{
AutoComplete = false,
MaxAutoRenewDuration = new TimeSpan(0, 5, 0), // 5 minutes
MaxConcurrentCalls = 1,
};
messageReceiver.RegisterMessageHandler(MessageProcessor, messageHandlerOptions);
static async Task MessageProcessor(Message message, CancellationToken token)
{
await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
}
I am unable to access messageReceiver within MessageProcessor and thats why this is not possible too.
Can anyone please suggest how I can set ServiceBusOptions in a config file to be read at runtime?
FYI, I am using the following packages:
1. Microsoft.Azure.ServiceBus Version="4.1.3"
2. Microsoft.Azure.WebJobs.Extensions Version="3.0.0"
3. Microsoft.Azure.WebJobs.Extensions.ServiceBus Version="3.0.0"
4. Microsoft.Azure.WebJobs.Extensions.Storage Version="4.0.2"
5. Microsoft.Azure.WebJobs.Logging.ApplicationInsights Version="3.0.14"
After a lot of searching, finally found the answer. Posting it for anyone looking for the same question:
services.AddServiceBus(options =>
{
options.ConnectionString = "ServiceBusConnectionString";
options.MessageHandlerOptions.AutoComplete = false;
options.PrefetchCount = 1;
options.MessageHandlerOptions.MaxConcurrentCalls = 1;
});
Last comment on https://github.com/Azure/azure-functions-servicebus-extension/issues/34 helped me to get it configured with host.json
So I've been searching like a mad man after a way to solve this issue, but I can't seem to find an answer.
So, I need to send a POST request with HTTPClient in C# to a server, and if the server isn't running it will keep sending the request until it connects (or dies after a nr of attempts). But I always get the exception System.Net.Http.HttpRequestException, which wouldn't be a problem if I just could store it (or something) and try again.
I found a couple of ways that people tried to do this, and I've tried them all. Creating a for-loop that loops and catches the exception that the program throws, adds to the counter and tries again. Creating a while-loop that loops until the HttpResponseMessage.IsSuccessStatusCode == true. I've even gone to such lengts as restarting the program if it can't connect (yeah, I'm that desperate).
So, I had to see if anyone of you guys might have a solution to this problem, or if you maybe had a better way to solve this problem.
Here is the code im running, thanks for your help!
EDIT: Just to add some clarity, the exception is thrown at the "rep"-variable, and the code never runs further than to that variable. And I've tried to make the HTTPResponseMessage variable just a "var" and await the Postasync method to.
HttpResponseMessage rep = new HttpResponseMessage();
try
{
rep = client.PostAsync("https://localhost:9999/", content).Result;
}
catch (Exception e)
{
}
Task t1 = Task.Factory.StartNew(() => ContinueTrasmission(client, c1.name, c1.state));
You have to look for retry libraries, for example Polly
var policy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(_retryCount, retryAttempt =>
TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
policy.Execute(() => DoSomething());
A solution could be:
bool success = false;
while (!success)
{
var rep = new HttpResponseMessage();
try
{
rep = client.PostAsync("https://localhost:9999/", content).Result;
//No exception here. Check your condition and set success = true if satisfied.
}
catch (Exception e)
{
//Log your exception if needed
}
}
I am using this tutorial in order to connect a xamarin.forms app with easy tables. I cannot add data to the database in Azure as i get
System.InvalidOperationException
The error message is the following
An insert operation on the item is already in the queue.
The exception happends in the following line of code.
await usersTable.InsertAsync(data);
In order to add a user
var user = new User { Username = "username", Password = "password" };
bool x = await AddUser(user);
AddUser
public async Task<bool> AddUser(User user)
{
try
{
await usersTable.InsertAsync(user);
await SyncUsers();
return true;
}
catch (Exception x)
{
await new MessageDialog(x.Message.ToString()).ShowAsync();
return false;
}
}
SyncUsers()
public async Task SyncUsers()
{
await usersTable.PullAsync("users", usersTable.CreateQuery());
await client.SyncContext.PushAsync();
}
where
IMobileServiceSyncTable<User> usersTable;
MobileServiceClient client = new MobileServiceClient("url");
Initialize
var path = Path.Combine(MobileServiceClient.DefaultDatabasePath, "DBNAME.db");
var store = new MobileServiceSQLiteStore(path);
store.DefineTable<User>();
await client.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());
usersTable = client.GetSyncTable<User>();
Please check your table. You probably have added the item already. Also, I would suggest that you don't set the Id property for your entity, because you might be inserting a same ID that's already existing in your table. It's probably the reason why the exception is appearing.
Hope it helps!
Some debugging you can do:
1) Turn on diagnostic logging in the backend and debug the backend: https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter8/developing/#debugging-your-cloud-mobile-backend
2) Add a logging delegating handler in your MobileServiceClient setup: https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter3/server/#turning-on-diagnostic-logs
The MobileServicePushFailedException contains an inner exception that contains the actual error. Normally, it is one of the 409/412 HTTP errors, which indicates a conflict. However, it can also be a 404 (which means there is a mismatch between what your client is asking for and the table name in Easy Tables) or 500 (which means the server crashed, in which case the server-side diagnostic logs indicate why).
Easy Tables is just a Node.js service underneath the covers.
I'm using the C# SDK for Bot Framework to develop a bot and i want my bot send a satisfaction message after a time without activity from the client.
I tried with Task but at first Task are not serializable so i can't store the task to Dispose it if i recieve a new message, and second PrompChoice throw a 'Microsoft.Bot.Builder.Internals.Fibers.InvalidNeedException' with the message : " invalid need: expected Call, have Wait"
I tried to replace my PromptChoice with just a context.sendAsync("Hi"), no exception here but message never be sent to the emulator.
If somebody have an idea on the way to do this, i would be grateful.
EDIT:
i use this sample to do the job:
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
var botData = scope.Resolve<IBotData>();
await botData.LoadAsync(CancellationToken.None);
IDialogTask task = scope.Resolve<IDialogTask>();
//interrupt the stack
var dialog = new InactivityDialog();
task.Call(dialog.Void<object, IMessageActivity>(), null);
//stack.Post<InactivityDialog>(dialog, (c, item) => { return Task.CompletedTask; });
await task.PollAsync(CancellationToken.None);
//flush dialog stack
await botData.FlushAsync(CancellationToken.None);
}
and this in my static messageController:
var builder = new ContainerBuilder();
builder.Register(c => ((ClaimsIdentity)HttpContext.Current.User.Identity).GetCredentialsFromClaims())
.AsSelf()
.InstancePerLifetimeScope();
builder.Update(Conversation.Container);
But the HttpContext.Current is null when it try to resolve IBotData from the scope
That functionality isn't in the bot framework right now. You would have to create your own custom code where you save the conversation information & update your own timer if there's been activity.
https://github.com/Microsoft/BotBuilder/issues/837