public async Task RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var message = context.GetInput <SlackMessage>(); var model = await context.CallActivityAsync <LuisModel>((nameof(Scheduler) + nameof(GetWhen)), message.Text); var httpTask = context.CallHttpAsync( HttpMethod.Post, new Uri(_options.WebHookUrl), JsonConvert.SerializeObject(new SlackMessage() { Text = $"Scheduled task at {model.Time}" }, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() })); var timerTask = context.CreateTimer(model.Time, CancellationToken.None); await Task.WhenAll(httpTask, timerTask); await context.CallHttpAsync( HttpMethod.Post, new Uri(_options.WebHookUrl), JsonConvert.SerializeObject(new SlackMessage() { Text = $"Hey! time to do your task: {model.Task.ToUpper()}" }, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() })); }
public static async Task RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { ResourceInfo vmInfo = context.GetInput <ResourceInfo>(); string apiVersion = vmInfo.ApiVersion ?? "2018-06-01"; string subscriptionId = vmInfo.SubscriptionId; string resourceGroup = vmInfo.ResourceGroup; // Implicitly uses the Azure AD identity of the current app to make an HTTP call to Azure Resource Manager var managedIdentity = new ManagedIdentityTokenSource("https://management.core.windows.net"); // List all of the VMs in my subscription and add them to a list. DurableHttpRequest request = new DurableHttpRequest( HttpMethod.Get, new Uri($"https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Compute/virtualMachines?api-version=2018-06-01"), tokenSource: managedIdentity); DurableHttpResponse response = await context.CallHttpAsync(request); if (response.StatusCode != HttpStatusCode.OK) { throw new ArgumentException($"Failed to list VMs: {response.StatusCode}: {response.Content}"); } // Deserializes content to just get the names of the VMs in the subscription JObject jObject = JsonConvert.DeserializeObject <JObject>(response.Content); var vmNamesList = new List <string>(); foreach (JToken value in jObject["value"]) { string vmName = value["name"].ToString(); vmNamesList.Add(vmName); } // Restart all of the VMs in my subscription foreach (string vmName in vmNamesList) { var restartRequest = new DurableHttpRequest( HttpMethod.Post, new Uri($"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines/{vmName}/restart?api-version={apiVersion}"), tokenSource: managedIdentity); DurableHttpResponse restartResponse = await context.CallHttpAsync(restartRequest); if (restartResponse.StatusCode != HttpStatusCode.OK) { throw new ArgumentException($"Failed to restart VM: {restartResponse.StatusCode}: {restartResponse.Content}"); } } }
public static async Task CheckWebsiteIsAvailable([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { try { Uri jonahsUrl = new Uri("https://jonahandersson.tech"); // Makes an HTTP GET request to the specified endpoint like a url DurableHttpResponse httpResponse = await context.CallHttpAsync(HttpMethod.Get, jonahsUrl); if ((int)httpResponse.StatusCode >= 500 && (int)httpResponse.StatusCode < 600) { throw new HttpRequestException("Hey, there is a server error! Something wrong with your website. Fix it Jonah!"); } else { await context.CallActivityAsync <string>("CheckHttpResponseActivity", httpResponse); log.LogInformation($"Completed: STATUS CODE = {httpResponse.StatusCode}"); log.LogInformation($"Completed: HEADER = {httpResponse.Headers}"); } } catch (Exception ex) { log.LogError($"Error at CheckIfMySiteIsAvailable(): { ex.Message} { ex.InnerException}"); throw; } }
public async Task OpenCircuit( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { if (!context.IsReplaying) { log.LogInformation("Disabling function app to open circuit"); } var resourceId = context.GetInput <string>(); var stopFunctionRequest = new DurableHttpRequest( HttpMethod.Post, new Uri($"https://management.azure.com{resourceId}/stop?api-version=2016-08-01"), tokenSource: new ManagedIdentityTokenSource("https://management.core.windows.net")); var restartResponse = await context.CallHttpAsync(stopFunctionRequest); if (restartResponse.StatusCode != HttpStatusCode.OK) { throw new ArgumentException($"Failed to stop Function App: {restartResponse.StatusCode}: {restartResponse.Content}"); } if (!context.IsReplaying) { log.LogInformation("Function disabled"); } }
public static async Task <string> RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { string endpoint = context.GetInput <object>().ToString(); var request = new DurableHttpRequest(HttpMethod.Get, new Uri(endpoint)); DurableHttpResponse endpointResponse = await context.CallHttpAsync(request); if (endpointResponse.StatusCode != HttpStatusCode.OK) { throw new ArgumentException($"Failed to contact endpoint: {endpointResponse.StatusCode}: {endpointResponse.Content}"); } log.LogInformation($"Information retrieved from endpoint = {endpointResponse.Content}."); string[] words = endpointResponse.Content.Split(" "); log.LogInformation($"Words count = {words.Count()}."); var entityId = new EntityId("OrchestrationSample_Counter", "charCounter"); context.SignalEntity(entityId, "reset"); foreach (string word in words) { context.SignalEntity(entityId, "Add", word); } await context.CallActivityAsync("OrchestrationSample_LogBlob", endpoint.Replace("/", "bar")); int count = await context.CallEntityAsync <int>(entityId, "Get"); return($"Endpoint: {endpoint} has the total of {count} chars"); }
public static async Task <DurableHttpResponse> CallHttpAsyncOrchestrator([OrchestrationTrigger] IDurableOrchestrationContext ctx) { TestDurableHttpRequest testRequest = ctx.GetInput <TestDurableHttpRequest>(); DurableHttpRequest durableHttpRequest = ConvertTestRequestToDurableHttpRequest(testRequest); DurableHttpResponse response = await ctx.CallHttpAsync(durableHttpRequest); return(response); }
public async Task OrderOutForDeliveryOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { log = context.CreateReplaySafeLogger(log); //to prevent logging at the time of function replay Order order = context.GetInput <Order>(); try { order.OrderStatus = OrderStatus.OutForDelivery; await context.CallActivityAsync("UpsertOrder", order); await context.CallActivityAsync("NotifyCustomer", order); Uri uri = new Uri($"{_configuration["HostEndpoint"]}/orders/delivered/{order.Id}"); await context.CallHttpAsync(HttpMethod.Get, uri); using (var cts = new CancellationTokenSource()) { var timeoutAt = context.CurrentUtcDateTime.AddHours(1); var timeoutTask = context.CreateTimer(timeoutAt, cts.Token); var acknowledgeTask = context.WaitForExternalEvent(Constants.DELIVERY_ORDER_DELIVERED_EVENT); var winner = await Task.WhenAny(acknowledgeTask, timeoutTask); if (winner == acknowledgeTask) { order.OrderStatus = OrderStatus.Delivered; await context.CallActivityAsync("UpsertOrder", order); await context.CallActivityAsync("NotifyCustomer", order); cts.Cancel(); } else { //Handle time out logic log.LogError($"OrderOutForDeliveryOrchestrator Timed out {order.Id}"); await context.CallActivityAsync("NotifyCustomer", order); await context.CallActivityAsync("NotifyRestaurant", order); } } } catch (Exception ex) { if (order != null) { ex.LogExceptionDetails(log, order.Id, GetType().FullName); } else { ex.LogExceptionDetails(log, null, GetType().FullName); } } }
public async Task LongRunningFunction([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { log.LogInformation("Starting LongRunningFunction"); await context.CallHttpAsync(HttpMethod.Get, new System.Uri($"{_config.LongRunningJobUrl}/{context.InstanceId}")); await context.WaitForExternalEvent("LongRunningJobDone"); log.LogInformation("LongRunningFunction is done"); }
public static Task <DurableHttpResponse> MakeHttpRequest(string name, string stringUri, string input, IDurableOrchestrationContext context, ILogger log) { var uri = new Uri($"{stringUri}"); if (!context.IsReplaying) { log.LogInformation("Calling {name} with input: {input} at uri: {uri}", name, input, stringUri); } return(context.CallHttpAsync(System.Net.Http.HttpMethod.Post, uri, input)); }
public async Task OrderPlacedOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { log = context.CreateReplaySafeLogger(log); //to prevent logging at the time of function replay Order order = context.GetInput <Order>(); try { await context.CallActivityAsync("UpsertOrder", order); await context.CallActivityAsync("NotifyRestaurant", order); Uri uri = new Uri($"{_configuration["HostEndpoint"]}/orders/accepted/{order.Id}"); await context.CallHttpAsync(HttpMethod.Get, uri); using (var cts = new CancellationTokenSource()) { var timeoutAt = context.CurrentUtcDateTime.AddSeconds(60); var timeoutTask = context.CreateTimer(timeoutAt, cts.Token); var acknowledgeTask = context.WaitForExternalEvent(Constants.RESTAURANT_ORDER_ACCEPT_EVENT); var winner = await Task.WhenAny(acknowledgeTask, timeoutTask); if (winner == acknowledgeTask) { string instanceId = $"{order.Id}-accepted"; context.StartNewOrchestration("OrderAcceptedOrchestrator", order, instanceId); cts.Cancel(); } else { //TODO: Handle time out logic log.LogError($"OrderPlacedOrchestrator Timed out {order.Id}"); await context.CallActivityAsync("NotifyCustomer", order); await context.CallActivityAsync("NotifyRestaurant", order); } } } catch (Exception ex) { if (order != null) { ex.LogExceptionDetails(log, order.Id, GetType().FullName); } else { ex.LogExceptionDetails(log, null, GetType().FullName); } } }
public async Task HealCheckOrchestration( [OrchestrationTrigger] IDurableOrchestrationContext context) { var service = context.GetInput <ServiceInput>(); var entityId = new EntityId(nameof(ServiceAggregator), service.Id); var serviceProxy = context.CreateEntityProxy <IServiceAggregator>(entityId); var httpClientResponse = await context.CallHttpAsync(HttpMethod.Get, new Uri(service.Url)); var status = httpClientResponse.StatusCode == HttpStatusCode.OK ? Status.Closed : Status.Open; await serviceProxy.ChangeState(new StatusCommand(status)); }
public static async Task <string> Orchestrator_CallDurableHttp( [OrchestrationTrigger] IDurableOrchestrationContext context) { DurableHttpResponse response = await context.CallHttpAsync(HttpMethod.Get, _uri); if (response.StatusCode == HttpStatusCode.OK) { return(response.Content); } return("Something went wrong"); }
public async Task RunOrchestratorWithHttpCall( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { // Call Activity Functions as usual. // ... var activityResult = "ResultFromTheActivities"; // Finally call an orchestration in another Function App: var uri = new Uri("https://anotherfunctionapp/start/nextorchestrator"); await context.CallHttpAsync(HttpMethod.Post, uri, activityResult); }
internal static Task <DurableHttpResponse> PostData(IDurableOrchestrationContext context, string url, object body, string authToken) { var authHeaders = new Dictionary <string, StringValues> { ["Authorization"] = new StringValues($"Bearer {authToken}") }; var request = new DurableHttpRequest( HttpMethod.Post, new Uri(url), authHeaders, JsonConvert.SerializeObject(body)); return(context.CallHttpAsync(request)); }
public static async Task <List <string> > RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var outputs = new List <string>(); List <Task> sites = new List <Task>(); var responses = new List <Task <DurableHttpResponse> > { context.CallHttpAsync(HttpMethod.Get, new Uri("https://www.google.com")), context.CallHttpAsync(HttpMethod.Get, new Uri("https://www.amazon.com")), context.CallHttpAsync(HttpMethod.Get, new Uri("https://www.msn.com")) }; await Task.WhenAll(responses.ToArray()); foreach (var item in responses) { outputs.Add($"{item.Result.StatusCode}:{item.Result.Content.Length} bytes"); } return(outputs); }
public async Task Run( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger logger) { var uri = context.GetInput <Uri>(); var response = await context.CallHttpAsync(HttpMethod.Get, uri); if (response.StatusCode != System.Net.HttpStatusCode.OK) { logger.LogError(response.StatusCode.ToString()); } ; }
public async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context) { //todo: when message is received, the function can be scheduled till time T, //e.g. till 3-5 minutes prior to match start, after that it can change it's polling behavior from // 60 days (e.g. time from the match info is parsed) - simply it waits, without being billed till the moment // to 3 every 2 secs while the match is finished and exits. //Multiple sources can be queried from this 1 function, for instance if we've specified them in a message, that scheduled the function. var message = context.GetInput <LiveSyncMessage>(); int pollingInterval = message.PollingIntervalInSec; DateTime expiryTime = message.FinishTime; if (message.StartTime >= context.CurrentUtcDateTime.AddMinutes(1)) { //Orchestration was scheduled, and waits till the start of a match, without billing. var sleepUntil = message.StartTime - context.CurrentUtcDateTime; var nextCheck = context.CurrentUtcDateTime.AddSeconds(sleepUntil.TotalSeconds); await context.CreateTimer(nextCheck, CancellationToken.None); } while (DateTime.UtcNow < expiryTime) { //todo: if match has ended or was cancelled - skip. var source = factory.GetSource(message.ConnectorType); var retriever = source.GetRetriever(message); //todo: currently only all is supported for the demo //todo: can support almost unlimited amount of calls to source apis, that can be aggregated in this point. DurableHttpResponse response = await context.CallHttpAsync(System.Net.Http.HttpMethod.Get, message.Uri); var stats = await retriever.GetLiveAsync(response.Content); var result = new CompetitionStatsMessage { CompetitionId = message.CompetitionUniqueId, Score = stats.Score }; if (!String.IsNullOrEmpty(result.CompetitionId)) { await context.CallActivityAsync("LiveDataFunctionResultServiceBus", result); // Orchestration sleeps until this time. var nextCheck = context.CurrentUtcDateTime.AddSeconds(pollingInterval); await context.CreateTimer(nextCheck, CancellationToken.None); } } }
public static async Task <string[]> SearchWorkflow( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger logger) { var search = context.GetInput <string>(); logger.LogInformation("Queuing searches..."); var searches = new List <Task <DurableHttpResponse> >() { context.CallHttpAsync(HttpMethod.Get, new Uri($"https://google.com/search?q={search}")), context.CallHttpAsync(HttpMethod.Get, new Uri($"https://search.yahoo.com/search?p={search}")), context.CallHttpAsync(HttpMethod.Get, new Uri($"https://bing.com/search?q={search}")) }; var result = await Task.WhenAll(searches); logger.LogInformation("Searches complete."); var resultString = new List <string>(); foreach (var response in result) { if (response.StatusCode == HttpStatusCode.OK) { resultString.Add(response.Content); } else { resultString.Add("<h1>No Results</h1>"); } } return(resultString.ToArray()); }
public static async Task <HttpStatusCode> WatchWorkflow( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger logger) { var req = context.GetInput <string>(); logger.LogInformation("Starting watcher: {url}", req); var result = await context.CallHttpAsync( HttpMethod.Get, new Uri(req, UriKind.Absolute)); logger.LogInformation("Done watching: {url}", req); return(result.StatusCode); }
public async Task <string> CheckSiteAvailable( [OrchestrationTrigger] IDurableOrchestrationContext context) { Uri url = context.GetInput <Uri>(); // Makes an HTTP GET request to the specified endpoint DurableHttpResponse response = await context.CallHttpAsync(HttpMethod.Get, url); if ((int)response.StatusCode >= 400) { // handling of error codes goes here } return(response.Content); }
public async Task <string> CheckSiteAvailable( [OrchestrationTrigger] IDurableOrchestrationContext context) { Uri uri = context.GetInput <Uri>(); // Makes an HTTP GET request to the specified endpoint DurableHttpResponse response = await context.CallHttpAsync(HttpMethod.Get, uri); if ((int)response.StatusCode >= 400) { throw new Exception($"HttpEndpoint can not found: {uri} statusCode: {response.StatusCode} body: {response.Content}"); } return(response.Content); }
public static async Task <List <string> > RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { log.LogInformation("C# Orchestation Trigger function 'combineorder' processed a request."); var outputs = new List <string>(); // Get OrderReceived Entity and check if complete string batchPrefix = context.GetInput <string>(); log.LogInformation($"Orchestration combineorder {batchPrefix} getting processed."); var entityId = new EntityId(nameof(OrderReceived), batchPrefix); CombineOrderRequest orderReceived = await context.CallEntityAsync <CombineOrderRequest>(entityId, "CheckOrderReceived"); if (orderReceived == null) { log.LogInformation($"Order {batchPrefix} not ready."); } else { // Build CombineOrder Content //string content = $"{{\"orderHeaderDetailsCSVUrl\": \"{orderReceived.headerURL}\", \"orderLineItemsCSVUrl\": \"{orderReceived.lineItemsURL}\", \"productInformationCSVUrl\": \"{orderReceived.productionInformationURL}\" }}"; CombineOrderContent content = new CombineOrderContent(); content.orderHeaderDetailsCSVUrl = orderReceived.headerURL; content.orderLineItemsCSVUrl = orderReceived.lineItemsURL; content.productInformationCSVUrl = orderReceived.productionInformationURL; string json = JsonConvert.SerializeObject(content); log.LogInformation($"CombineOrder Content: {json}"); DurableHttpResponse response = await context.CallHttpAsync(HttpMethod.Post, new System.Uri("https://serverlessohmanagementapi.trafficmanager.net/api/order/combineOrderContent"), json); if (response.StatusCode != System.Net.HttpStatusCode.OK) { log.LogError($"Combine Order was not successful: {response.StatusCode} - {response.Content}"); } else { log.LogInformation($"Combine Order was successful: {response.StatusCode} - {orderReceived.entityKey}"); //log.LogInformation($"{response.Content}"); orderReceived.content = json; outputs.Add(await context.CallActivityAsync <string>("savecombinedorders", orderReceived)); outputs.Add(await context.CallActivityAsync <string>("deleteorders", orderReceived)); } } return(outputs); }
public static async Task <List <string> > RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { // param into orchestrator OrchestratorInput oi = context.GetInput <OrchestratorInput>(); // call activity function await context.CallActivityAsync <List <string> >(nameof(MyActivityFunction), oi.Url); // call durable entity List <string> result = await ContactDurableEntity(context); // call http var request = new DurableHttpRequest(HttpMethod.Post, new Uri(oi.Url), content: "myContent"); DurableHttpResponse response = await context.CallHttpAsync(request); return(result); }
public static async Task MonitorUrl( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var input = context.GetInput <AzDoRelease>(); try { await SendTaskStartedEvent(context, input); // send task started message feed and log the message. You will see feed messages in task log UI. await SendTaskLogFeeds(context, input, "Task Started"); for (var i = 1; ; i++) { var urlResponse = await context.CallHttpAsync(HttpMethod.Get, new Uri(input.WebUrl)); var logMessage = $"{DateTime.UtcNow:0} Message {i}"; await SendTaskLogFeeds(context, input, logMessage); if (urlResponse.StatusCode == HttpStatusCode.OK) { break; } else { await context.CreateTimer(context.CurrentUtcDateTime.AddSeconds(10), CancellationToken.None); } } await SendTaskCompletedEvent(context, input, TaskResultSucceeded); } catch { await SendTaskCompletedEvent(context, input, TaskResultFailed); } finally { // Create task log entry // Append task log data // Attach task log to timeline record // Set task variable } }
public static async Task <RedditEmotionResult> RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { string redditJsonUrl = context.GetInput <string>(); var jsonContent = await context.CallHttpAsync(HttpMethod.Get, new Uri(redditJsonUrl)); var listings = JsonConvert.DeserializeObject <List <Listing> >(jsonContent.Content); List <(string id, string comment)> comments = new List <(string id, string comment)>(); foreach (var child in from listing in listings from child in listing.data.children where child.IsComment select child) { await child.data.AddCommentToList(comments); } return(await context.CallActivityAsync <RedditEmotionResult>("RedditThreadAnalyzer_AnalyzeEmotions", comments)); }
public static async Task <RedditEmotionResult> RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { string redditJsonUrl = context.GetInput <string>(); var existingResult = await context.CallActivityAsync <RedditEmotionResult>("RedditThreadAnalyzer_GetExistingEmotionResult", redditJsonUrl); if (existingResult != null) { return(existingResult); } var jsonContent = await context.CallHttpAsync(HttpMethod.Get, new Uri(redditJsonUrl)); var comments = await context.CallActivityAsync <List <(string id, string comment)> >("RedditThreadAnalyzer_ParseAllComments", jsonContent.Content); var redditEmotionResult = await context.CallActivityAsync <RedditEmotionResult>("RedditThreadAnalyzer_AnalyzeEmotions", comments); await context.CallActivityAsync("RedditThreadAnalyzer_SaveResults", new SaveResultInput { EmotionResult = redditEmotionResult, Url = redditJsonUrl }); return(redditEmotionResult); }
public static async Task <string> MakeHttpRequestSync(string name, string stringUri, string input, IDurableOrchestrationContext context, ILogger log) { var uri = new Uri($"{stringUri}"); if (!context.IsReplaying) { log.LogInformation("Calling {name} with input: {input} at uri: {uri}", name, input, stringUri); } var result = await context.CallHttpAsync(System.Net.Http.HttpMethod.Post, uri, input); if (result.StatusCode != System.Net.HttpStatusCode.OK) { throw new Exception($"incorrect result returned by {name}: {result.Content}"); } string output = result.Content; if (!context.IsReplaying) { log.LogInformation("{name} returned output: {output}", name, output); } return(output); }
public static async Task SingleClientOnboardingOrchestration( [OrchestrationTrigger] IDurableOrchestrationContext createAccountContext ) { AccountOpeningData payload = createAccountContext.GetInput <AccountOpeningData>(); if (null != payload) { string newAccountNumber = await createAccountContext.CallActivityAsync <string>(nameof( CreateRandomAccountNumber), null); string jsonContent = JsonConvert.SerializeObject(payload); var newAccountRequest = new DurableHttpRequest( HttpMethod.Post, new Uri($"https://retailbankazurefunctionapp.azurewebsites.net/api/OpenAccount/{newAccountNumber}?code=9IcflcYh904F3Dcbp5IGCPuDrqelVJniQK5Ck1ZcVdacOd3Mx4ShWQ=="), content: jsonContent); newAccountRequest.Headers.Add(@"Content-Type", @"application/json"); DurableHttpResponse restartResponse = await createAccountContext.CallHttpAsync(newAccountRequest); } }
public static async Task <string> AllOrchestratorActivityActions([OrchestrationTrigger] IDurableOrchestrationContext ctx) { EntityId input = ctx.GetInput <EntityId>(); var stringInput = input.ToString(); RetryOptions options = new RetryOptions(TimeSpan.FromSeconds(5), 3); await ctx.CreateTimer(ctx.CurrentUtcDateTime, CancellationToken.None); await ctx.CallActivityAsync <string>(nameof(TestActivities.Hello), stringInput); await ctx.CallActivityWithRetryAsync <string>(nameof(TestActivities.Hello), options, stringInput); await ctx.CallSubOrchestratorAsync <string>(nameof(TestOrchestrations.SayHelloInline), stringInput); await ctx.CallSubOrchestratorWithRetryAsync <string>(nameof(TestOrchestrations.SayHelloWithActivity), options, stringInput); ctx.StartNewOrchestration(nameof(TestOrchestrations.SayHelloWithActivityWithDeterministicGuid), stringInput); ctx.SignalEntity(input, "count"); ctx.SetCustomStatus("AllAPICallsUsed"); await ctx.CallHttpAsync(null); return("TestCompleted"); }
public static async Task IssueCallbackIfNecessary(this IDurableOrchestrationContext durableOrchestrationContext, FunctionContext functionContext, object content) { if (functionContext.CallbackUrl.IsNullOrWhiteSpace()) { return; } // NOTE: The Azure Storage Emulator is flaky and when used its possible for the callback to be issued // before the instance-id callback handler is ready. When it does a 404 not-found is returned. Thereofore, // in that event we'll continue to retry until successful. Its been confirmed that this is not an issue // when using an Azure Storage Account see the following issue for more details. // https://github.com/Azure/azure-functions-durable-extension/issues/1531 // NOTE: Regarding `asynchronousPatternEnabled`, disabling it is important because when enabled it attempts // to apply an asynchronous pattern based on HTTP Accepted responses (status code 202) which coincidentally // is exactly what the Durable Functionsbuilt-in HTTP APIs return when acknowledging submitted events and // therefore fools the `CallHttpAsync` method into trying to apply the asynchronous pattern. DurableHttpResponse response; do { response = await durableOrchestrationContext.CallHttpAsync( new DurableHttpRequest( HttpMethod.Post, new Uri(functionContext.CallbackUrl), new Dictionary <string, StringValues>() { { "Content-Type", "application/json" } }, content.ToJson(), asynchronousPatternEnabled : false ) ); }while (response.StatusCode == HttpStatusCode.NotFound); }