How to check status of queue trigger function programmatically in c#? - c#

I have two azure functions, one is HttpTrigger, one is QueueTrigger. The purpose of the http trigger is to get some data from some service and put it in blob storage. The purpose of queue trigger is to get that data from blob storage and save it in local database. When http trigger finish the job, the queue trigger is triggered automatically.
I am wondering how can I know when the queue function is finished programmatically?
So, I have some service which is calling this http trigger function:
public async Task<HttpResponseMessage> CallHttpAzureFunction(int someParameter)
{
var client = new HttpClient();
var azureFunctionsPath = "someRandomPath";
var url = $"{azureFunctionsPath}/{AzureFunctionConstant.NameOfFunction}";
var request = "not important"
var response await client.PostAsync(url, new StringContent(JsonConvert.SerializeObject(request)));
if (response.Result.IsSuccessStatusCode)
{
//Check the status of queue function, if it is finished, call the database to get that data
}
}

Currently, you can't get the status of the azure function but if it is a durable function you can redirect the client to a status endpoint that the client polls to learn when the operation is finished.
REFERENCES:
How to check the status of a Function
Durable Functions Overview
How to check running status and stop Durable function

Related

How to handle CancellationToken in Azure function eventhub trigger

In an Azure function event hub trigger (v3) it takes in a cancellation token in the Run method. When cancellation is signaled it means the server it shutting down. If I send this token to for example a Get operation using httpClient it will throw a TaskCanceledException and the function will end.
Will the events that this function was processing be sent to another instance of the function on another server or are they lost? Should cancellation be handle in a different way?
[FunctionName(nameof(MyFunction)), FixedDelayRetry(10, "00:00:15")]
public async Task RunAsync(
[EventHubTrigger("%InEventHubName%",
Connection = "InEventHubConnectionString",
ConsumerGroup = "%ConsumerGroup%")]
EventData[] events,
PartitionContext partitionContext,
CancellationToken cancellationToken)
{
foreach (var ev in events)
{
var response = await _httpClient.GetAsync("http://example.com/fetch?key=" + ev.Properties["Key"],
cancellationToken);
await Process(response, cancellationToken);
}
}
Will the events that this function was processing be sent to another instance of the function on another server or are they lost?
They are lost:
Unhandled exceptions may cause you to lose messages. Executions that result in an exception will continue to progress the pointer.
Should cancellation be handle in a different way?
You could choose to ignore cancellation. That may be best for this kind of situation.

Is it possible for HTTP server to receive requests out of order even if they are sent sequentially?

(This discussion might not be specific to C#...)
I have a C# method SendMultipleRequests that sends HTTP POST request 10 times sequentially.
Is it possible for the server to receive requests out of order?
If my understanding is correct if the requests are sent concurrently (without await), the server could receive requests out of order, but in the example below it needs to wait for the response to be received at the client before sending next request, so the server will receive requests in order.
public async Task SendRequest(int i)
{
// definition of endpoint is omitted in this example
var content = new StringContent($"I am {i}-th request");
await HttpClient.PostAsync(endpoint, content);
}
public async Task SendMultipleRequests()
{
for (int i = 0; i < 10; i++)
{
await SendRequest(i);
}
}
with await your app will wait for the task returned by PostAsync to finish before it issues the next request - see the docs for postasync where it says “This operation will not block. The returned Task<TResult> object will complete after the whole response (including content) is read.” - using await will mean that you will only issue the next request after you I’ve read the content of the previous response
If you remove the await then your code will queue up ten tasks and start working on them all in some undefined order. The server will see requests in an unspecified order. This may be further exacerbated by the fact that the requests may take different routes through the internet, some slower. If you remove the await then you should capture the returned task into a list, then you can use something like await Task.WhenAll(list) to wait for them all to complete (unless you really want to fire and forget in which case you can assign them to the discard _ = client.PostAsync... but keeping the task allows you to discover and deal with exceptions that arose)

Asynchronous event execution using websockets

I have windows application that communicates to server via websockets, I use meteor server as server
and websockets4net for communication in client. when send some messages to server(json format).
server will respond to websocket in different order. I can keep track of messages sent to server.
In c# can we have produce consumer pattern, where I can store messageid and callback in dictionary
and execute callback when response recieved.
//<int, Action>(<messageid,Callback delegate>)
ConcurrentDictionary<int, Action> serverResponseCollection = new ConcurrentDictionary<int, Action>();
public send(JObject message,Action Callback)
{
socket.Send(message);
serverResponseCollection.Add(message.id,Callback);
}
void socket_MessageReceived(object sender, MessageReceivedEventArgs e)
{
//server response contains message id
//get callback function and execute
var callbackObj = serverResponseCollection[e.id];
Callback();
}
You can add a field called "Method" to the json object and set its value to the name of operation you are performing while creating a request message.
message.Add("Method", "GetUser");
The serve will also add "Method" field in the response with the same value the client has sent in the request.
And then in your response handler you can parse the value of Method field to know which operation you need to perform. And you will also get rid from mapping the message ids with callbacks.

How can I send an AWS SQS message with C# with a custom timeout?

Here's my basic code to send an SQS message from C# using the AWS .NET SDK. How can I give the message a different timeout other than the queue default?
public async Task PostMessage(Uri queueUrl, string body)
{
var request = new SendMessageRequest()
{
MessageBody = body,
QueueUrl = queueUrl.ToString(),
};
var result = await this.client.SendMessageAsync(request);
}
I can send a separate API call to extend the timeout of an in-flight message. But I'd like to do this at the time of creation if that's practical to do.
You can't do it with C# API or with any other API. Message visibility timeout is set globally on a queue.
I would suggest to create 2 queues. One for short tasks and one for long tasks. This way you can set different visibility timeouts on the queues.

Web API allow only single async task

What is a proper scenario for handling only single async action? For example I need to import large file and while it being imported I need to disable that option to ensure that second import not triggered.
What comes in mind that:
[HttpPost]
public async Task<HttpResponseMessage> ImportConfigurationData()
{
if (HttpContext.Current.Application["ImportConfigurationDataInProcess"] as bool? ?? false)
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Task still running");
HttpContext.Current.Application["ImportConfigurationDataInProcess"] = true;
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
await Request.Content.ReadAsMultipartAsync(provider);
//actual import
HttpContext.Current.Application["ImportConfigurationDataInProcess"] = false;
Request.CreateResponse(HttpStatusCode.OK, true)
}
But it seems like very hard-coded solution. What is a proper way of handling that?
Another thing it is not properly works on client side at it still waits for a response. So is it possible for user just to send that file to server and not wait unlit it will finishes but reload page after file sent to server without waiting while await stuff will finish.
async does not change the HTTP protocol (as I explain on my blog). So you still just get one response per request.
The proper solution is to save a "token" (and import data) for the work in some reliable storage (e.g., Azure table/queue), and have a separate processing backend that does the actual import.
The ImportConfigurationData action would then check whether a token already exists for that data, and fault the request if found.

Categories