// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 using System; using System.IO; using System.Threading.Tasks; using Amazon.DynamoDBv2; using Amazon.ECS; using Amazon.Lambda.Core; using Amazon.Scheduler; using ManagementConsoleBackend.Common; using ManagementConsoleBackend.ManagementService.Data; using ManagementConsoleBackend.ManagementService.Lib; using Newtonsoft.Json; namespace ManagementConsoleBackend.ManagementService; public class ScheduledActionInput { public string LaunchId; public string Type; } public class VirtualPlayerTaskScheduledAction { /// /// Lookup schedule and perform task/launch termination accordingly /// public async Task ScheduledActionHandler(Stream stream, ILambdaContext context) { var eventStr = Utils.ReadEventStream(stream); LambdaLogger.Log(eventStr); var schedulerHandler = new SchedulerHandler(new AmazonSchedulerClient()); var schedules = await schedulerHandler.GetSchedules(); var dynamoDbRequestHandler = new DynamoDbRequestHandler(new AmazonDynamoDBClient()); var virtualPlayersHandler = new VirtualPlayersHandler(new AmazonECSClient()); try { var actionInput = JsonConvert.DeserializeObject(eventStr); if (actionInput != null) { LambdaLogger.Log(actionInput.Type); LambdaLogger.Log(actionInput.LaunchId); if (actionInput.Type == "Launch") { // check if this schedule is still meant to be active if (schedules.LaunchSchedule.State == ScheduleState.DISABLED) { LambdaLogger.Log("SCHEDULE DISABLED"); return false; } var scheduleInput = JsonConvert.DeserializeObject(schedules.LaunchSchedule.Target.Input); if (scheduleInput==null || scheduleInput.LaunchId != actionInput.LaunchId) { LambdaLogger.Log("THIS REQUEST IS FOR AN OLD LAUNCH SCHEDULE - EXITING..."); return false; } } var scheduleLaunchRequest = await dynamoDbRequestHandler.GetLaunchRequest(actionInput.LaunchId); LambdaLogger.Log(JsonConvert.SerializeObject(scheduleLaunchRequest)); for (var i = 0; i < scheduleLaunchRequest.Schedule.Actions.Count; i++) { if (scheduleLaunchRequest.Schedule.Actions[i].Status != "Scheduled" || scheduleLaunchRequest.Schedule.Actions[i].Type != actionInput.Type) { continue; } var currentAction = scheduleLaunchRequest.Schedule.Actions[i]; scheduleLaunchRequest.Schedule.Actions[i].StartedTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); scheduleLaunchRequest.Schedule.Actions[i].Status = "Executing"; await dynamoDbRequestHandler.SaveLaunchRequest(scheduleLaunchRequest); switch (currentAction.Type) { case "Launch": { var launchTaskRequest = await virtualPlayersHandler.LaunchPlayers(currentAction.NumTasks, scheduleLaunchRequest.TaskDefinitionArn, scheduleLaunchRequest.CapacityProvider, null, null, scheduleLaunchRequest); if (launchTaskRequest != null) { scheduleLaunchRequest.Schedule.Actions[i].Status = "Completed"; scheduleLaunchRequest.Schedule.Actions[i].LaunchId = launchTaskRequest.LaunchId; } else { scheduleLaunchRequest.Schedule.Actions[i].Status = "Failed"; } break; } case "Terminate": { var errors = await virtualPlayersHandler.TerminateVirtualPlayerTasksByLaunchIdTag(scheduleLaunchRequest.LaunchId); scheduleLaunchRequest.Schedule.Actions[i].Status = errors.Count == 0 ? "Completed" : "Failed"; break; } } scheduleLaunchRequest.Schedule.Actions[i].EndedTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); await dynamoDbRequestHandler.SaveLaunchRequest(scheduleLaunchRequest); await ManagementService.SendToActiveConnections(new ServerMessageScheduleProgress { Schedule = scheduleLaunchRequest.Schedule, ActionIndex = i, }); break; } var remainingLaunchTasks = scheduleLaunchRequest.Schedule.Actions.FindAll(x => x.Status == "Scheduled" && x.Type == "Launch").Count; var remainingTerminateTasks = scheduleLaunchRequest.Schedule.Actions.FindAll(x => x.Status == "Scheduled" && x.Type == "Terminate").Count; if (remainingLaunchTasks != 0 && remainingTerminateTasks != 0) { return true; } // disable schedule if (remainingLaunchTasks == 0) { LambdaLogger.Log("DISABLING LAUNCH SCHEDULE"); await schedulerHandler.DisableSchedule(schedules.LaunchSchedule); } if (remainingTerminateTasks != 0) { return true; } LambdaLogger.Log("DISABLING TERMINATE SCHEDULE"); await schedulerHandler.DisableSchedule(schedules.TerminateSchedule); return true; } } catch (Exception e) { Console.WriteLine(e); throw; } return false; } }