private static async Task OnMessageEventAsync(IDurableOrchestrationClient client, MessageEvent messageEvent) { if (messageEvent.Message is TextEventMessage message) { var str = message.Text.Replace("\r\n", "\n").Replace("\n", "。"); // テンプレート入力中であればテンプレートにメッセージを追加 var tmplStatus = await client.GetStatusAsync("tmpl_" + messageEvent.Source.UserId); if (tmplStatus?.RuntimeStatus == OrchestrationRuntimeStatus.ContinuedAsNew || tmplStatus?.RuntimeStatus == OrchestrationRuntimeStatus.Pending || tmplStatus?.RuntimeStatus == OrchestrationRuntimeStatus.Running) { // Durable Functionsの外部イベントとして送信メッセージを投げる await client.RaiseEventAsync("tmpl_" + messageEvent.Source.UserId, Consts.DurableEventNameAddToTemplate, str); await lineMessagingClient.ReplyMessageAsync(messageEvent.ReplyToken, new List <ISendMessage> { new TextMessage("テンプレートに追加しました。", new QuickReply { Items = { new QuickReplyButtonObject(new PostbackTemplateAction("作成を終了する", "action=endTemplateSetting")) } }) }); } else { // 待機中になるまで待つ while (true) { // ひとつ前のイベントを処理している最中は無視されるので注意 var ventStatus = await client.GetStatusAsync(messageEvent.Source.UserId); if (ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.ContinuedAsNew || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Pending || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Running) { // Durable Functionsの外部イベントとして送信メッセージを投げる await client.RaiseEventAsync(messageEvent.Source.UserId, Consts.DurableEventNameLineVentriloquismInput, str); break; } else if (ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Terminated || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Canceled || ventStatus.RuntimeStatus == OrchestrationRuntimeStatus.Failed) { // キャンセル、失敗時はスキル起動していない状態のため、スキル起動を促す await lineMessagingClient.ReplyMessageAsync(messageEvent.ReplyToken, new List <ISendMessage> { new TextMessage("Clovaで「テキスト腹話術」のスキルを起動してください。") }); break; } } } } }
public static async Task <HttpResponseMessage> SubmitApproval( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "SubmitApproval/{id}")] HttpRequest req, [DurableClient] IDurableOrchestrationClient client, [Table("Approvals", "Approval", "{id}", Connection = "AzureWebJobsStorage")] Approval approval, ILogger log) { string result = req.Query["result"]; if (result == null) { return(new HttpResponseMessage(HttpStatusCode.BadRequest)); } log.LogInformation($"Sending approval result to {approval.OrchestrationId} of {result}"); try { // send the ApprovalResult external event to this orchestration await client.RaiseEventAsync(approval.OrchestrationId, "ApprovalResult", result); } catch (System.Exception) { return(new HttpResponseMessage(HttpStatusCode.BadRequest)); } return(new HttpResponseMessage(HttpStatusCode.OK)); }
private static async Task WakeUpOrchestrator(IDurableOrchestrationClient starter, ILogger log) { // TODO: This should live elsewhere, dependent on any frontend calling /ping before orchestration loop starts or is woken up // Ideally, should react to users connecting/disconnecting to SignalR. Have to use ping because we know when they connect (negotiate), // but not when they disconnect: https://github.com/Azure/azure-signalr/issues/301#issuecomment-474668605 try { var existingInstance = await starter.GetStatusAsync(Constants.SingletonOrchestratorId); if (existingInstance == null || existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Failed) { // An instance with the specified ID doesn't exist, create one. await starter.StartNewAsync(FunctionNames.NowPlayingOrchestrator, Constants.SingletonOrchestratorId, new OrchestratorData { Interval = 0 }); log.LogInformation($"Started orchestration with ID = '{Constants.SingletonOrchestratorId}'."); } else { await starter.RaiseEventAsync(Constants.SingletonOrchestratorId, FunctionEvents.WakeUpOrchestrator, true); } } catch (Exception ex) { log.LogError(ex, "Could not start orchestration or raise event"); } }
public static async Task SagaEventProcessor( [EventHubTrigger(@"%ReplyEventHubName%", Connection = @"EventHubsNamespaceConnection")] EventData[] eventsData, [CosmosDB( databaseName: @"%CosmosDbDatabaseName%", collectionName: @"%CosmosDbSagaCollectionName%", ConnectionStringSetting = @"CosmosDbConnectionString")] IAsyncCollector <SagaItem> documentCollector, [DurableClient] IDurableOrchestrationClient client, ILogger log) { foreach (EventData eventData in eventsData) { var jsonBody = Encoding.UTF8.GetString(eventData.Body); DefaultEvent @event = JsonConvert.DeserializeObject <DefaultEvent>(jsonBody); if (@event.Header == null) { log.LogError("Invalid event header"); continue; } var item = new SagaItem { TransactionId = @event.Header.TransactionId, MessageType = @event.Header.MessageType, Source = @event.Header.Source, CreationDate = @event.Header.CreationDate }; await documentCollector.AddAsync(item); await client.RaiseEventAsync(@event.Header.TransactionId, @event.Header.Source, @event.Header.MessageType); } }
public static async Task EventReplyReader( [EventHubTrigger("ReplyEventtHub", Connection = "EventHubConnectionAppSetting")] EventData eventHubEvent, [DurableClient] IDurableOrchestrationClient client, ILogger log) { CommandProducer command = JsonConvert.DeserializeObject <CommandProducer>(Encoding.UTF8.GetString(eventHubEvent.Body)); await client.RaiseEventAsync(command.MessageId, command.Source, command.OperationStatus); }
public static async Task Raise([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, [DurableClient] IDurableOrchestrationClient client, Microsoft.Azure.WebJobs.ExecutionContext executionContext, ILogger log) { string instanceId = InstanceId; var eventData = req.Query["event"]; var existingInstance = await client.GetStatusAsync(instanceId); if (eventData == "stop") { log.LogInformation("Start orchestration"); await client.StartNewAsync("OrchestrationWorkflow", instanceId); } else if (eventData == "start") { await Start(GetAzureContext(executionContext), log); if (existingInstance == null || existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Completed || existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Failed || existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Terminated) { log.LogInformation("There is no timers to interrupt"); } else { log.LogInformation("Raise start instance event"); bool isStartEvent = true; await client.RaiseEventAsync(instanceId, "StartEvent", isStartEvent); } } }
public static async Task <HttpResponseMessage> HttpStart( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req, [DurableClient] IDurableOrchestrationClient starter, ILogger logger) { var orchestrationId = "SingletonId"; var orchestration = await starter.GetStatusAsync(orchestrationId); if (orchestration == null) { logger.LogInformation(">>>>>> [CLI] Starting new orchestration, expiring in 10 minutes"); await starter.StartNewAsync(nameof(RunOrchestrator), orchestrationId, DateTime.UtcNow.AddMinutes(10)); } else { logger.LogInformation(">>>>>> [CLI] Orchestration already exists"); } var data = $"DATA:{Guid.NewGuid()}"; logger.LogInformation($">>>>>> [CLI] Sending data { data }"); await starter.RaiseEventAsync(orchestrationId, DataEventName, data); return(starter.CreateCheckStatusResponse(req, orchestrationId)); }
private static async Task OnPostbackEventAsync(IDurableOrchestrationClient client, PostbackEvent postbackEvent) { switch (postbackEvent?.Postback?.Data) { // テンプレート作成開始 case "action=startTemplateSetting": await lineMessagingClient.ReplyMessageAsync(postbackEvent.ReplyToken, new List <ISendMessage> { new TextMessage("テンプレートに追加したいセリフを送ってください。") }); await client.StartNewAsync(nameof(MakeTemplate), "tmpl_" + postbackEvent.Source.UserId, null); break; // テンプレート作成終了 case "action=endTemplateSetting": // Durable Functionsの外部イベントとして送信メッセージを投げる await client.RaiseEventAsync("tmpl_" + postbackEvent.Source.UserId, Consts.DurableEventNameAddToTemplate, $"{Consts.FinishMakingTemplate}_{postbackEvent.ReplyToken}"); break; // 翻訳モード選択 case "action=startTranslation": // クイックリプライでモード選択 await lineMessagingClient.ReplyMessageAsync(postbackEvent.ReplyToken, new List <ISendMessage> { new TextMessage("何語に翻訳しますか?", new QuickReply { Items = { new QuickReplyButtonObject(new PostbackTemplateAction(" 英語へ", "lang=en")), new QuickReplyButtonObject(new PostbackTemplateAction(" 韓国語へ", "lang=ko")), new QuickReplyButtonObject(new PostbackTemplateAction(" 日本語へ", "lang=ja")), new QuickReplyButtonObject(new PostbackTemplateAction(" 翻訳モード終了", "action=endTranslation")) } }) }); break; // 翻訳モード開始 case string s when s.StartsWith("lang="): var lang = s.Replace("lang=", string.Empty); await lineMessagingClient.ReplyMessageAsync(postbackEvent.ReplyToken, new List <ISendMessage> { new TextMessage( @$ "{lang switch { " en " => " 英語 ", " ko " => " 韓国語 ", " ja " => " 日本語 ", _ => throw new InvalidOperationException() }}に翻訳してしゃべります。") });
public static async Task <IActionResult> HttpTrigger( [HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpTriggerArgs args, [OrchestrationClient] IDurableOrchestrationClient durableOrchestrationClient, ILogger log) { // 'orchestrationId = DeviceId' > tricky stuff, make sure the orchestrationId is deterministic but also unique and has now weird characters var orchestrationId = args.DeviceId; var status = await durableOrchestrationClient.GetStatusAsync(orchestrationId); // Maybe do this from within the Orchestrator var entity = new EntityId(nameof(DeviceEntity), args.DeviceId); await durableOrchestrationClient.SignalEntityAsync(entity, "UpdateLastCommunicationDateTime"); switch (status?.RuntimeStatus) { case OrchestrationRuntimeStatus.Running: case OrchestrationRuntimeStatus.Pending: case OrchestrationRuntimeStatus.ContinuedAsNew: await durableOrchestrationClient.RaiseEventAsync(orchestrationId, "MessageReceived", null); break; default: await durableOrchestrationClient.StartNewAsync(nameof(WaitingOrchestrator), orchestrationId, new OrchestratorArgs { DeviceId = args.DeviceId }); break; } log.LogInformation("Started orchestration with ID = '{orchestrationId}'.", orchestrationId); var response = durableOrchestrationClient.CreateHttpManagementPayload(orchestrationId); return(new OkObjectResult(response)); }
public static async Task Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "sendinteraction/{instanceId}")] HttpRequestMessage req, [DurableClient] IDurableOrchestrationClient client, string instanceId) { await client.RaiseEventAsync(instanceId, "FinishedHello"); }
public static Task RaiseEventAsync( this IDurableOrchestrationClient client, string instanceId, string eventName) { return(client.RaiseEventAsync(instanceId, eventName, null)); }
public static async Task Raise([EventGridTrigger] EventGridEvent eventGridEvent, [DurableClient] IDurableOrchestrationClient client, ILogger log) { log.LogInformation(eventGridEvent.Data.ToString()); if (eventGridEvent.Data is EventModel) { log.LogInformation("enter if statement"); var eventData = (EventModel)eventGridEvent.Data; if (eventData.EventType == "stop") { log.LogInformation("Start orchestration"); await client.StartNewAsync("OrchestrationWorkflow"); } else if (eventData.EventType == "start") { log.LogInformation("Raise start event"); await client.RaiseEventAsync(eventData.Id.ToString(), "StartEvent", eventData.EventType); } } else { log.LogInformation("enter else statement"); } return; }
public static async Task RaiseWorkflowEventAsync( this IDurableOrchestrationClient client, string instanceId, WorkflowEvent workflowEvent) { ThrowIfNullArgument(instanceId, nameof(instanceId)); ThrowIfNullArgument(workflowEvent, nameof(workflowEvent)); DurableOrchestrationStatus?status = await client.GetStatusAsync(instanceId, showInput : false); if (status == null) { throw new NotSupportedException(); } else if (status.RuntimeStatus == OrchestrationRuntimeStatus.Completed || status.RuntimeStatus == OrchestrationRuntimeStatus.Terminated || status.RuntimeStatus == OrchestrationRuntimeStatus.Failed) { throw new InvalidOperationException($"Cannot send events to '{instanceId}' because it is in the {status.RuntimeStatus} state."); } await client.RaiseEventAsync( instanceId, WorkflowEvent.ExternalEventName, workflowEvent); }
public static async Task HandleStockLeased( [ServiceBusTrigger("stock-unleased", "orchestrator", Connection = "ServiceBus")] Message message, [DurableClient] IDurableOrchestrationClient client) { var @event = JsonConvert.DeserializeObject <StockUnleasedEvent>(Encoding.UTF8.GetString(message.Body)); await client.RaiseEventAsync(message.ReplyTo, "stock-unleased", @event); }
public Task HandleReplyDequeue( [ServiceBusTrigger("%" + Constants.ReplyQueueNameVariableName + "%")] Message queueMessage, [DurableClient] IDurableOrchestrationClient orchestrationClient) { var reply = JsonSerializer.Deserialize <QueueReplyDto>(queueMessage.Body); return(orchestrationClient.RaiseEventAsync(reply.OrchestrationId, Constants.RequestProcessedEventName, reply)); }
public static async Task RaiseGameDayPlayerUnavailable( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "Games/{gameId}/Players/{player}/Unavailable")] HttpRequestMessage requestMessage, [DurableClient] IDurableOrchestrationClient starter, string gameId, string player, ILogger log) { await starter.RaiseEventAsync($"{gameId}:{player}", "GameDay_Event_PlayerUnavailable"); }
public static Task RejectProposal( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "reject-proposal/{proposalId}")] HttpRequestMessage req, string proposalId, [DurableClient] IDurableOrchestrationClient client, ILogger log) { return(client.RaiseEventAsync(proposalId, "ApprovalEvent", false)); }
public static async Task ChallengeResponse( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req, [DurableClient] IDurableOrchestrationClient client, ILogger log) { var instanceId = req.Query["instanceId"]; var verificationCode = int.Parse(req.Query["verificationCode"]); log.LogInformation($"Sending response with verificationCode {verificationCode}"); await client.RaiseEventAsync(instanceId, "verificationCodeSended", verificationCode); }
public static async Task <IActionResult> UnlockTrip( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "tripmanager/{code}")] HttpRequest req, string code, [DurableClient] IDurableOrchestrationClient context, ILogger log) { await context.RaiseEventAsync(code, "RiderUnlockedAndStarted", code); return(new OkObjectResult("OK")); }
public async Task <IActionResult> ApprovalRequestResponseHttp( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "approval")] HttpRequestMessage req, [DurableClient] IDurableOrchestrationClient orchestrationClient) { var response = await req.Content.ReadAsAsync <ApprovalResponse>(); await orchestrationClient.RaiseEventAsync(response.InstanceId, Constants.Events.Approval, response.Response); return(new AcceptedResult()); }
public async Task SignalTasksCompleted(TaskExecutionRequest request) { if (request.TaskOrchestratorInstanceId != CurrentRequest.TaskOrchestratorInstanceId) { // this would be bad but should never happen } CurrentRequest = null; await client.RaiseEventAsync(request.TaskOrchestratorInstanceId, "TasksCompleted", null); await RunNextTaskIfComputeIsAvailable(); }
public static async Task stepResultCallback( [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestMessage req, [DurableClient] IDurableOrchestrationClient cli, ILogger log) { string eventName = req.RequestUri.ParseQueryString().Get("eventName"); string status = req.RequestUri.ParseQueryString().Get("status"); log.LogInformation($"RECEIVED FEEDBACK FROM {eventName} WITH STATUS {status}"); await cli.RaiseEventAsync(req.RequestUri.ParseQueryString().Get("instanceId"), eventName, status); }
public static async Task ManagerApproval( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req, [DurableClient] IDurableOrchestrationClient starter, ILogger log) { log.LogInformation("ManagerApproval begin"); await starter.RaiseEventAsync(InstanceId, "ManagerPaymentApproval", await req.Content.ReadAsAsync <bool>()); log.LogInformation("ManagerApproval end"); }
public async Task Run( [DurableClient] IDurableOrchestrationClient client, [ActivityTrigger] IDurableActivityContext context, ILogger log) { var command = context.GetInput <SaveApplicationCommand>(); var applicationToSave = _mapper.Map <SaveApplicationCommand, DataStorage.Models.Application>(command); var saveResult = await _applicationRepository.Create(applicationToSave); if (!saveResult.Success) { this.LogError(log, context.InstanceId, string.Join(',', saveResult.Errors.Select(x => x.Value))); var eventToDispatch = new ApplicationSaveFailedInternalFunctionEvent(saveResult.Errors); await client.RaiseEventAsync(context.InstanceId, nameof(ApplicationSaveFailedInternalFunctionEvent), eventToDispatch); return; } var applicationSavedEvent = new ApplicationSavedInternalFunctionEvent(applicationToSave); await client.RaiseEventAsync(context.InstanceId, nameof(ApplicationSavedInternalFunctionEvent), applicationSavedEvent); }
public async Task Run( [DurableClient] IDurableOrchestrationClient client, [ActivityTrigger] IDurableActivityContext context, ILogger log) { var command = context.GetInput <UploadCvCommand>(); var saveCvResult = await _fileWriter.Write( FileStore.CvsContainer, command.Content, command.ContentType, _fileNameProvider.GetFileName(context.InstanceId, command.Extension)); if (!saveCvResult.Success) { log.LogErrors($"Uploading cv failed instanceId: {context.InstanceId}", saveCvResult.Errors); var failedEvent = new CvUploadFailedInternalFunctionEvent(saveCvResult.Errors); await client.RaiseEventAsync(context.InstanceId, nameof(CvUploadFailedInternalFunctionEvent), failedEvent); } var eventToDispatch = new CvUploadedInternalFunctionEvent(saveCvResult.Value); await client.RaiseEventAsync(context.InstanceId, nameof(CvUploadedInternalFunctionEvent), eventToDispatch); }
public async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "AssessSalesAnalysis/{instanceId}/{approved:bool}")] HttpRequestMessage req, string instanceId, bool approved, [DurableClient] IDurableOrchestrationClient orchestrationClient) { log.LogDebug($"Requesting results for instance id: '{instanceId}'"); await orchestrationClient.RaiseEventAsync(instanceId, FunctionConstants.ApprovalEvent, approved); return(new OkObjectResult(GetAssessmentMessage(approved))); }
public static async Task <HttpResponseMessage> HttpStart( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "orchestrators/approvePayments/{instanceId}")] HttpRequestMessage req, [DurableClient] IDurableOrchestrationClient starter, string instanceId, ILogger log) { log.LogInformation($"Approving payments for orchestrator instance {instanceId}"); await starter.RaiseEventAsync(instanceId, "PaymentsApproved", true); log.LogInformation($"Approved payments for orchestrator instance {instanceId}"); return(req.CreateResponse(HttpStatusCode.OK)); }
public async Task <HttpResponseMessage> AddSignEvent( [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestMessage req, [DurableClient] IDurableOrchestrationClient orchestrationClient, ILogger log) { AddSignEventModel model = await req.Content.ReadAsAsync <AddSignEventModel>(); string instanceId = model.InstanceId; SigningEvent eventData = model.EventData; await orchestrationClient.RaiseEventAsync(instanceId, SignEvent, eventData); log.LogInformation("Sign event raised to instance {InstanceId}", instanceId); return(req.CreateResponse(HttpStatusCode.NoContent)); }
public static async Task <IActionResult> Run1( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, [DurableClient] IDurableOrchestrationClient client, ILogger log) { string instancei = req.Query["instanceid"]; string eventname = req.Query["eventname"]; string eventvalue = req.Query["eventvalue"]; await client.RaiseEventAsync(instancei, eventname, eventvalue); return(new OkObjectResult("ok")); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, HttpVerbs.GET, Route = "ApproveArticle")] HttpRequestMessage req, [DurableClient] IDurableOrchestrationClient client, ILogger logger) { var keys = req.RequestUri.ParseQueryString(); var approveResponse = new ApproveElement { InstanceId = keys.Get("InstanceId"), Result = bool.Parse(keys.Get("ApproveValue")) }; await client.RaiseEventAsync(approveResponse.InstanceId, ConfirmationTask.ConfirmArticleHuman, approveResponse.Result); return(new AcceptedResult()); }