/// <summary> /// Updates the state of a command on the server side. /// </summary> public async Task UpdateCommand(ScheduledCommand command) { if (Connected) { await hubConnection.SendAsync("UpdateCommand", new[] { command }); } }
public override async Task When_a_clock_is_set_on_a_command_then_it_takes_precedence_over_GetClockName() { // arrange var clockName = Any.CamelCaseName(); var targetId = Any.CamelCaseName(); var command = new CreateCommandTarget(targetId); var scheduledCommand = new ScheduledCommand <CommandTarget>( targetId: targetId, command: command, dueTime: DateTimeOffset.Parse("2016-03-20 09:00:00 AM")) { Clock = new CommandScheduler.Clock { Name = clockName, UtcNow = DateTimeOffset.Parse("2016-03-01 02:00:00 AM") } }; // act await scheduler.Schedule(scheduledCommand); await Configuration.Current.SchedulerClockTrigger() .AdvanceClock(clockName, by: 30.Days()); //assert var target = await store.Get(targetId); target.Should().NotBeNull(); }
private async Task ServerClient_ServerCommandRecieved(ScheduledCommand command) { switch (command.Name) { case "arm": await RunRequestedCommand(async() => { return(await Arm()); }, command); break; case "disarm": await RunRequestedCommand(async() => { return(await Disarm()); }, command); break; case "alarm": await RunRequestedCommand(async() => { return(await Alarm()); }, command); break; case "silence": await RunRequestedCommand(async() => { return(await Silence()); }, command); break; } }
public void A_ScheduledCommand_with_an_non_event_sourced_target_has_a_null_AggregateId() { var command = new ScheduledCommand <NonEventSourcedCommandTarget>(new NonEventSourcedCommandTarget.TestCommand(), Any.Guid().ToString()); command.AggregateId.Should().Be(null); }
protected static async Task ScheduleCommandAgainstEventSourcedAggregate( string targetId, string etag, DateTimeOffset?dueTime = null, IPrecondition deliveryDependsOn = null) { var aggregateId = Guid.Parse(targetId); var repository = Configuration.Current.Repository <Order>(); if (await repository.GetLatest(aggregateId) == null) { await repository.Save(new Order(new CreateOrder(Any.FullName()) { AggregateId = aggregateId })); } var command = new AddItem { ETag = etag, ProductName = Any.Word(), Price = 10m }; var scheduledCommand = new ScheduledCommand <Order>( command, aggregateId, dueTime, deliveryDependsOn); var scheduler = Configuration.Current.CommandScheduler <Order>(); await scheduler.Schedule(scheduledCommand); }
public void HandleCommand(ByteReader data) { ScheduledCommand cmd = ScheduledCommand.Deserialize(data); cmd.issuedBySelf = data.ReadBool(); OnMainThread.ScheduleCommand(cmd); }
/// <summary> /// Deserializes a scheduled command from SQL storage and delivers it to the target. /// </summary> /// <param name="configuration">The configuration.</param> /// <param name="serializedCommand">The serialized command.</param> /// <param name="db">The command scheduler database context.</param> public static async Task DeserializeAndDeliver( this Configuration configuration, ScheduledCommand serializedCommand, CommandSchedulerDbContext db) => await DeserializeAndDeliver( configuration.Container.Resolve <CommandDelivererResolver>(), serializedCommand, db);
public static Map GetMap(this ScheduledCommand cmd) { if (cmd.mapId == ScheduledCommand.Global) { return(null); } return(Find.Maps.Find(map => map.uniqueID == cmd.mapId)); }
public static Faction GetFaction(this ScheduledCommand cmd) { if (cmd.factionId == ScheduledCommand.NoFaction) { return(null); } return(Find.FactionManager.GetById(cmd.factionId)); }
public void HandleCommand(ByteReader data) { ScheduledCommand cmd = ScheduledCommand.Deserialize(data); cmd.issuedBySelf = data.ReadBool(); OnMainThread.ScheduleCommand(cmd); Multiplayer.session.localCmdId++; Multiplayer.session.ProcessTimeControl(); }
public void HandleWorldData(ByteReader data) { connection.State = ConnectionStateEnum.ClientPlaying; Log.Message("Game data size: " + data.Length); int factionId = data.ReadInt32(); Multiplayer.session.myFactionId = factionId; int tickUntil = data.ReadInt32(); byte[] worldData = GZipStream.UncompressBuffer(data.ReadPrefixedBytes()); OnMainThread.cachedGameData = worldData; List <int> mapsToLoad = new List <int>(); int mapCmdsCount = data.ReadInt32(); for (int i = 0; i < mapCmdsCount; i++) { int mapId = data.ReadInt32(); int mapCmdsLen = data.ReadInt32(); List <ScheduledCommand> mapCmds = new List <ScheduledCommand>(mapCmdsLen); for (int j = 0; j < mapCmdsLen; j++) { mapCmds.Add(ScheduledCommand.Deserialize(new ByteReader(data.ReadPrefixedBytes()))); } OnMainThread.cachedMapCmds[mapId] = mapCmds; } int mapDataCount = data.ReadInt32(); for (int i = 0; i < mapDataCount; i++) { int mapId = data.ReadInt32(); byte[] rawMapData = data.ReadPrefixedBytes(); byte[] mapData = GZipStream.UncompressBuffer(rawMapData); OnMainThread.cachedMapData[mapId] = mapData; mapsToLoad.Add(mapId); } Multiplayer.session.localCmdId = data.ReadInt32(); TickPatch.tickUntil = tickUntil; TickPatch.SkipTo( toTickUntil: true, onFinish: () => Multiplayer.Client.Send(Packets.Client_WorldReady), cancelButtonKey: "Quit", onCancel: GenScene.GoToMainMenu ); ReloadGame(mapsToLoad); }
protected void AddScheduledCommand(ScheduledCommand command) { if (command == null) { throw new ArgumentNullException(nameof(command)); } _pendingScheduledCommands.Add(command); }
public Task UpdateCommand(ScheduledCommand command) { using (IServiceScope scope = _serviceProvider.CreateScope()) { ApplicationDbContext _context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>(); CommandStatusUpdated?.Invoke(command, _context); return(Task.CompletedTask); } }
internal static ScheduledCommand ToScheduledCommand(this PersistedScheduledCommand instance) { var result = new ScheduledCommand(); result.CommandName = instance.CommandName; result.Data = instance.Data; result.ExecuteTime = instance.ExecuteTime; return(result); }
public static byte[] SerializeCmds(List <ScheduledCommand> cmds) { ByteWriter writer = new ByteWriter(); writer.WriteInt32(cmds.Count); foreach (var cmd in cmds) { writer.WritePrefixedBytes(ScheduledCommand.Serialize(cmd)); } return(writer.ToArray()); }
public async Task Multiple_scheduled_commands_having_the_some_causative_command_etag_have_repeatable_and_unique_etags() { var senderId = Any.Word(); await store.Put(new CommandTarget(senderId)); var targetIds = new[] { Any.Word(), Any.Word(), Any.Word() }; var results = new ConcurrentBag <RequestReply>(); configuration.TraceScheduledCommands( onScheduling: cmd => { var requestReply = ((dynamic)cmd).Command as RequestReply; if (requestReply != null) { results.Add(requestReply); } }); var initialEtag = "initial".ToETag(); var firstCommand = new SendRequests(targetIds) { ETag = initialEtag }; var scheduledCommand = new ScheduledCommand <CommandTarget>( firstCommand, senderId); await scheduler.Deliver(scheduledCommand); var secondCommand = new SendRequests(targetIds) { ETag = initialEtag }; scheduledCommand = new ScheduledCommand <CommandTarget>( secondCommand, senderId); // redeliver await scheduler.Deliver(scheduledCommand); Console.WriteLine(results.ToJson()); results.Should().HaveCount(6); results.Select(r => r.ETag) .Distinct() .Should() .HaveCount(3); }
public async Task Multiple_scheduled_commands_having_the_some_causative_command_etag_have_repeatable_and_unique_etags() { var senderId = Any.Word(); await Save(new NonEventSourcedCommandTarget(senderId)); var targetIds = new[] { Any.Word(), Any.Word(), Any.Word() }; var results = new ConcurrentBag<RequestReply>(); Configuration.Current .TraceScheduledCommands( onScheduling: cmd => { var requestReply = ((dynamic) cmd).Command as RequestReply; if (requestReply != null) { results.Add(requestReply); } }); var initialEtag = "initial".ToETag(); var firstCommand = new SendRequests(targetIds) { ETag = initialEtag }; var scheduledCommand = new ScheduledCommand<NonEventSourcedCommandTarget>( firstCommand, senderId); await Deliver(scheduledCommand); var secondCommand = new SendRequests(targetIds) { ETag = initialEtag }; scheduledCommand = new ScheduledCommand<NonEventSourcedCommandTarget>( secondCommand, senderId); // redeliver await Deliver(scheduledCommand); results.Should().HaveCount(6); results.Select(r => r.ETag) .Distinct() .Should() .HaveCount(3); }
/// <summary> /// Append the data for the given command in a somewhat readable form to the provided string builder /// </summary> /// <param name="builder">The builder to append data to</param> /// <param name="cmd">The command to append</param> private static void PrintCmdInfo(StringBuilder builder, ScheduledCommand cmd) { //Add basic data builder.Append($"{cmd.type} {cmd.ticks} {cmd.mapId} {cmd.factionId}"); //If this is a sync command, add data on the handler used. if (cmd.type == CommandType.Sync) { builder.Append($" {Sync.handlers[BitConverter.ToInt32(cmd.data, 0)]}"); } builder.AppendLine(); }
public void AddScheduledCommand_adds_envelope() { ProcessManager sut = Mock.Of <ProcessManager>(); MethodInfo mut = typeof(ProcessManager).GetMethod( "AddScheduledCommand", BindingFlags.NonPublic | BindingFlags.Instance); var scheduledCommand = new ScheduledCommand(new object(), DateTime.UtcNow); mut.Invoke(sut, new[] { scheduledCommand }); IEnumerable <ScheduledCommand> actual = sut.FlushPendingScheduledCommands(); actual.Should().ContainSingle().Which.Should().BeSameAs(scheduledCommand); }
/// <summary> /// Updates a command in the database with new /// State and Result enum values. /// </summary> /// <param name="commands">ScheduledCommand to update. GUIDs must match.</param> public async Task SetScheduledCommands(ScheduledCommand command) { using (IServiceScope scope = _provider.CreateScope()) { ApplicationDbContext _context = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>(); ScheduledCommand dbCommand = await _context.ScheduledCommands.Select(s => s).Where(p => (p.Id == command.Id)).FirstAsync(); dbCommand.State = command.State; dbCommand.Result = command.Result; _context.ScheduledCommands.Update(dbCommand); await _context.SaveChangesAsync(); } }
private List <ScheduledCommand> DeserializeCmds(byte[] data) { var reader = new ByteReader(data); int count = reader.ReadInt32(); var result = new List <ScheduledCommand>(count); for (int i = 0; i < count; i++) { result.Add(ScheduledCommand.Deserialize(new ByteReader(reader.ReadPrefixedBytes()))); } return(result); }
private static async Task DeserializeAndDeliver( CommandSchedulerResolver schedulerResolver, ScheduledCommand serializedCommand, CommandSchedulerDbContext db) { dynamic scheduler = schedulerResolver.ResolveSchedulerForAggregateTypeNamed(serializedCommand.AggregateType); await Storage.DeserializeAndDeliverScheduledCommand( serializedCommand, scheduler); serializedCommand.Attempts++; await db.SaveChangesAsync(); }
/// <summary> /// Pushes a single command to the controller from the server side. /// Always called when a command is being executed on a live connection. /// </summary> private async Task PushCommandToController(CabinetController controller, ScheduledCommand command) { // Don't send if the controller is offline! if (!ValidateController(controller)) { throw new Exception("The controller is not connected to the hub!"); } if (command.State != CommandState.Scheduled) { throw new Exception("Command is in an incorrect state. It may be invalid or have completed already."); } await _hub.Clients.Client(controller.HubConnectionId)?.SendCoreAsync("RecieveCommand", new[] { command }); }
public async Task ScheduleCommand(ScheduledCommand command) { try { await ScheduledCommands.InsertOneAsync(command); } catch (MongoBulkWriteException ex) { if (ex.WriteErrors.All(x => x.Category == ServerErrorCategory.DuplicateKey)) { return; } throw; } }
public void AddScheduledCommand_appends_envelope() { ProcessManager sut = Mock.Of <ProcessManager>(); MethodInfo mut = typeof(ProcessManager).GetMethod( "AddScheduledCommand", BindingFlags.NonPublic | BindingFlags.Instance); var existingScheduledCommand = new ScheduledCommand(new object(), DateTime.UtcNow); mut.Invoke(sut, new[] { existingScheduledCommand }); var scheduledCommand = new ScheduledCommand(new object(), DateTime.UtcNow); mut.Invoke(sut, new[] { scheduledCommand }); IEnumerable <ScheduledCommand> actual = sut.FlushPendingScheduledCommands(); actual.Should().HaveCount(2).And.HaveElementAt(1, scheduledCommand); }
public async Task ScheduleCommand(ScheduledCommand command) { try { using (var db = ConstructDbContext()) { var persistable = command.ToPersistable(); var result = db.Set <PersistedScheduledCommand>().Add(persistable); await db.SaveChangesAsync(); } } catch (DbUpdateException) { //log } }
/// <summary> /// Handles a command from the server. /// </summary> private async Task HandleCommand(ScheduledCommand command) { // Update the server state of the command command.State = CommandState.InProgress; await UpdateCommand(command); switch (command.Name) { case "arm": await ServerCommandRecieved.Invoke(command); break; case "disarm": await ServerCommandRecieved.Invoke(command); break; case "alarm": await ServerCommandRecieved.Invoke(command); break; case "silence": await ServerCommandRecieved.Invoke(command); break; case "clientDelete": command.State = CommandState.Complete; command.Result = CommandResult.Success; await UpdateCommand(command); await Unenroll(); break; default: // Command is invalid. command.State = CommandState.Complete; command.Result = CommandResult.Invalid; await UpdateCommand(command); break; } }
public static void ScheduleCommand(ScheduledCommand cmd) { MpLog.Log($"Cmd: {cmd.type}, faction: {cmd.factionId}, map: {cmd.mapId}, ticks: {cmd.ticks}"); cachedMapCmds.GetOrAddNew(cmd.mapId).Add(cmd); if (Current.ProgramState != ProgramState.Playing) { return; } if (cmd.mapId == ScheduledCommand.Global) { Multiplayer.WorldComp.cmds.Enqueue(cmd); } else { cmd.GetMap()?.AsyncTime().cmds.Enqueue(cmd); } }
public void HandleMapResponse(ByteReader data) { int mapId = data.ReadInt32(); int mapCmdsLen = data.ReadInt32(); List <ScheduledCommand> mapCmds = new List <ScheduledCommand>(mapCmdsLen); for (int j = 0; j < mapCmdsLen; j++) { mapCmds.Add(ScheduledCommand.Deserialize(new ByteReader(data.ReadPrefixedBytes()))); } OnMainThread.cachedMapCmds[mapId] = mapCmds; byte[] mapData = GZipStream.UncompressBuffer(data.ReadPrefixedBytes()); OnMainThread.cachedMapData[mapId] = mapData; //ClientJoiningState.ReloadGame(TickPatch.tickUntil, Find.Maps.Select(m => m.uniqueID).Concat(mapId).ToList()); // todo Multiplayer.client.Send(Packets.CLIENT_MAP_LOADED); }
/// <summary> /// Queues a new command with the cabinet management controller (CMC). /// </summary> /// <param name="command">The command to send to the controller.</param> /// <param name="data">Additional data to send with the command.</param> public async Task <ScheduledCommand> SendCommandToController(string command, IDictionary <string, dynamic> data = null) { ScheduledCommand scheduledCommand = new ScheduledCommand() { ControllerId = controller.Id, Name = command, UserId = CurrentUserId, Payload = data, State = CommandState.Scheduled, Result = CommandResult.None, TimeCreated = DateTime.Now, }; await _context.ScheduledCommands.AddAsync(scheduledCommand); await _context.SaveChangesAsync(); await PushCommandToController(controller, scheduledCommand); return(scheduledCommand); }
public async Task <IActionResult> Post(Guid id, [FromBody] ScheduledCommand _scheduledCommand) { CabinetController cabinetController = await GetController(id); if (cabinetController == null) { return(GetCommandError(_scheduledCommand, ErrorStrings.ControllerNotFound)); } // Make sure the controller is online ControllerProxy proxy = GetControllerProxy(cabinetController); if (!proxy.ValidateController(cabinetController)) { return(GetCommandError(_scheduledCommand, ErrorStrings.ControllerOffline)); } // Send the command to the proxy ScheduledCommand command = await proxy.SendCommandToController(_scheduledCommand.Name, _scheduledCommand.Payload); return(new JsonResult(command)); }
public async Task Multiple_scheduled_commands_having_the_some_causative_command_etag_have_repeatable_and_unique_etags() { var id = Any.Word(); await store.Put(new CommandTarget(id)); var command = new SendRequests(new[] { Any.Word() }) { ETag = "one".ToETag() }; var scheduled = new ScheduledCommand<CommandTarget>( command, id); await scheduler.Deliver(scheduled); Assert.Fail("Test not written yet."); }
protected static async Task ScheduleCommandAgainstEventSourcedAggregate( string targetId, string etag, DateTimeOffset? dueTime = null, IPrecondition deliveryDependsOn = null) { var aggregateId = Guid.Parse(targetId); var repository = Configuration.Current.Repository<Order>(); if (await repository.GetLatest(aggregateId) == null) { await repository.Save(new Order(new CreateOrder(Any.FullName()) { AggregateId = aggregateId })); } var command = new AddItem { ETag = etag, ProductName = Any.Word(), Price = 10m }; var scheduledCommand = new ScheduledCommand<Order>( command, aggregateId, dueTime, deliveryDependsOn); var scheduler = Configuration.Current.CommandScheduler<Order>(); await scheduler.Schedule(scheduledCommand); }
protected async Task ScheduleCommandAgainstNonEventSourcedAggregate( string targetId, string etag, DateTimeOffset? dueTime = null, IPrecondition deliveryDependsOn = null) { var repository = Configuration.Current.Store<CommandTarget>(); if (await repository.Get(targetId) == null) { await repository.Put(new CommandTarget(targetId)); } var command = new ScheduledCommand<CommandTarget>( new TestCommand(etag), targetId, dueTime, deliveryDependsOn); var scheduler = Configuration.Current.CommandScheduler<CommandTarget>(); await scheduler.Schedule(command); }