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.
Related
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
I'm trying to build a Dialog using the Microsoft Bot Framework which helps users consult purchase order status (currently, just a mock). I am using a LuisDialog which, when it detects the "ConsultPO" intent, it's supposed to ask for the user's 'customer id' and wait a follow up message from the user. However, it keeps going back to the start of the Luis Dialog and processing the intent instead of resuming from the waited method. This is the intent's code, which runs correctly:
[LuisIntent("ConsultPO")]
public async Task POIntent(IDialogContext context, LuisResult result)
{
string PO = "";
foreach (var entity in result.Entities)
{
if (entity.Type == "purchaseOrder")
PO = entity.Entity;
}
if (PO.Length != 0)
{
po_query = PO;
}
await context.PostAsync("Ok, can you confirm your customer id and I'll check for you?");
context.Wait(confirmCustomer_getPO);
}
This is the code I would expect to be executed after the user responds with a follow up message:
public async Task confirmCustomer_getPO(IDialogContext context, IAwaitable<object> argument)
{
await context.PostAsync("DEBUG TEST");
IMessageActivity activity = (IMessageActivity)await argument;
customer_query = activity.Text;
if (po_query.Length > 0)
{
PurchaseOrder po = POservice.findPO(po_query, customer_query);
await buildSendResponse(po, context);
//more non relevant code
When I answer to the bot's inquiry after context.Wait(confirmCustomer_getPO) is executed, it just goes into LUIS then runs the code respective to "None" intent. The message "DEBUG TEST" is never sent.
Why is "confirmCustomer_getPO" never getting called?
EDIT:
I added a debug message in the StartAsync method. I'm not sure whether this is supposed to happen but it pops up every time I send a message to the bot, which makes me believe the Dialog is simply restarting every time I message the bot:
public class EchoDialog : LuisDialog<object>
{
public EchoDialog() : base(new LuisService(new LuisModelAttribute(
ConfigurationManager.AppSettings["LuisAppId"],
ConfigurationManager.AppSettings["LuisAPIKey"],
domain: ConfigurationManager.AppSettings["LuisAPIHostName"])))
{
}
public override Task StartAsync(IDialogContext context)
{
context.PostAsync("I'm in startAsync");
return base.StartAsync(context);
}
Local debugging shows no exceptions are occurring and that any breakpoint in the waited method is never reached, although the context.Wait call does happen.
I figured out the issue myself after fighting with it for a while. The issue was with the bot store. I was using an InMemoryDataStore which was not working - switching to TableBotDataStore fixed the problem. The issue with the DataStore meant that states weren't being saved so my "waits" and "forwards" were not being saved into the dialog stack - any new incoming message was sent to the RootDialog.
Broken - not working while this was in global.asax.cs:
Conversation.UpdateContainer(
builder =>
{
builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));
var store = new InMemoryDataStore(); // volatile in-memory store
builder.Register(c => store)
.Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
.AsSelf()
.SingleInstance();
});
GlobalConfiguration.Configure(WebApiConfig.Register);
As soon as I updated store to:
var store = new TableBotDataStore(ConfigurationManager.AppSettings["AzureWebJobsStorage"]);
Having a valid "AzureWebJobsStorage" setting in web.config from my application settings in Azure, the problem was fixed without any other changes in the code.
I'd like to have items added to a service bus topic, then pulled off the 'Live' subscription and sent to the live site, and pulled off the 'Development' subscription and sent to the dev site.
[FunctionName("AddFoo")]
public static async Task AddFooAsync(
[ServiceBusTrigger("topic-foo", "Live")]QueueItem item,
TraceWriter log)
{
var endpoint = ConfigurationManager.AppSettings["EndPoint"];
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("PublisherKey", foo.PublisherKey);
var foos = new HttpFooStore(httpClient, endpoint);
try
{
await foos.AddAsync(item.Value);
}
catch (BadRequestException)
{
log.Warning("Malformed request was rejected by XXX", item.PublisherName);
return;
}
catch (AuthorizationException)
{
log.Warning("Unauthorized request was rejected by XXX", item.PublisherName);
return;
}
catch (ResourceNotFoundException)
{
log.Warning("Request for unknown tracker was rejected by XXX", item.PublisherName);
return;
}
catch (Exception e)
{
log.Error("Request to XXX was unsuccessful", e, item.PublisherName);
throw e;
}
}
The implementation of the function is exactly the same, the only thing that is different is the name of the subscription, and the endpoint used. Unfortunately, the subscription name is part of an annotation, so it has to be a constant. Is there any way I can get the desired effect without having to duplicate all the code?
Edit
To clarify, I want to create two separate deployments - one for live, and one for development. For each deployment, I would update the environment settings, which would determine which subscription the function is bound to.
You can refer to environment variables by surrounding them in percentage signs:
ServiceBusTrigger("%myTopic%", "%mySubscription%")
Where myTopic and mySubscription are environment variables in the app settings.
You can't have a single function triggered by two service bus topics (development vs. live), but you can move the meat of your function into a helper method that can be called from both functions.
I've been trying to swap over my code from the 0.9.6 Discord.NET API to the new 1.0.1 API, and it's basically calling for a complete restructure to my code. But I've been having some trouble actually getting the bot up and running first of all.
I set up the code body according to the guide linked here
And while it runs without error, the bot itself is not appearing online in my server.
And before you ask, I had in fact replaced "Bot token here" with the actual bot token.
namespace DiscordBot{
public class Program
{
private CommandService commands;
private DiscordSocketClient client;
private IServiceProvider services;
static void Main(string[] args) => new Program().Start().GetAwaiter().GetResult();
public async Task Start()
{
client = new DiscordSocketClient();
commands = new CommandService();
string token = "<token>";
services = new ServiceCollection()
.BuildServiceProvider();
await InstallCommands();
await client.LoginAsync(TokenType.Bot, token);
await client.StartAsync();
await Task.Delay(-1);
}
public async Task InstallCommands()
{
// Hook the MessageReceived Event into our Command Handler
client.MessageReceived += HandleCommand;
// Discover all of the commands in this assembly and load them.
await commands.AddModulesAsync(Assembly.GetEntryAssembly());
}
public async Task HandleCommand(SocketMessage messageParam)
{
// Don't process the command if it was a System Message
var message = messageParam as SocketUserMessage;
if (message == null) return;
// Create a number to track where the prefix ends and the command begins
int argPos = 0;
// Determine if the message is a command, based on if it starts with '!' or a mention prefix
if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))) return;
// Create a Command Context
var context = new CommandContext(client, message);
// Execute the command. (result does not indicate a return value,
// rather an object stating if the command executed successfully)
var result = await commands.ExecuteAsync(context, argPos, services);
if (!result.IsSuccess)
await context.Channel.SendMessageAsync(result.ErrorReason);
}
}
}
And then for the MyBot.cs class
namespace DiscordBot
{
class MyBot : ModuleBase
{
private CommandService _service;
public MyBot(CommandService service)
{
_service = service;
}
}
}
The first thing you might want to do is add some logging to your bot.
As your code might be correct, but discord could be rejecting your connection for any amount of reason.
After await client.StartAsync(); add
client.Log += (msg) => {return Console.WriteLine(${msg.ToString()}");};`
This will output the message your receive from your client to the console.
Now you also need to configure which message should be send to this event. This can be done when creating your DiscordClient(). So instead of client = new DiscordSocketClient(); You could use
client = new DiscordSocketClient(
new DiscordSocketConfig()
{
LogLevel = LogSeverity.Verbose
}
);
Verbose should give you all the information you need. However you could also use LogSeverity.Debug instead, which is the highest available logging, and therefore would give you all messages.
Now that you have some feedback in your console, go and see what concrete errors you are having.
Also I would recommend first completing the your first bot part of the linked tutorial, instead of stepping into the commands directly. Once you got this working, you can continue onwards
I've been writing some code that pulls data from an external source. Essentially first it gets a list of the events that relate to today, processes it, then gets a list of events that relate to tomorrow. Depending upon how many events there are in a given day the processing can take a number of hours. Here is the problem:
If I run ScrapeToday() and ScrapeTomorrow() immediately after one another without the processing everything is gravy. However, as in the normal program flow, if there is a large gap between the operations I catch the following error;
The request was aborted: Could not create SSL/TLS secure channel.
My first instinct is that this must be due to a bug in HttpClient, likely something expiring due to the long duration between requests. However as a new client is created for each request I wouldn't've thought it possible. I've done some digging around on SO and some other sites but have not been able to reach the root of the problem - any help would be appreciated!
Code below.
public static async Task<Dictionary<string, Calendar.Event>> ScrapeToday()
{
try
{
var client = new HttpClient();
WriteLine("Requesting today's calendar...");
var json = await client.GetStringAsync(calendarTodayUrl);
var results = JsonConvert.DeserializeObject<Dictionary<string, Calendar.Event>>(json);
return results;
}
catch (Exception e)
{
Scraper.Instance.WriteLine("Error retrieving today's calendar: " + e);
return new Dictionary<string, Calendar.Event>();
}
}
public static async Task<Dictionary<string, Calendar.Event>> ScrapeTomorrow()
{
try {
var client = new HttpClient();
WriteLine("Requesting tomorrow's calendar...");
var json = await client.GetStringAsync(calendarTomorrowUrl);
var results = JsonConvert.DeserializeObject<Dictionary<string, Calendar.Event>>(json);
return results;
}
catch (Exception e)
{
Scraper.Instance.WriteLine("Error retrieving tomorrow's calendar: " + e);
return new Dictionary<string, Calendar.Event>();
}
}
Edit: Since posting I have tried making a global httpclient and using that for both requests. That also did not work.
Edit2: The bug is reproduceable with an elapsed time of 30 minutes between the calls.
Edit3: If the call is retried after the failure it always works.