I'm learning how to use Azure Durable Functions and I've come across a problem. I'm posting a message to a queue and waiting for it, then logging it to trace, but I'm not sure where to get the InstanceId from.
Here's what I have so far:
public static class Go
{
private const string ReceivedMessage = "received-message";
[FunctionName(nameof(Go))]
public static async Task Run(
[OrchestrationTrigger] DurableOrchestrationContext context,
TraceWriter log)
{
var message = await context.WaitForExternalEvent<string>(ReceivedMessage);
log.Info($"Received message: {message}");
}
[FunctionName(nameof(GetMessageFromQueue))]
public static async Task GetMessageFromQueue(
[QueueTrigger("messages")] string message,
[OrchestrationClient] DurableOrchestrationClient client)
{
await client.RaiseEventAsync("InstanceId", ReceivedMessage, message); // <- here
}
}
For completeness, here's the rest of the code that I have. The HttpStartSingle
class is in the same project as the one above and the Program
class is just a normal console application that I use to start the context:
public static class HttpStartSingle
{
[FunctionName(nameof(HttpStartSingle))]
public static async Task<HttpResponseMessage> RunSingle(
[HttpTrigger(
AuthorizationLevel.Function,
"get", "post",
Route = "orchestrators/{functionName}")]
HttpRequestMessage req,
[OrchestrationClient] DurableOrchestrationClient starter,
string functionName,
TraceWriter log)
{
var eventData = await req.Content.ReadAsAsync<object>();
var instanceId = await starter.StartNewAsync(functionName, eventData);
return starter.CreateCheckStatusResponse(req, instanceId);
}
}
public class Program
{
public static async Task Main(string[] args)
{
Thread.Sleep(TimeSpan.FromSeconds(5));
var request = WebRequest.Create("http://localhost:7071/api/orchestrators/Go");
request.Timeout = Convert.ToInt32(TimeSpan.FromMinutes(1).TotalSeconds);
request.ContentLength = 0;
request.Method = "POST";
var json = string.Empty;
using (var response = await request.GetResponseAsync())
using (var stream = response.GetResponseStream())
{
if (stream != null)
{
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
if (reader.Peek() > -1)
{
json = await reader.ReadToEndAsync();
}
}
}
}
Console.WriteLine(json);
var storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
var queueuClient = storageAccount.CreateCloudQueueClient();
var queue = queueuClient.GetQueueReference("messages");
await queue.CreateIfNotExistsAsync();
await queue.AddMessageAsync(new CloudQueueMessage("This is a test message"));
Console.ReadKey();
}
}
Update:
The above code is just really a proof of concept to see if Durable Functions meets my requirements. I'm not sure so far, however here is what I'm looking to do:
I will have two queues.
Queue A will be seeded with a small number of A's, which I intend to recycle.
Queue B will have an indeterminate (for all intents and purposes infinite) number of B's pushed to it by an external source.
I want the orchestrator to wait for inputs from both queues, then send A and B to another function which will produce a number of B's. That function will then push the B's to Queue B and then push the A back to Queue A. The process then repeats.
I'd prefer the processing to be parallel based on the number of A's I have. As I see it, I have two options:
A) Create one Orchestrator created with an InstanceId taken from a constant. Then, the functions that listen to the A and B Queues will know what InstanceId to use for the RaiseEventAsync
call.
Problem: Not parallel.
B) Wrap an instanceId in an A. Create one Orchestrator per A. A knows which Orchestrator to use and now each Orchestrator can just listen to Queue B.
Problem: B's don't know what InstanceId to use for the RaiseEventAsync
call.