public static async Task <HttpResponseMessage> Run( [HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "hotelgroups/{code}/signals/{signal}")] HttpRequestMessage req, [OrchestrationClient] DurableOrchestrationClient context, string code, string signal, TraceWriter log) { string json = await req.Content.ReadAsStringAsync(); HotelGroupActorState initialState = JsonConvert.DeserializeObject <HotelGroupActorState>(json); var hotelGroupActorStatus = await context.GetStatusAsync(code); string runningStatus = hotelGroupActorStatus == null ? "NULL" : hotelGroupActorStatus.RuntimeStatus.ToString(); log.Info($"Instance running status: '{runningStatus}'."); if (hotelGroupActorStatus == null || hotelGroupActorStatus.RuntimeStatus != OrchestrationRuntimeStatus.Running) { await context.StartNewAsync("HotelGroupActor", code, initialState); log.Info($"Started a new hotel group actor with code = '{code}'."); } else { await context.RaiseEventAsync(code, "operation", signal); log.Info($"Signaled an existing hotel group actor with code '{code}' and signal '{signal}'."); } var res = context.CreateCheckStatusResponse(req, code); res.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(10)); return(res); }
public static async Task <int> RefreshMemberships([ActivityTrigger] HotelGroupActorState state, TraceWriter log) { var digitalMemberships = new List <string>(); DateTime now = DateTime.Now; string formatDate = now.ToString("MM/dd/yyyy hh:mm:ss.fff tt"); log.Info($"**** start refresh request for '{state.Code}' @ {formatDate}"); // For testing only... if (state.RefreshCounter < state.MaxTestCounter) { digitalMemberships.Add("TEST"); } now = DateTime.Now; formatDate = now.ToString("MM/dd/yyyy hh:mm:ss.fff tt"); log.Info($"**** end refresh request for '{state.Code}' @ {formatDate}"); return(digitalMemberships.Count); }
public static async Task <HotelGroupActorState> Run( [OrchestrationTrigger] DurableOrchestrationContext context, TraceWriter log) { HotelGroupActorState state = context.GetInput <HotelGroupActorState>(); log.Info($"HotelGroupActor starting with refresh counter: {state.RefreshCounter} and isTest: {state.IsTest}"); string operation = "refresh"; using (var cts = new CancellationTokenSource()) { var operationTask = context.WaitForExternalEvent <string>("operation"); DateTime deadline = context.CurrentUtcDateTime.AddMinutes(state.MinutesBetweenInvocations); var timeoutTask = context.CreateTimer(deadline, cts.Token); Task winner = await Task.WhenAny(operationTask, timeoutTask); if (winner == operationTask) { log.Info($"An operation event received!"); operation = operationTask.Result; // Cancel the timer cts.Cancel(); } else { // Default the timeout task to mean a 'refresh' operation log.Info($"A timeout event received!"); operation = "refresh"; } } log.Info($"***** received '{operation}' event."); operation = operation?.ToLowerInvariant(); if (operation == "refresh") { state.UpTimeInMinutes += state.MinutesBetweenInvocations; log.Info($"Calling the refresh memberships function {state.UpTimeInMinutes}"); var memberships = 0; memberships = await context.CallActivityAsync <int>("RefreshMemberships", state); state.RefreshCounter += memberships; log.Info($"Resuming after the refresh memberships function: {state.RefreshCounter}"); string reason = $"Simulate an end due to no more memberships"; if (memberships == 0) { log.Info(reason); state.EndReason = reason; operation = "end"; } else if (state.UpTimeInMinutes >= state.MaxMinutesToRun) { reason = $"Simulate an end due to max run time reached"; log.Info(reason); state.EndReason = reason; operation = "end"; } } else { // Support other operations } if (operation != "end") { log.Info($"Re-enqueing the state"); context.ContinueAsNew(state); } if (operation == "end") { // Externalize the state to email, SMS or both - trigger a logic app } return(state); }