public static async Task <IActionResult> PostOrchestrationFunction( // Using /a/p/i route prefix, to let Functions Host distinguish api methods from statics [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "a/p/i/orchestrations('{instanceId}')/{action?}")] HttpRequest req, string instanceId, string action, [DurableClient(TaskHub = "%DFM_HUB_NAME%")] IDurableClient durableClient, ILogger log) { // Checking that the call is authenticated properly try { await Auth.ValidateIdentityAsync(req.HttpContext.User, req.Headers); } catch (Exception ex) { log.LogError(ex, "Failed to authenticate request"); return(new UnauthorizedResult()); } string bodyString = await req.ReadAsStringAsync(); switch (action) { case "purge": await durableClient.PurgeInstanceHistoryAsync(instanceId); break; case "rewind": await durableClient.RewindAsync(instanceId, bodyString); break; case "terminate": await durableClient.TerminateAsync(instanceId, bodyString); break; case "raise-event": dynamic bodyObject = JObject.Parse(bodyString); string eventName = bodyObject.name; JObject eventData = bodyObject.data; await durableClient.RaiseEventAsync(instanceId, eventName, eventData); break; case "set-custom-status": string connectionString = Environment.GetEnvironmentVariable(EnvVariableNames.AzureWebJobsStorage); string hubName = Environment.GetEnvironmentVariable(EnvVariableNames.DFM_HUB_NAME); // Updating the table directly, as there is no other known way var tableClient = CloudStorageAccount.Parse(connectionString).CreateCloudTableClient(); var table = tableClient.GetTableReference($"{hubName}Instances"); var orcEntity = (await table.ExecuteAsync(TableOperation.Retrieve(instanceId, string.Empty))).Result as DynamicTableEntity; if (string.IsNullOrEmpty(bodyString)) { orcEntity.Properties.Remove("CustomStatus"); } else { // Ensuring that it is at least a valid JSON string customStatus = JObject.Parse(bodyString).ToString(); orcEntity.Properties["CustomStatus"] = new EntityProperty(customStatus); } await table.ExecuteAsync(TableOperation.Replace(orcEntity)); break; case "restart": bool restartWithNewInstanceId = ((dynamic)JObject.Parse(bodyString)).restartWithNewInstanceId; await durableClient.RestartAsync(instanceId, restartWithNewInstanceId); break; default: return(new NotFoundResult()); } return(new OkResult()); }
public static async Task <IActionResult> DfmPostOrchestrationFunction( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = Globals.ApiRoutePrefix + "/orchestrations('{instanceId}')/{action?}")] HttpRequest req, string instanceId, string action, [DurableClient(TaskHub = Globals.TaskHubRouteParamName)] IDurableClient durableClient, ILogger log) { // Checking that the call is authenticated properly try { await Auth.ValidateIdentityAsync(req.HttpContext.User, req.Headers, durableClient.TaskHubName); } catch (Exception ex) { log.LogError(ex, "Failed to authenticate request"); return(new UnauthorizedResult()); } // Checking that we're not in ReadOnly mode if (DfmEndpoint.Settings.Mode == DfmMode.ReadOnly) { log.LogError("Endpoint is in ReadOnly mode"); return(new StatusCodeResult(403)); } string bodyString = await req.ReadAsStringAsync(); switch (action) { case "purge": await durableClient.PurgeInstanceHistoryAsync(instanceId); break; case "rewind": await durableClient.RewindAsync(instanceId, bodyString); break; case "terminate": await durableClient.TerminateAsync(instanceId, bodyString); break; case "raise-event": dynamic bodyObject = JObject.Parse(bodyString); string eventName = bodyObject.name; JObject eventData = bodyObject.data; var match = ExpandedOrchestrationStatus.EntityIdRegex.Match(instanceId); // if this looks like an Entity if (match.Success) { // then sending signal var entityId = new EntityId(match.Groups[1].Value, match.Groups[2].Value); await durableClient.SignalEntityAsync(entityId, eventName, eventData); } else { // otherwise raising event await durableClient.RaiseEventAsync(instanceId, eventName, eventData); } break; case "set-custom-status": // Updating the table directly, as there is no other known way var table = TableClient.GetTableClient().GetTableReference($"{durableClient.TaskHubName}Instances"); var orcEntity = (await table.ExecuteAsync(TableOperation.Retrieve(instanceId, string.Empty))).Result as DynamicTableEntity; if (string.IsNullOrEmpty(bodyString)) { orcEntity.Properties.Remove("CustomStatus"); } else { // Ensuring that it is at least a valid JSON string customStatus = JObject.Parse(bodyString).ToString(); orcEntity.Properties["CustomStatus"] = new EntityProperty(customStatus); } await table.ExecuteAsync(TableOperation.Replace(orcEntity)); break; case "restart": bool restartWithNewInstanceId = ((dynamic)JObject.Parse(bodyString)).restartWithNewInstanceId; await durableClient.RestartAsync(instanceId, restartWithNewInstanceId); break; default: return(new NotFoundResult()); } return(new OkResult()); }