How can I get the name of the triggering queue at runtime? - azure

I have a C# WebJob that uses QueueTrigger with a custom INameResolver to look up queue names from the application settings. This part is working as expected, but now within the method body, I need to know the name of the queue from which the triggering message was received. Ideally, I'd like to just be able to add a specially-named string parameter on my method which would be populated with the triggering queue name by the WebJobs SDK, but the documentation doesn't mention any such bindable parameter.
Is there another way to accomplish this, preferrably without hardcoding the queue name/pattern in two locations (i.e. once in the QueueTrigger attribute and again inside the method body) or writing custom string-parsing code to manually invoke my INameResolver for %patterns%?

You could add an additional parameter to your function to bind to the queue like so:
public static void MyFunction(
[QueueTrigger("%name%")] string message,
[Queue("%name%")] CloudQueue queue)
{
string queueName = queue.Name;
}
An alternative is as you suggested - make your custom INameResolver instance available to your job function (e.g. via DI) and just call resolver.Resolve to get the name.

Related

How to schedule a task in Shopware 6

I have created a custom scheduled task. I have registered it as well using the following tutorial:
https://developer.shopware.com/docs/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task#overview
However, in my database, the status of this task is still "queued" instead of "scheduled". This stops the task from executing. How to fix this? I am currently working on localhost.
Status queued means that a message to execute that task was dispatched to the message queue. If the status does not change automatically that indicates that now worker executed the messages from the queue.
By default (for dev setups!) there is a AdminWorker, which will poll and execute messages from the queue as long as the shopware administration is open in a browser. You can also start a worker manually per CLI:
bin/console messenger:consume
You can find more information how to work with the message queue and how to start workers in the official docs.
I had exactly the same problem.
After I had created and registered my task, it was displayed in the database as "queued" and accordingly not executed.
By manually changing it to "scheduled" it was then executed once and set back to "queued".
Of course unusable for productive use.
My error was the following:
In the services.xml I had passed additional parameters for my handler.
Accordingly my handler had a __construct() method.
However, the class inherits from "ScheduledTaskHandler" which in turn also has a constructor and expects the parameter "scheduledTaskRepository".
This repository is used to update the status.
The solution:
inject the service scheduled_task.repository in the services.xml into your custom handler
call in the construct method of the handler: parent::__construct($scheduledTaskRepository);.
In the end it should like this:
<?php declare(strict_types=1);
class myCustomHandler extends ScheduledTaskHandler
{
public function __construct(
EntityRepository $scheduledTaskRepository,
[...]
) {
parent::__construct($scheduledTaskRepository);
[...]
}
public static function getHandledMessages(): iterable
{
return [ MyCustomTask::class ];
}
public function run(): void
{
file_put_contents('test.txt', 'test');
}
}

How to route message to right queue when working with multiple regional Azure Queues

I have an app which is distributed to five regions, US, EU, China, etc.
Requests are routed to the closest worker to the client, however some aspects of the requests must be processed in the specific regions according to some business logic, like if the client is for instance requesting info from the NYSE but are in Europe, most of the work could happen in Europe but some of the work has to happen in the US region.
When that happens I use the right QueueClient for the right region to send a message over there where that sensitive work is processed.
I have a routing client to determine when we need to send those messages to the right region, which works fine. However I find I need to manage multiple queue clients.
Looking for a design pattern that handles this need, because today I'm doing this:
public class MyService : IMyAppService
{
private readonly IMyAppQueueEventClient usQueueClient;
private readonly IMyAppQueueEventClient euQueueClient;
private readonly IMyAppQueueEventClient cnQueueClient;
public MyAppService(IMyAppQueueEventClient USQueueClient,
IMyAppQueueEventClient EUqueueClient;
IMyAppQueueEventClient CNqueueClient;
)
{
this.usQueueClient = USQueueClient;
this.euQueueClient = EUQueueClient;
this.cnQueueClient = CNQueueClient;
}
This feels really clunky. As I add new regions I end up having to update the constructer, which leads to follow on changes to update the tests, etc etc.
Surely there is a way to just read from appSettings and make an array of QueueClients and pass them in, and then just pick the right one.
The way I solved this need was to use the Decorator pattern.
I took the base QueueClient and I added it and a string Region property type to an implementation like so:
public class RegionalQueueClient
public string region;
private QueueClient client;
I added a public Receipt SendMessage() method to this class, which calls the private QueueClient member to pass the message along.
Then I made another type called my SuperQueue which contains a List<RegionalQueueClient> member.
I load them all up using DependencyInjection and it works like a charm, and I'm able to find the right client for the right region using a Linq query as desired.
The records are read from AppSettings as an array, as seen in this answer.

Does Azure Function method name matter?

I am currently developing some C# Azure Functions. The naming convention I use is Process[ThingIWantToProcess]() like so...
public static void ProcessRequest([TimerTrigger("00:00:10", RunOnStartup = true, UseMonitor = false)] TimerInfo timer, ILogger logger)
{
// Do function things
}
A few days ago, all of the functions (currently, 6 of them) stopped running when they were deployed, but no code had been changed that I am aware of or can see.
The console, both locally and the Kudu console, say "Found the following functions:" and display all the expected functions; however, those functions are never run.
I tried all sorts of things, including re-deploys, restarting the Azure Web Job, and changing the contents of the methods, but still nothing fired. And then, I changed the name of the function, and suddenly it started working!
So instead of ProcessRequest it was now ProcessRequest1, and the function fired successfully. I changed the name several different ways, and all of them worked, but when I changed back to ProcessRequest, it stopped working again.
I can't find anything explaining this behavior in the docs or internet search, and I'm concerned it will happen again during future maintenance.
Has anyone else experienced this, and if so, can you point me to some kind of explanation?
Heyy !! This is due to the lock behavior that TimerTrigger employs to ensure that only a single instance of your function is running across scaled out instances. So if you are using the same Storage Account for multiple web job's you will face this issue.
To resolve this issue I would suggest just create separate Storage Account for you Job and it should work as it is !!!
For more information please visit: https://github.com/Azure/azure-webjobs-sdk/issues/614
No, it does not matter.
The FunctionName attribute marks the method as a function entry point. The name must be unique within a project, start with a letter and only contain letters, numbers, _, and -, up to 127 characters in length. Project templates often create a method named Run, but the method name can be any valid C# method name.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-class-library#methods-recognized-as-functions
Seems you are bit confused about is there any azure function naming convention? Okay let's make it more clear.
Azure Functions Are Like C# Method:
As you know Azure functions are like C# method. So it is good to follow C# method naming convention here also.
But azure functions Suggested Pattern like this <name>-func
Example azureexample-func
public static class AzureFunctionExampleClass
{
[FunctionName("azureexample-func")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
//Read Request Body
var content = await new StreamReader(req.Body).ReadToEndAsync();
//Extract Request Body and Parse To Class
Users objUsers = JsonConvert.DeserializeObject<Users>(content);
//As we have to return IAction Type So converting to IAction Class Using OkObjectResult We Even Can Use OkResult
var result = new OkObjectResult(objUsers);
return (IActionResult)result;
}
}
Note: You even can use PascalCase format like AzureExampleFunc. As there is no such strict bindings.
Casing:
Case insensitive
Function Valid Characters: Alphanumeric and hyphen
Function Length:
1-60
Key-Words Should Skip:
Every language has its own defined key-words while name your function its good to omit that name. So that compiler never get confused about that.
Make Function Readable:
Though function doesn't restricts any mandatory naming convention but its recommended to use a readable name so that its be easy to understand what it does.
If you still have any query regarding Azure naming convention you could check this docs
Thank you and happy coding!

Azure Functions - how to obtain invocation ID from within the function?

I am trying to return the invocation ID of an Azure function, similar to WebJob's sending the WebJob run ID back in the HTTP Location header. This is so the invoker of my function can check the status periodically to know when it completes.
I see that I must add this id into the response object, and I surmise I need to retrieve it from some context object in the function. This is because when I visit the Functions UI at https://functionapp.scm.azurewebsites.net/azurejobs/#/functions/invocations/a-long-guid
I see a variable named _context with the invocation id. However, I can't seem to access a variable named context, _context, etc in my function.
You can bind to the ExecutionContext by adding a parameter of that type to your function's method (e.g. Run(..., ExecutionContext context)).
That type exposes an InvocationId property that will give you the information you're looking for.

SignalR Wait for result

Trying to push a message into UI and receive some result to return in synchronous way from web-service.
Method code goes as follows.
[OperationContract]
public string DecypherCaptcha(string captcha)
{
var connection = new HubConnection("http://localhost:51806");
IHubProxy hub = connection.CreateHubProxy("robo");
string decaptcha = null;
hub.On("captchaDecyphered", decyphered =>
{
decaptcha = decyphered;
});
connection.Start().Wait();
hub.Invoke<string>("DecypherCaptcha", new object[] { captcha });
return decaptcha;
}
The issue is that method finishes before value is obtained from hub's captchaDecyphered. However the expression { decaptcha = decyphered; } triggers fine from server after method exits.
Adding ManualResetEvent flag and WaitOne() for it doesn't solve the problem freezing the execution and preventing hub.On("captchaDecyphered" from firing.
Any ideas how to synchronize this?
UPDATE#1 Small notice. Cannot avoid using the intermediate synchronous WCF web-service acting as SignalR client, because of pretty specific robots sitting behind, which are able to interact with outer world only by calling webservices synchronously. Basically in this scenario when robot faces captcha it calls the web-service passing it via SignalR to UI for manual recognition.
UPDATE#2 Thanks to #Ken's inspiring advice got it working by enclosing the connection establishing and hub method invocation into separate 'Thread' followed by waiting with 'ManualResetEvent':
new Thread(() =>
{
connection.Start().Wait();
hub.Invoke<string>("DecypherCaptcha", new object[] { captcha });
}).Start();
sync.WaitOne();
Have previously been trying to start from 'Task' supposing it would run on separate thread implicitly, but with no luck.
You could have the DecypherCaptcha hub method on the SignalR server return the deciphered captcha as a Task<string> instead on invoking captchaDecyphered.
You may want to use a TaskCompletionSource to help you create the appropriate task. Basically you could call tcs.SetResult(deciphered) and return tcs.Task instead of calling Clients.Caller.captchaDecyphered(deciphered).
Then your client-side code code would simply be:
[OperationContract]
public string DecypherCaptcha(string captcha)
{
var connection = new HubConnection("http://localhost:51806");
IHubProxy hub = connection.CreateHubProxy("robo");
connection.Start().Wait();
return hub.Invoke<string>("DecypherCaptcha", captcha).Result;
}
You've got several options.
(1) Spin off the request to the SignalR hub onto a separate thread, probably using the static ThreadPool class, and then add in all the ManualResetEvent stuff. That way it won't block when you're waiting on the SignalR method to return.
(2) Make the DecypherCaptcha method asynchronous. It looks to me like the DecypherCaptcha() is intended to be a WCF method that in turn wraps a SignalR method. If that's the case, forgetting for a moment whether this is a wise approach, you could still call a WCF method on the client when the captchaDecyphered SignalR method completes. But if it's not intended to be a WCF method, then you could have DecypherCaptcha() either (a) return a Task<T>, and only flag the Task to be complete when the captchaDecyphered completes; or (b) pass in a Func<T> as a continuation parameter, and call that when the captchaDecyphered completes.
In general, one of the things that makes asynchronous programming difficult is that except for the very top-level method, you generally need to make every method that calls an asynchronous method itself asynchronous, all the way up and down the stack, either through the Async pattern (nasty), or continuation passing (better) or through a Task object + async/await (probably best). So adding in a single asynchronous method often results in significant changes to your application, all the way through. That's one of the many reasons why the new async and await keywords in .NET 4.5 are so helpful, because they help to encapsulate the necessary changes when you start making your application asynchronous.
You can use the generic Invoke method where you can specify the type of result you expect. With the method you CAN use .Result to wait for the result.
string result = IHubProxy.Invoke<string>("GetString").Result;

Resources