public static async Task <IActionResult> StartTripDemo([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "tripdemos")] HttpRequest req, [OrchestrationClient] DurableOrchestrationClient context, ILogger log) { try { string requestBody = new StreamReader(req.Body).ReadToEnd(); TripDemoState demoState = JsonConvert.DeserializeObject <TripDemoState>(requestBody); // The demo instance id is the trip code + -D. This is to make sure that a Trip Manager and a monitor can co-exist var instanceId = $"{demoState.Code}-D"; await StartInstance(context, demoState, instanceId, log); //NOTE: Unfortunately this does not work the same way as before when it was using HttpMessageResponse //var reqMessage = req.ToHttpRequestMessage(); //var res = context.CreateCheckStatusResponse(reqMessage, trip.Code); //res.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(10)); //return (ActionResult)new OkObjectResult(res.Content); return((ActionResult) new OkObjectResult("NOTE: No status URLs are returned!")); } catch (Exception ex) { var error = $"StartTripDemo failed: {ex.Message}"; log.LogError(error); return(new BadRequestObjectResult(error)); } }
public static async Task <TripDemoState> RetrieveRouteItems([ActivityTrigger] TripDemoState state, ILogger log) { log.LogInformation($"RetrieveRouteItems starting...."); // Supply the trip source & destination points state.RouteLocations = await ServiceFactory.GetRoutesService().RetrieveRouteItems(state.Source, state.Destination); return(state); }
public async Task Enqueue(TripDemoState tripDemoState) { await InitializeStorage(); if (_tripDemosQueue != null) { await _tripDemosQueue.SendMessageAsync(JsonConvert.SerializeObject(tripDemoState)); } }
public async Task Enqueue(TripDemoState tripDemoState) { await InitializeStorage(); if (_tripDemosQueue != null) { var queueMessage = new CloudQueueMessage(JsonConvert.SerializeObject(tripDemoState)); await _tripDemosQueue.AddMessageAsync(queueMessage); } }
public static async Task StartTripDemoViaQueueTrigger( [OrchestrationClient] DurableOrchestrationClient context, [QueueTrigger("%TripDemosQueue%", Connection = "AzureWebJobsStorage")] TripDemoState demoState, ILogger log) { try { // The demo instance id is the trip code + -D. This is to make sure that a Trip Manager and a monitor can co-exist var instanceId = $"{demoState.Code}-D"; await StartInstance(context, demoState, instanceId, log); } catch (Exception ex) { var error = $"StartTripDemoViaQueueTrigger failed: {ex.Message}"; log.LogError(error); } }
//TODO: Implement Get Trip Demo Instances, Restart Trip Demo Instances and Terminate Trip Demo Instances if Persist to table storage if persist instances is activated /** PRIVATE **/ private static async Task StartInstance(DurableOrchestrationClient context, TripDemoState state, string instanceId, ILogger log) { try { var reportStatus = await context.GetStatusAsync(instanceId); string runningStatus = reportStatus == null ? "NULL" : reportStatus.RuntimeStatus.ToString(); log.LogInformation($"Instance running status: '{runningStatus}'."); if (reportStatus == null || reportStatus.RuntimeStatus != OrchestrationRuntimeStatus.Running) { await context.StartNewAsync("O_DemoTrip", instanceId, state); log.LogInformation($"Started a new trip demo = '{instanceId}'."); // TODO: Persist to table storage if persist instances is activated } } catch (Exception ex) { throw ex; } }
public static async Task Cleanup([ActivityTrigger] TripDemoState state, ILogger log) { log.LogInformation($"Cleanup for {state.Code} starting...."); // TODO: Really nothing to do }
public static async Task <object> DemoTrip( [OrchestrationTrigger] DurableOrchestrationContext context, ILogger log) { TripDemoState state = context.GetInput <TripDemoState>(); if (!context.IsReplaying) { log.LogInformation($"DemoTrip {state.Code} starting....."); } try { var trip = await context.CallActivityAsync <TripItem>("A_TD_RetrieveTrip", state.Code); if (trip == null) { throw new Exception($"Trip with code {trip.Code} is not found!"); } if (trip.EndDate != null) { throw new Exception($"Trip with code {trip.Code} already ended!"); } if (trip.Type == TripTypes.Normal) { throw new Exception($"Trip with code {trip.Code} is not a demo!"); } // Retrieve time settings var settings = await context.CallActivityAsync <TripTimeSettings>("A_TD_RetrieveSettings", trip.Code); // Run every x seconds DateTime nextUpdate = context.CurrentUtcDateTime.AddSeconds(settings.IntervalInSeconds); await context.CreateTimer(nextUpdate, CancellationToken.None); // Retrieve trip route locations if needed if (state.RouteLocations.Count == 0) { state = await context.CallActivityAsync <TripDemoState>("A_TD_RetrieveRouteItems", state); } if (state.RouteLocations.Count == 0) { throw new Exception($"Trip with code {trip.Code} has no routes!"); } // Assign a driver if (trip.Driver == null && trip.AvailableDrivers.Count > 0) { await context.CallActivityAsync("A_TD_AssignDriver", trip); } // Navigate to a new route location if (trip.Driver != null) { state = await context.CallActivityAsync <TripDemoState>("A_TD_Navigate", new TripDemoInfo() { State = state, Trip = trip }); } // Check for completion if (state.CurrentRouteIndex < state.RouteLocations.Count) { // Reload the instance with a new state context.ContinueAsNew(state); } } catch (Exception e) { if (!context.IsReplaying) { log.LogInformation($"Caught an error from an activity: {e.Message}"); } await context.CallActivityAsync <string>("A_TO_Cleanup", state); return(new { Error = "Failed to process trip", Message = e.Message }); } return(new { State = state }); }
public async Task TripCreated(TripItem trip, int activeTrips) { var error = ""; try { // Start a trip manager if (!_settingService.IsEnqueueToOrchestrators()) { var baseUrl = _settingService.GetStartTripManagerOrchestratorBaseUrl(); var key = _settingService.GetStartTripManagerOrchestratorApiKey(); if (string.IsNullOrEmpty(baseUrl) || string.IsNullOrEmpty(key)) { throw new Exception("Trip manager orchestrator base URL and key must be both provided"); } await Utilities.Post <dynamic, dynamic>(null, trip, $"{baseUrl}/tripmanagers?code={key}", new Dictionary <string, string>()); } else { await _storageService.Enqueue(trip); } // Send an event telemetry _loggerService.Log("Trip created", new Dictionary <string, string> { { "Code", trip.Code }, { "Passenger", $"{trip.Passenger.FirstName} {trip.Passenger.LastName}" }, { "Destination", $"{trip.Destination.Latitude} - {trip.Destination.Longitude}" }, { "Mode", $"{trip.Type}" } }); // Send a metric telemetry _loggerService.Log("Active trips", activeTrips); if (trip.Type == TripTypes.Demo) { var tripDemoState = new TripDemoState(); tripDemoState.Code = trip.Code; tripDemoState.Source = new TripLocation() { Latitude = trip.Source.Latitude, Longitude = trip.Source.Longitude }; tripDemoState.Destination = new TripLocation() { Latitude = trip.Destination.Latitude, Longitude = trip.Destination.Longitude }; if (!_settingService.IsEnqueueToOrchestrators()) { var baseUrl = _settingService.GetStartTripDemoOrchestratorBaseUrl(); var key = _settingService.GetStartTripDemoOrchestratorApiKey(); if (string.IsNullOrEmpty(baseUrl) || string.IsNullOrEmpty(key)) { throw new Exception("Trip demo orchestrator base URL and key must be both provided"); } await Utilities.Post <dynamic, dynamic>(null, tripDemoState, $"{baseUrl}/tripdemos?code={key}", new Dictionary <string, string>()); } else { await _storageService.Enqueue(tripDemoState); } } } catch (Exception ex) { error = $"Error while starting the trip manager: {ex.Message}"; throw new Exception(error); } finally { _loggerService.Log($"{LOG_TAG} - TripCreated - Error: {error}"); } }