public static async Task IssueCertificate([OrchestrationTrigger] DurableOrchestrationContext context, ILogger log) { var dnsNames = context.GetInput <string[]>(); // 前提条件をチェック await context.CallActivityAsync(nameof(Dns01Precondition), dnsNames); // 新しく ACME Order を作成する var orderDetails = await context.CallActivityAsync <OrderDetails>(nameof(Order), dnsNames); // 複数の Authorizations を処理する var challenges = new List <ChallengeResult>(); foreach (var authorization in orderDetails.Payload.Authorizations) { // ACME Challenge を実行 var result = await context.CallActivityAsync <ChallengeResult>(nameof(Dns01Authorization), authorization); // Azure DNS で正しくレコードが引けるか確認 await context.CallActivityWithRetryAsync(nameof(CheckIsDnsRecord), new RetryOptions(TimeSpan.FromSeconds(10), 6), result); challenges.Add(result); } // ACME Answer を実行 await context.CallActivityAsync(nameof(AnswerChallenges), challenges); // Order のステータスが ready になるまで 60 秒待機 await context.CallActivityWithRetryAsync(nameof(CheckIsReady), new RetryOptions(TimeSpan.FromSeconds(5), 12), orderDetails); await context.CallActivityAsync(nameof(FinalizeOrder), (dnsNames, orderDetails)); }
public static async Task <object> NewWorker( [OrchestrationTrigger] DurableOrchestrationContext ctx, TraceWriter log ) { int retryattempts = 1; var query = ctx.GetInput <string>(); var retryOptions = new RetryOptions( firstRetryInterval: TimeSpan.FromSeconds(5), maxNumberOfAttempts: retryattempts); var getcookietask = ctx.CallActivityWithRetryAsync <string>("Authenticate", retryOptions, "credentials"); getcookietask.ContinueWith(t => { return("Failed"); }, TaskContinuationOptions.OnlyOnFaulted); await getcookietask; var cookiesjsonb64 = getcookietask.Result; var cookies = CookieConverter.DecodeCookie(cookiesjsonb64); if (!ctx.IsReplaying) { log.Warning($"Successfully retrieved {cookies.Length} cookies."); } var querygurutask = ctx.CallActivityWithRetryAsync <int>("QueryGuru", retryOptions, new Tuple <string, string>(query, cookiesjsonb64)); querygurutask.ContinueWith(t => { return("Failed"); }, TaskContinuationOptions.OnlyOnFaulted); var pages = await querygurutask; if (!ctx.IsReplaying) { log.Warning($"Query successfully returned {pages}."); } var workload = await ctx.CallActivityAsync <List <int> >("CreateWorkload", pages); //log.Warning(ctx.InstanceId); var worker = ctx.CallSubOrchestratorAsync("WorkerWork", new WorkerWorkArgs { query = query, cookiestext = cookiesjsonb64, workload = workload, total = workload.Count }); string result = await ctx.WaitForExternalEvent <string>("Finished"); return(result); }
public async Task Run([OrchestrationTrigger] DurableOrchestrationContext context, ILogger log) { var teamModel = context.GetInput <TeamModel>(); await context.CallActivityWithRetryAsync(nameof(ScheduleActivity), _options.AsRetryOptions(), teamModel); if (_options.ClearScheduleEnabled) { await context.CallSubOrchestratorAsync(nameof(ClearScheduleOrchestrator), teamModel); } else { await context.CallActivityWithRetryAsync(nameof(ClearCacheActivity), _options.AsRetryOptions(), new ClearScheduleModel { TeamId = teamModel.TeamId }); } }
public static async Task <VideoFileInfo[]> TranscodeVideo( [OrchestrationTrigger] DurableOrchestrationContext ctx, TraceWriter log) { var videoLocation = ctx.GetInput <string>(); var bitRates = await ctx.CallActivityAsync <int[]>("A_GetTranseCodeBitrates", null); var transeCodeTasks = new List <Task <VideoFileInfo> >(); foreach (var bitRate in bitRates) { var info = new VideoFileInfo { BitRate = bitRate, Location = videoLocation }; var task = ctx.CallActivityWithRetryAsync <VideoFileInfo>("A_TranscodeVideo", new RetryOptions(TimeSpan.FromSeconds(1), 2), info); transeCodeTasks.Add(task); } var transeCodeResults = await Task.WhenAll(transeCodeTasks); return(transeCodeResults); }
public static async Task <List <string> > RunOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext context, ILogger log) { var outputs = new List <string>(); // Replace "hello" with the name of your Durable Activity Function. var retryOptions = new RetryOptions(TimeSpan.FromSeconds(1), 3); outputs.Add(await context.CallActivityWithRetryAsync <string>("RetryOrchestration_PossiblyFail", retryOptions, "Tokyo")); outputs.Add(await context.CallActivityWithRetryAsync <string>("RetryOrchestration_PossiblyFail", retryOptions, "Seattle")); outputs.Add(await context.CallActivityWithRetryAsync <string>("RetryOrchestration_PossiblyFail", retryOptions, "London")); // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"] log.LogInformation(">>>>>>>>>>>>>>>>> Done <<<<<<<<<<<<<<<<<<"); return(outputs); }
public static async Task <List <string> > RunOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext context) { var outputs = new List <string>(); var ratesXml = await context.CallActivityWithRetryAsync <string>("ImportWorkflow_DownloadRates", null, new RetryOptions(TimeSpan.FromMinutes(10), 100)); var exchangeRates = await context.CallActivityAsync <IEnumerable <ExchangeRate> >("ImportWorkflow_ParseRatesXml", ratesXml); return((from er in exchangeRates select er.Ccy1).ToList()); }
public static async Task <string> TranslationSubOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext context) { var translationContext = context.GetInput <TranslationOrchestrationContext>(); var retryOptions = new RetryOptions(TimeSpan.FromMinutes(1), 5); // Read Document translationContext = await context.CallActivityWithRetryAsync <TranslationOrchestrationContext>("ReadDocument", retryOptions, translationContext); translationContext = await context.CallActivityWithRetryAsync <TranslationOrchestrationContext>("TranslateDocument", retryOptions, translationContext); await context.CallActivityWithRetryAsync("UpdateDocument", retryOptions, translationContext); return(translationContext.Path); }
public static async Task CallSendToConsumerActivityAsync(DurableOrchestrationContext ctx, RetryOptions retryOptions, string consumerUrl, IEnumerable <string> changedProducts) { try { await ctx.CallActivityWithRetryAsync(nameof(SendToConsumerFunc), retryOptions, (consumerUrl, changedProducts)); } catch { //TODO: TEMPORARILY MARK THE CONSUMER AS BANNED IN CONSUMER_DB } }
public static async Task CallSendToConsumerActivityAsync(DurableOrchestrationContext ctx, Microsoft.Azure.WebJobs.RetryOptions retryOptions, ConsumerData consumerData) { try { await ctx.CallActivityWithRetryAsync(nameof(SendToConsumerFunc), retryOptions, consumerData); } catch { //TODO: TEMPORARILY MARK THE CONSUMER AS BANNED IN CONSUMER_DB } }
public static async Task <object> ProcessVideo( [OrchestrationTrigger] DurableOrchestrationContext ctx, TraceWriter log) { var videoLocation = ctx.GetInput <string>(); try { var transcodedLocations = await ctx.CallSubOrchestratorAsync <string[]>(OrchestratorNames.Transcode, videoLocation); var transcodedLocation = transcodedLocations.First(x => x.Contains(".mp4")); // these are SAS tokens var thumbnailLocation = await ctx.CallActivityWithRetryAsync <string>(ActivityNames.ExtractThumbnail, new RetryOptions(TimeSpan.FromSeconds(5), 4), // {Handle = ex => ex.InnerException is InvalidOperationException}, - currently not possible #84 transcodedLocation); var withIntroLocation = await ctx.CallActivityAsync <string> (ActivityNames.PrependIntro, transcodedLocation); // we need to give our suborchestrator its own id so we can send it events // could be a new guid, but by basing it on the parent instance id we make it predictable var approvalInfo = new ApprovalInfo { OrchestrationId = "XYZ" + ctx.InstanceId, VideoLocation = withIntroLocation }; var approvalResult = await ctx.CallSubOrchestratorAsync <string>(OrchestratorNames.GetApprovalResult, approvalInfo.OrchestrationId, approvalInfo); if (approvalResult == "Approved") { await ctx.CallActivityAsync(ActivityNames.PublishVideo, new [] { transcodedLocation, thumbnailLocation, withIntroLocation }); return("Approved and published"); } await ctx.CallActivityAsync(ActivityNames.RejectVideo, new [] { transcodedLocation, thumbnailLocation, withIntroLocation }); return($"Not published because {approvalResult}"); } catch (Exception e) { if (!ctx.IsReplaying) { log.Error("Failed to process video with error " + e.Message); } await ctx.CallActivityAsync(ActivityNames.Cleanup, videoLocation); return(new { Error = "Failed to process video", e.Message }); } }
public static async Task Run([OrchestrationTrigger] DurableOrchestrationContext context, ILogger log) { log.LogInformation($"[START ORCHESTRATOR] --> {FunctionNames.OrderWorkflowFunction}"); var order = context.GetInput <Order>(); log.LogTrace($"Adding Order {order}"); var addResult = await context.CallActivityWithRetryAsync <bool>(FunctionNames.AddOrderFunction, new RetryOptions(TimeSpan.FromSeconds(1), 10), order); if (addResult) { DateTime orderDeadline = GetOrderDeadLine(context); var orderPaidEvent = context.WaitForExternalEvent(Events.OrderPaid); var orderCancelledEvent = context.WaitForExternalEvent(Events.OrderCancelled); var cancelTimer = context.CreateTimer(orderDeadline, CancellationToken.None); var taskCompleted = await Task.WhenAny(orderPaidEvent, orderCancelledEvent, cancelTimer); if (taskCompleted == orderCancelledEvent || taskCompleted == cancelTimer) { log.LogWarning($"Order Cancelled : {order}"); order = await context.CallActivityAsync <Order>(FunctionNames.FinalizeOrderFunction, new OrderStateChange() { NewOrderState = OrderStatus.Cancelled, OrderId = order.Id }); } else if (taskCompleted == orderPaidEvent) { log.LogTrace($"Order Paid : {order}"); order = await context.CallActivityAsync <Order>(FunctionNames.FinalizeOrderFunction, new OrderStateChange() { NewOrderState = OrderStatus.Paid, OrderId = order.Id }); await context.CallActivityAsync <string>(FunctionNames.GenerateInvoiceFunction, order); } if (order != null) { var sendMailResult = await context.CallActivityAsync <bool>(FunctionNames.SendMailFunction, order); log.LogTrace($"Sendmail result : {sendMailResult}"); } } }
public static async Task ProcessOrderOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext context, ILogger log) { var policy = context.GetInput <WhatIfDemoDbDataContext.Policy>(); // Configuring retries for SavePolicyToDb activity var retryOptions = new RetryOptions(TimeSpan.FromSeconds(5), 3); policy = await context.CallActivityWithRetryAsync <WhatIfDemoDbDataContext.Policy>(nameof(SavePolicyToDb), retryOptions, policy); // Now let's start charging the customer via a sub-orchestration await context.CallSubOrchestratorAsync(nameof(ProcessOrderSubOrchestrator), policy); }
public static async Task ClientOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext context) { const int agentNumber = 100; var tasks = new Task[agentNumber]; for (int i = 0; i < agentNumber; i++) { var deviceId = GetDeviceId(i); tasks[i] = context.CallActivityWithRetryAsync("Client", new RetryOptions(TimeSpan.FromSeconds(1), int.MaxValue), deviceId); } await Task.WhenAll(tasks); }
/// <summary> /// Invia notifica ordine via Mail /// </summary> /// <param name="context"></param> /// <param name="ordineAcquisto"></param> /// <returns></returns> private static async Task SendMail(DurableOrchestrationContext context, OrdiniAcquistoModel ordineAcquisto) { string mailInstance = await context.CallActivityWithRetryAsync <string>(Workflow.InviaMailOrdineCliente, new RetryOptions(TimeSpan.FromSeconds(5), 10), new OrdiniAcquistoModel { IdConfirmation = context.InstanceId, IdOrdine = ordineAcquisto.IdOrdine, Articoli = ordineAcquisto.Articoli, ClienteCorrente = ordineAcquisto.ClienteCorrente }); Log.Information($"OrdineClienteManager: MailInstance {mailInstance}"); }
public static async Task <HttpResponseMessage> Run([OrchestrationTrigger] DurableOrchestrationContext cartContext) { // Get input data var cartInfo = cartContext.GetInput <CheckoutData>() ?? new CheckoutData(); if ((cartInfo.CartId == null) || (cartInfo.CartUrl == null)) { return(new HttpResponseMessage(HttpStatusCode.BadRequest)); } // retryoptions var retryOptionsCartContent = new RetryOptions(firstRetryInterval: TimeSpan.FromSeconds(5), maxNumberOfAttempts: 3); var retryOptionsPayment = new RetryOptions(firstRetryInterval: TimeSpan.FromSeconds(4), maxNumberOfAttempts: 2); // Start the workflow try { var payment = await cartContext.CallActivityAsync <bool>("HandlePayment", 22); var cart = await cartContext.CallActivityWithRetryAsync <CartInstance>("GetCartContent", retryOptionsCartContent, cartInfo.CartUrl); var notif = await cartContext.CallActivityWithRetryAsync <bool>("SendReceipt", retryOptionsPayment, cart); if (notif == false) { throw new Exception("Hoppsan"); } var order = await cartContext.CallActivityAsync <bool>("UpdateOrderSystem", cart); } catch (Exception ex) { throw ex; } return(new HttpResponseMessage(HttpStatusCode.OK)); }
public static async Task ActivityWithRetry_NullRetryOptions([OrchestrationTrigger] DurableOrchestrationContext ctx) { string message = ctx.GetInput <string>(); if (string.IsNullOrEmpty(message)) { // This throw happens directly in the orchestration. throw new ArgumentNullException(nameof(message)); } RetryOptions options = null; // This throw happens in the implementation of an activity. await ctx.CallActivityWithRetryAsync(nameof(TestActivities.ThrowActivity), options, message); }
public static async Task <bool> Run([OrchestrationTrigger] DurableOrchestrationContext context) { var orderData = context.GetInput <dynamic>(); await context.CallActivityWithRetryAsync("PayViaMastercard", new RetryOptions(TimeSpan.FromMinutes(3), 3), orderData.MastercardInfo); await context.CallActivityAsync("NotifyBuyerOfPayment", orderData.Buyer.ContactEmail); await context.CallActivityAsync("NotifySellerOfPayment", orderData.Seller.ContactEmail); await context.CallActivityAsync("UpdateOrderInDatabase", orderData); await context.CallActivityAsync("ArrangeShipment", orderData.ShipmentDetails); return(true); }
public static async Task ProcessClaimOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext context, ILogger log) { var claim = context.GetInput <WhatIfDemoDbDataContext.Claim>(); // Sending mobile notification await context.CallActivityAsync(nameof(SendMobileNotification), claim); // Waiting for the claim to be approved await context.WaitForExternalEvent(nameof(ApproveClaim)); // Saving the claim to DB var retryOptions = new RetryOptions(TimeSpan.FromSeconds(5), 3); await context.CallActivityWithRetryAsync <WhatIfDemoDbDataContext.Claim>(nameof(SaveClaimToDb), retryOptions, claim); log.LogWarning($"Claim {claim.id} processing finished!"); }
public static async Task <int> Orchestration2([OrchestrationTrigger] DurableOrchestrationContext context) { var payload = context.GetInput <(int, Guid)>(); try { var retryOptions = new RetryOptions(TimeSpan.FromSeconds(5), 5); var total = await context.CallActivityWithRetryAsync <int>(nameof(Transfer2), retryOptions, payload); return(total); } catch (Exception) { var total = await context.CallActivityAsync <int>(nameof(Refund2), payload); return(total); } }
public static async Task OrderManager([OrchestrationTrigger] DurableOrchestrationContext context, ILogger log) { log.LogInformation($"[START ORCHESTRATOR] --> {FunctionNames.OrderManagerDurable}!"); var order = context.GetInput <Order>(); bool result = await context.CallActivityWithRetryAsync <bool>(FunctionNames.OrderStoreDurable, new RetryOptions(TimeSpan.FromSeconds(1), 10), order); if (!result) { return; } var fileName = await context.CallActivityAsync <string>(FunctionNames.GenerateInvoiceDurable, order); order.fileName = fileName; await context.CallActivityAsync <string>(FunctionNames.SendMailToCustomerDurable, order); }
public static async Task <List <string> > RunOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext ctx) { var retryOptions = new RetryOptions( firstRetryInterval: TimeSpan.FromSeconds(5), maxNumberOfAttempts: 3 ); TimeSpan timeout = TimeSpan.FromSeconds(60); DateTime deadline = ctx.CurrentUtcDateTime.Add(timeout); var outputs = new List <string>(); var parallelTasks = new List <Task <string> >(); List <string> results = null; using (var cts = new CancellationTokenSource()) { // get a list of N work items to process in parallel for (int i = 0; i < 200; i++) { Task <string> task = ctx.CallActivityWithRetryAsync <string>("trigger_Hello", retryOptions, i.ToString()); parallelTasks.Add(task); } Task timeoutTask = ctx.CreateTimer(deadline, cts.Token); Task runTask = Task.WhenAll(parallelTasks); Task winner = await Task.WhenAny(runTask, timeoutTask); if (winner == runTask) { // Success case cts.Cancel(); results = parallelTasks.Select(t => t.Result).ToList(); } } // aggregate all N outputs and send result to F3 return(results); }
public static async Task ExternalRegistrySynchronizer_DeleteDeviceOrchestration( [OrchestrationTrigger] DurableOrchestrationContext context, TraceWriter log) { var input = context.GetInput <DeviceDeleteOrchestrationInput>(); var deviceId = input.Device["deviceId"].ToString(); if (!context.IsReplaying) { log.Info($"{nameof(ExternalRegistrySynchronizer_DeleteDeviceOrchestration)} started for {deviceId} / {input.IoTHubName}. {nameof(Settings.Instance.TwinCheckIntervalInSeconds)}: {Settings.Instance.TwinCheckIntervalInSeconds} secs, {nameof(Settings.Instance.TwinCheckMaxRetryCount)}: {Settings.Instance.TwinCheckMaxRetryCount}, {nameof(Settings.Instance.TwinCheckMaxIntervalInSeconds)}: {Settings.Instance.TwinCheckMaxIntervalInSeconds} secs, {nameof(Settings.Instance.TwinCheckRetryTimeoutInMinutes)}: {Settings.Instance.TwinCheckRetryTimeoutInMinutes} minutes"); } var deleteExternalDeviceSucceeded = false; try { deleteExternalDeviceSucceeded = await context.CallActivityWithRetryAsync <bool>(nameof(DeleteDeviceInExternalSystemActivity), new RetryOptions(TimeSpan.FromSeconds(Settings.Instance.ExternalSystemCallRetryIntervalInSeconds), Settings.Instance.ExternalSystemCallMaxRetryCount) { BackoffCoefficient = 2, // backoff coefficient ^2 MaxRetryInterval = TimeSpan.FromSeconds(Settings.Instance.ExternalSystemCallMaxIntervalInSeconds), // will wait for a new retry up to x seconds RetryTimeout = TimeSpan.FromMinutes(Settings.Instance.ExternalSystemCallRetryTimeoutInMinutes) // will try up to x minutes }, input); } catch (FunctionFailedException) { deleteExternalDeviceSucceeded = false; } if (!deleteExternalDeviceSucceeded) { Utils.TelemetryClient?.TrackEvent(Utils.Event_ExternalDeviceDeleteFailed, new Dictionary <string, string>() { { "deviceId", deviceId }, { "iothubname", input.IoTHubName } }); } log.Info($"{nameof(ExternalRegistrySynchronizer_DeleteDeviceOrchestration)} finished for {deviceId} / {input.IoTHubName}. Succeeded: {deleteExternalDeviceSucceeded.ToString()}"); }
public static async Task <CarResultWrapper> RunOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext context) { var searchRequest = context.GetInput <CarSearchRequest>(); var suppliers = await context.CallActivityWithRetryAsync <List <Supplier> >("GetActiveSuppliers", RetryPolicy.DbReadRetryOption, null); bool isLocalhost; bool.TryParse(Environment.GetEnvironmentVariable("Localhost"), out isLocalhost); MockSearchService.IsLocalHost = isLocalhost; MockSearchService.InitData(); var searchParallelTasks = new List <Task <List <CarPrice> > >(); foreach (var sup in suppliers) { var task = context.CallActivityAsync <List <CarPrice> >("SearchCarSupplier", new { CarSearchRequest = searchRequest, Supplier = sup }); searchParallelTasks.Add(task); } await Task.WhenAll(searchParallelTasks); var carPriceResults = new CarResultWrapper { BookingDetail = searchRequest }; var carResults = new List <CarPrice>(); foreach (var t in searchParallelTasks) { carResults.AddRange(t.Result); } carPriceResults.CarPrices = carResults; // TODO: fan-in, aggregate & de-duplicate data, sort/grouping etc. return(carPriceResults); }
public static async Task ManageLetter([OrchestrationTrigger] DurableOrchestrationContext context, ILogger log) { log.LogInformation($"[START ORCHESTRATOR] --> LetterManager!"); var letter = context.GetInput <LetterDto>(); ChildDto child = await context.CallActivityWithRetryAsync <ChildDto>(Constants.RetrieveChildActivityFunction, new RetryOptions(TimeSpan.FromSeconds(1), 10), letter); if (child == null) { return; } child.CurrentLetter = letter; if (child.Goodness >= 5) { await context.CallActivityAsync(Constants.OrderGiftActivityFunction, child); } else { await context.CallActivityAsync(Constants.SendMailToSupportActivityFunction, (context.InstanceId, child)); var approvedGiftEvent = context.WaitForExternalEvent <bool>(Constants.GiftApprovedEvent); var rejectedGiftEvent = context.WaitForExternalEvent <bool>(Constants.GiftRejectedEvent); var eventFired = await Task.WhenAny(approvedGiftEvent, rejectedGiftEvent); if (eventFired == approvedGiftEvent) { await context.CallActivityAsync(Constants.OrderGiftActivityFunction, child); } else if (eventFired == rejectedGiftEvent) { await context.CallActivityAsync(Constants.RetrieveChildActivityFunction, child); } } }
public static async Task <Dictionary <string, int> > GetLevels([OrchestrationTrigger] DurableOrchestrationContext context) { var engineers = context.GetInput <List <string> >(); var levels = new Dictionary <string, int>(); var tasks = engineers .Select(engineer => context.CallActivityWithRetryAsync <int>("FileProcessor_GetLevels_Each", new RetryOptions(TimeSpan.FromMilliseconds(1000), 10), engineer)) .ToArray(); await Task.WhenAll(tasks); for (var i = 0; i < engineers.Count; i++) { if (!tasks[i].IsFaulted) { levels.Add(engineers[i], tasks[i].Result); } else { levels.Add(engineers[i], 0); } } return(levels); }
public static async Task <bool> RunOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext context) { int batchSize; int.TryParse(Environment.GetEnvironmentVariable("BatchSize"), out batchSize); int firstRetryIntervalVar; int.TryParse(Environment.GetEnvironmentVariable("FirstRetrySeconds"), out firstRetryIntervalVar); int maxNumberOfAttemptsVar; int.TryParse(Environment.GetEnvironmentVariable("MaxNumberOfAttempts"), out maxNumberOfAttemptsVar); double backoffCoefficientVar; double.TryParse(Environment.GetEnvironmentVariable("BackoffCoefficient"), out backoffCoefficientVar); var retryOptions = new RetryOptions( firstRetryInterval: TimeSpan.FromSeconds(firstRetryIntervalVar), maxNumberOfAttempts: maxNumberOfAttemptsVar); retryOptions.BackoffCoefficient = backoffCoefficientVar; var outputs = new List <bool>(); var tasks = new Task <bool> [batchSize]; for (int i = 0; i < batchSize; i++) { tasks[i] = context.CallActivityWithRetryAsync <bool>("BulkLoader_Batch", retryOptions, i); } await Task.WhenAll(tasks); return(true); }
public static async Task <List <string> > RunOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext context, TraceWriter log) { var outputs = new List <string>(); DateTime endTime = context.CurrentUtcDateTime.AddMinutes(10); while (context.CurrentUtcDateTime < endTime) { if (!context.IsReplaying) { log.Info($"This event occurs {context.CurrentUtcDateTime}."); } outputs.Add(await context.CallActivityWithRetryAsync <string>( "SlotSampleDurable_Slack", new RetryOptions(new System.TimeSpan(5000), 10), "Tokyo : " + context.CurrentUtcDateTime.ToString())); var nextCheck = context.CurrentUtcDateTime.AddSeconds(30); await context.CreateTimer(nextCheck, CancellationToken.None); } return(outputs); }
public static async Task <ActivityResponse> QueryOutputProcessorOrchestrator( [OrchestrationTrigger] DurableOrchestrationContext context, Microsoft.Extensions.Logging.ILogger log) { ActivityResponse response = new ActivityResponse() { FunctionName = "QueryOutputProcessorOrchestrator" }; // Get the Query_Outputs_Request from the context... Query_Outputs_Request request = context.GetInput <Query_Outputs_Request>(); if (null != request) { // Read the outputs for the given query Guid queryGuid; if (Guid.TryParse(request.UniqueIdentifier, out queryGuid)) { // Get the current state of the query... Projection getQueryState = new Projection(Constants.Domain_Query, request.QueryName, queryGuid.ToString(), nameof(Query_Summary_Projection)); if (null != getQueryState) { // Get all the output targets Query_Outputs_Projection qryOutputs = new Query_Outputs_Projection(log); await getQueryState.Process(qryOutputs); if ((qryOutputs.CurrentSequenceNumber > 0) || (qryOutputs.ProjectionValuesChanged())) { #region Logging if (null != log) { log.LogDebug($"Sending results to output targets from {request.QueryName} : {request.UniqueIdentifier} "); } #endregion List <Task <ActivityResponse> > allOutputTasks = new List <Task <ActivityResponse> >(); if (null != request.Results) { // Create a QueryOutputRecord<object> QueryOutputRecord <object> outputRequest = QueryOutputRecord <object> .Create(request.Results, @"", request.QueryName, queryGuid); foreach (string location in qryOutputs.WebhookTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being sent by webhook in OutputResultsGetLeagueSummaryQuery"); } #endregion outputRequest.Target = location; // add a task to ouputit it via webhook.... allOutputTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("QueryOutputToWebhookActivity", DomainSettings.QueryRetryOptions(), outputRequest)); } foreach (string location in qryOutputs.BlobTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being persisted to a Blob in {response.FunctionName}"); } #endregion outputRequest.Target = location; // add a task to ouputit it via webhook.... allOutputTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("QueryOutputToBlobActivity", DomainSettings.QueryRetryOptions(), outputRequest)); } foreach (string location in qryOutputs.ServiceBusTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being sent out via service bus in {response.FunctionName}"); } #endregion outputRequest.Target = location; // add a task to ouputit it via service bus.... allOutputTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("QueryOutputToServiceBusActivity", DomainSettings.QueryRetryOptions(), outputRequest)); } //EventGridTargets foreach (string location in qryOutputs.EventGridTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being sent out via event grid in {response.FunctionName}"); } #endregion outputRequest.Target = location; // add a task to ouputit it via event grid.... allOutputTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("QueryOutputToEventGridActivity", DomainSettings.QueryRetryOptions(), outputRequest)); } foreach (string location in qryOutputs.SignalRTargets) { #region Logging if (null != log) { log.LogDebug($"Target : { location} - being sent out via SignalR in {response.FunctionName}"); } #endregion outputRequest.Target = location; // add a task to ouputit it via SignalR.... allOutputTasks.Add(context.CallActivityWithRetryAsync <ActivityResponse>("QueryOutputToSignalRActivity", DomainSettings.QueryRetryOptions(), outputRequest)); } // TODO: All the other output methods } // Await for all the outputs to have run in parallel... await Task.WhenAll(allOutputTasks); foreach (var returnedResponse in allOutputTasks) { if (returnedResponse.Result.FatalError) { response.FatalError = true; response.Message = returnedResponse.Result.Message; } #region Logging if (null != log) { log.LogDebug($"Sent results to output targets from {returnedResponse.Result.FunctionName} : {returnedResponse.Result.Message } "); } #endregion context.SetCustomStatus(returnedResponse.Result); } } } } } else { response.Message = $"Unable to get outputs request details in sub orchestration {context.InstanceId} "; response.FatalError = true; } return(response); }
public static async Task Run([OrchestrationTrigger] DurableOrchestrationContext context) { var header = context.WaitForExternalEvent <string>("OrderHeaderDetails.csv"); var info = context.WaitForExternalEvent <string>("ProductInformation.csv"); var lineItems = context.WaitForExternalEvent <string>("OrderLineItems.csv"); // all three documents are present, build the order documents await Task.WhenAll(header, info, lineItems); var account = CloudStorageAccount.Parse(Environment.GetEnvironmentVariable("StorageConnectionString")); var blobClient = account.CreateCloudBlobClient(); var container = blobClient.GetContainerReference("challengesixblob"); var headerBlob = container.GetBlockBlobReference(header.Result); var headerText = headerBlob.DownloadText(); var csv = new CsvReader(new StringReader(headerText), new Configuration { HasHeaderRecord = true }); var orderDictionary = csv.GetRecords <dynamic>() .Select(r => new Order { Id = r.ponumber, Datetime = Convert.ToDateTime(r.datetime), TotalTax = Convert.ToDouble(r.totaltax), TotalCost = Convert.ToDouble(r.totalcost), Location = new Location { Id = r.locationid, Name = r.locationname, Address = r.locationaddress, PostCode = r.locationpostcode } }).ToDictionary(o => o.Id, o => o); var infoBlob = container.GetBlockBlobReference(info.Result); var infoText = infoBlob.DownloadText(); csv = new CsvReader(new StringReader(infoText), new Configuration { HasHeaderRecord = true }); var productDictionary = csv.GetRecords <dynamic>() .Select(r => new ProductDetail { Id = r.productid, Name = r.productname, Description = r.productdescription }).ToDictionary(p => p.Id, p => p); var lineItemsBlob = container.GetBlockBlobReference(lineItems.Result); var itemsText = lineItemsBlob.DownloadText(); csv = new CsvReader(new StringReader(itemsText), new Configuration { HasHeaderRecord = true }); foreach (var i in csv.GetRecords <dynamic>()) { var o = (Order)orderDictionary[Convert.ToString(i.ponumber)]; var p = productDictionary[Convert.ToString(i.productid)]; var li = new LineItem { Product = p, Quantity = Convert.ToInt32(i.quantity), UnitCost = Convert.ToDouble(i.unitcost), TotalCost = Convert.ToDouble(i.totalcost), TotalTax = Convert.ToDouble(i.totaltax) }; o.LineItems.Add(li); } foreach (var order in orderDictionary) { await context.CallActivityWithRetryAsync("PersistOrder", new RetryOptions(TimeSpan.FromSeconds(2), 10), order.Value); } headerBlob.Metadata.Add("imported", "true"); await headerBlob.SetMetadataAsync(); infoBlob.Metadata.Add("imported", "true"); await infoBlob.SetMetadataAsync(); lineItemsBlob.Metadata.Add("imported", "true"); await lineItemsBlob.SetMetadataAsync(); }
public static async Task RunOrchestrator([OrchestrationTrigger] DurableOrchestrationContext context, ILogger log) { var request = context.GetInput <AddCertificateRequest>(); var site = await context.CallActivityAsync <Site>(nameof(SharedFunctions.GetSite), (request.ResourceGroupName, request.SiteName, request.SlotName)); if (site == null) { log.LogError($"{request.SiteName} is not found"); return; } var hostNameSslStates = site.HostNameSslStates .Where(x => request.Domains.Contains(x.Name)) .ToArray(); if (hostNameSslStates.Length != request.Domains.Length) { foreach (var hostName in request.Domains.Except(hostNameSslStates.Select(x => x.Name))) { log.LogError($"{hostName} is not found"); } return; } // ワイルドカード、コンテナ、Linux の場合は DNS-01 を利用する var useDns01Auth = request.Domains.Any(x => x.StartsWith("*")) || site.Kind.Contains("container") || site.Kind.Contains("linux"); // 前提条件をチェック if (useDns01Auth) { await context.CallActivityAsync(nameof(SharedFunctions.Dns01Precondition), request.Domains); } else { await context.CallActivityAsync(nameof(SharedFunctions.Http01Precondition), site); } // 新しく ACME Order を作成する var orderDetails = await context.CallActivityAsync <OrderDetails>(nameof(SharedFunctions.Order), request.Domains); // 複数の Authorizations を処理する var challenges = new List <ChallengeResult>(); foreach (var authorization in orderDetails.Payload.Authorizations) { // ACME Challenge を実行 if (useDns01Auth) { var result = await context.CallActivityAsync <ChallengeResult>(nameof(SharedFunctions.Dns01Authorization), authorization); // Azure DNS で正しくレコードが引けるか確認 await context.CallActivityWithRetryAsync(nameof(SharedFunctions.CheckIsDnsRecord), new RetryOptions(TimeSpan.FromSeconds(10), 6), result); challenges.Add(result); } else { challenges.Add(await context.CallActivityAsync <ChallengeResult>(nameof(SharedFunctions.Http01Authorization), (site, authorization))); } } // ACME Answer を実行 await context.CallActivityAsync(nameof(SharedFunctions.AnswerChallenges), challenges); // Order のステータスが ready になるまで 60 秒待機 await context.CallActivityWithRetryAsync(nameof(SharedFunctions.CheckIsReady), new RetryOptions(TimeSpan.FromSeconds(5), 12), orderDetails); // Order の最終処理を実行し PFX を作成 var(thumbprint, pfxBlob) = await context.CallActivityAsync <(string, byte[])>(nameof(SharedFunctions.FinalizeOrder), (request.Domains, orderDetails)); await context.CallActivityAsync(nameof(SharedFunctions.UpdateCertificate), (site, $"{request.Domains[0]}-{thumbprint}", pfxBlob)); foreach (var hostNameSslState in hostNameSslStates) { hostNameSslState.Thumbprint = thumbprint; hostNameSslState.SslState = request.UseIpBasedSsl ?? false ? SslState.IpBasedEnabled : SslState.SniEnabled; hostNameSslState.ToUpdate = true; } await context.CallActivityAsync(nameof(SharedFunctions.UpdateSiteBinding), site); }