public async Task Handle(CompleteComponentWorkCommand command) { var eventStore = await CaPMIngestEventStore.GetCaPMEventStore(_stagingStoreContainer, command.IngestId); var allPreviousEvents = await eventStore.GetStoredEvents(); //In case the component has already been considered timeout out (or, for some erraneous reason //has already reported that it has errored or completed) we want to ignore this message. var currentlyExecutingComponent = allPreviousEvents.GetFirstNonCompletedComponentInCurrentPlan(); if (currentlyExecutingComponent.HasValue && currentlyExecutingComponent.Value.ComponentExecutionId == command.ComponentExecutionId) { if (currentlyExecutingComponent.Value.IsCompensatingComponent) { await eventStore.StoreEvent(new IngestComponentCompensationCompleted { ComponentExecutionId = command.ComponentExecutionId }, _messageSenderFactory.GetChannel <SerializedEvent>(_componentChannelIdentifierRepository.GetChannelIdentifierFor(IngestEventConstants.ChannelIdentifierCode))); } else { await eventStore.StoreEvent(new IngestComponentWorkCompleted() { ComponentExecutionId = command.ComponentExecutionId }, _messageSenderFactory.GetChannel <SerializedEvent>(_componentChannelIdentifierRepository.GetChannelIdentifierFor(IngestEventConstants.ChannelIdentifierCode))); } await _componentPlanExecutor.ExecuteNextComponentInPlan(command.IngestId); } }
public async Task Handle(FailComponentWorkCommand command) { var eventStore = await CaPMIngestEventStore.GetCaPMEventStore(_stagingStoreContainer, command.IngestId); var allPreviousEvents = await eventStore.GetStoredEvents(); //In case the component has already been considered timeout out (or, for some erraneous reason //has already reported that it has errored or completed) we want to ignore this message. var currentlyExecutingComponent = allPreviousEvents.GetFirstNonCompletedComponentInCurrentPlan(); if (currentlyExecutingComponent.HasValue && currentlyExecutingComponent.Value.ComponentExecutionId == command.ComponentExecutionId) { var previousPlan = allPreviousEvents.OfType <IngestPlanSet>().Last(); if (currentlyExecutingComponent.Value.IsCompensatingComponent) { await eventStore.StoreEvent(new IngestComponentCompensationFailed() { ComponentExecutionId = command.ComponentExecutionId, Reason = command.Reason }, _messageSenderFactory.GetChannel <SerializedEvent>(_componentChannelIdentifierRepository.GetChannelIdentifierFor(IngestEventConstants.ChannelIdentifierCode))); await _componentPlanExecutor.ExecuteNextComponentInPlan(command.IngestId); } else { await eventStore.StoreEvent(new IngestComponentWorkFailed() { ComponentExecutionId = command.ComponentExecutionId, Reason = command.Reason }, _messageSenderFactory.GetChannel <SerializedEvent>(_componentChannelIdentifierRepository.GetChannelIdentifierFor(IngestEventConstants.ChannelIdentifierCode))); var ingestPlan = new IngestPlanSet() { IngestPlan = previousPlan.IngestPlan .Reverse() //Only compensate actions which have finished successfully .Where(p => p.ComponentExecutionId == command.ComponentExecutionId || allPreviousEvents.OfType <IngestComponentWorkCompleted>().Select(e => e.ComponentExecutionId).Contains(p.ComponentExecutionId)) .Select((eventToCompensate, index) => new IngestPlanSet.IngestPlanEntry() { ComponentCode = eventToCompensate.ComponentCode, ComponentSettings = eventToCompensate.ComponentSettings, ComponentExecutionId = Guid.NewGuid(), IsCompensatingComponent = true, Order = (uint)index }).ToArray() }; await eventStore.StoreEvent(ingestPlan, _messageSenderFactory.GetChannel <SerializedEvent>(_componentChannelIdentifierRepository.GetChannelIdentifierFor(IngestEventConstants.ChannelIdentifierCode))); await _componentPlanExecutor.ExecuteNextComponentInPlan(command.IngestId); } } }
internal static void Start(IChannelProvider channelProvider, IComponentChannelIdentifierRepository componentChannelIdentifierRepository, IHubContext <IngestEventsHub> hubContext) { channelProvider.GetMessageSource <SerializedEvent>(componentChannelIdentifierRepository.GetChannelIdentifierFor(IngestEventConstants.ChannelIdentifierCode)).GetChannel().Subscribe(evt => { hubContext.Clients.All.SendAsync("onNewEvent", evt.GetEventObject()); }); }
public IDisposable RegisterCommandHandler <Command, CommandHandler>(string messageChannelIdentifierCode) where CommandHandler : ICommandHandler <Command> { ChannelIdentifier messageChannelIdentifier = _componentChannelIdentifierRepository.GetChannelIdentifierFor(messageChannelIdentifierCode); return(_channelProvider.RegisterCommandHandler <Command, CommandHandler>(messageChannelIdentifier, _iocLifetimeScope)); }
public async Task ExecuteNextComponentInPlan(Guid ingestId) { var eventStore = await GetCaPMEventStore(ingestId); var storedEvents = await eventStore.GetStoredEvents(); var firstNonCompletedComponentInPlan = storedEvents.GetFirstNonCompletedComponentInCurrentPlan(); if (firstNonCompletedComponentInPlan.HasValue) { if (firstNonCompletedComponentInPlan.Value.IsCompensatingComponent) { await ExecuteComponentCompensation(ingestId, firstNonCompletedComponentInPlan.Value); } else { await ExecuteComponentWork(ingestId, firstNonCompletedComponentInPlan.Value); } } else { await eventStore.StoreEvent(new IngestCompleted(), _messageSenderFactory.GetChannel <SerializedEvent>(_componentChannelIdentifierRepository.GetChannelIdentifierFor(IngestEventConstants.ChannelIdentifierCode))); } }
public async Task Post([FromBody] StartIngestionModel model) { if (ModelState.IsValid) { var capmMessageChannelIdentifier = _componentChannelIdentifierRepository.GetChannelIdentifierFor(CaPMSystem.CaPMComponentIdentifier); var capmMessageChannel = _messageSenderFactory.GetChannel <StartIngestCommand>(capmMessageChannelIdentifier); await capmMessageChannel.Send(new StartIngestCommand() { SubmissionAgreementId = model.SubmissionAgreementId, IngestParameters = model.IngestParameters }); } else { throw new ArgumentException("Invalid model posted. " + System.Text.Json.JsonSerializer.Serialize(ModelState)); } }
public async Task Handle(StartIngestCommand command) { // We currently assume that the service that have sent the StartIngestCommand has already verified that the caller has authority // to invoke the specified submission agreement, so we just use the agreement specified. SubmissionAgreement submissionAgreement; try { submissionAgreement = _submissionAgreementStore.Get(command.SubmissionAgreementId); } catch (KeyNotFoundException) { Debug.WriteLine($"There is no submission agreement with the ID '{command.SubmissionAgreementId}'. Aborting!"); return; } var newIngestId = Guid.NewGuid(); var ingestStartedEvent = new IngestStarted() { IngestParameters = command.IngestParameters, ExternalContextId = command.ExternalContextId }; var eventStore = await CaPMIngestEventStore.CreateCaPMEventStore(_stagingStoreContainer, newIngestId).ConfigureAwait(false); await eventStore.StoreEvent(ingestStartedEvent, _messageSenderFactory.GetChannel <SerializedEvent>(_componentChannelIdentifierRepository.GetChannelIdentifierFor(IngestEventConstants.ChannelIdentifierCode))).ConfigureAwait(false); await CreateIngestPlanBasedOnSubmissionAgreement(eventStore, submissionAgreement).ConfigureAwait(false); await _componentPlanExecutor.ExecuteNextComponentInPlan(newIngestId).ConfigureAwait(false); }