private async Task StartWorkflowAsync(SigningRequest req, string[] signerEmails) { var model = new WorkflowStartModel { RequestId = req.Id, DocumentName = req.DocumentName, Message = req.Message, SignerEmails = signerEmails, Subject = req.Subject }; string json = JsonSerializer.Serialize(model); var startRequest = new HttpRequestMessage(HttpMethod.Post, _workflowStartUrl) { Content = new StringContent(json, Encoding.UTF8, "application/json") }; HttpResponseMessage startResponse = await _httpClient.SendAsync(startRequest); if (startResponse.StatusCode != System.Net.HttpStatusCode.Accepted) { throw new Exception("Unexpected start response: " + startResponse.StatusCode); } // Update info about the started workflow in DB // Allows us to query status, terminate it etc. DurableFunctionsCheckStatusResponse checkStatusResponse = JsonSerializer.Deserialize <DurableFunctionsCheckStatusResponse>(await startResponse.Content.ReadAsStringAsync()); req.Workflow.Id = checkStatusResponse.Id; req.Workflow.StatusQueryUrl = checkStatusResponse.StatusQueryGetUri; req.Workflow.SendEventUrl = checkStatusResponse.SendEventPostUri; req.Workflow.TerminateUrl = checkStatusResponse.TerminatePostUri; req.Workflow.PurgeHistoryUrl = checkStatusResponse.PurgeHistoryDeleteUri; await _db.SaveChangesAsync(); }
public async Task <HttpResponseMessage> StartSigningWorkflow( [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestMessage req, [DurableClient] IDurableOrchestrationClient starter, ILogger log) { WorkflowStartModel request = await req.Content.ReadAsAsync <WorkflowStartModel>(); string instanceId = await starter.StartNewAsync(nameof(MainOrchestrator), request); log.LogInformation("Started orchestration with ID '{InstanceId}'.", instanceId); return(starter.CreateCheckStatusResponse(req, instanceId)); }
public async Task <SignerResult[]> MainOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { WorkflowStartModel request = context.GetInput <WorkflowStartModel>(); // Database update, has to be done in an activity await context.CallActivityAsync(nameof(MarkWorkflowStarted), request.RequestId); // there is also a variant that supports retries // Prepare email send tasks string[] signerEmails = request.SignerEmails; var emailSendTasks = new List <Task>(signerEmails.Length); for (int i = 0; i < signerEmails.Length; i++) { Task sendTask = context.CallActivityAsync(nameof(SendPleaseSignEmail), new EmailSendParameters { To = signerEmails[i], Subject = request.Subject, Message = request.Message, RequestId = request.RequestId, DocumentName = request.DocumentName }); emailSendTasks.Add(sendTask); } // Fan out to send emails, activities triggered in parallel await Task.WhenAll(emailSendTasks); // Prepare parallel signing tasks var signingTasks = new List <Task <SignerResult> >(signerEmails.Length); for (int i = 0; i < signerEmails.Length; i++) { Task <SignerResult> signingTask = context.CallSubOrchestratorAsync <SignerResult>(nameof(WaitForSignature.WaitForSign), new WaitForSignParameters { SignerEmail = signerEmails[i], RequestId = request.RequestId }); signingTasks.Add(signingTask); } // Wait for result from each signer, another fan out SignerResult[] results = await Task.WhenAll(signingTasks); // Create signed document if everyone signed if (results.All(r => r.Result == SigningDecision.Signed)) { await context.CallActivityAsync(nameof(CreateSignedDocument), new CreateSignedDocumentParameters { RequestId = request.RequestId, Results = results }); } // Send completion email to all signers var completionEmailSendTasks = new List <Task>(signerEmails.Length); for (int i = 0; i < signerEmails.Length; i++) { Task sendTask = context.CallActivityAsync(nameof(SendCompletionEmail), new SendCompletionEmailParameters { RequestId = request.RequestId, To = signerEmails[i], DocumentName = request.DocumentName }); completionEmailSendTasks.Add(sendTask); } // Fan out to send completion emails await Task.WhenAll(completionEmailSendTasks); // Finally, mark the workflow completed in the DB await context.CallActivityAsync(nameof(MarkWorkflowCompleted), request.RequestId); return(results); }