/// <summary> /// Extracts a deploy anncouncement. /// </summary> /// <param name="announcement">The announcement that needs to be extracted.</param> /// <param name="token">Token of cancellation.</param> /// <inheritdoc /> /// <exception cref="AggregateException">Throw when one or more fusions failed to extract.</exception> public void Extract(IDeployAnnouncement announcement, CancellationToken token) { EnsureArg.IsNotNull(announcement, nameof(announcement)); var opts = new ParallelOptions { CancellationToken = token }; var fusionIds = announcement.GetFusionIds(); Parallel.ForEach(fusionIds, opts, (_, state) => { try { ExtractFusion(_, announcement); } catch (Exception ex) { state.Stop(); throw new FusionException(FusionException.ExtractionFailure, _, ex); } }); }
/// <summary> /// Schedules an <see cref="IDeployAnnouncement"/>. /// </summary> /// <param name="announcement">The announcement that needs to be scheduled.</param> /// <param name="token">The token of cancellation.</param> /// <inheritdoc /> public async Task ScheduleAsync(IDeployAnnouncement announcement, CancellationToken token) { EnsureArg.IsNotNull(announcement, nameof(announcement)); var fusionIds = announcement .GetFusionIds() .OrderBy(_ => GetOrderId(_)) .Stale(); if (!isFullCompleted && announcement.IsDelta()) { throw new ScheduleException(ScheduleException.FullAnnouncementRequired, "*"); } await syncLock.WaitAsync(); try { var activeProcesses = GetActiveProcesses(fusionIds); await TerminateMultipleAsync(activeProcesses, token); // drains and stops the services logService.Info("Terminated all active fusion(s)."); fusionService.Extract(announcement, token); // extracts the new fusions logService.Info("Extracted all new fusion(s)."); var newProcesses = SpawnMultiple(fusionIds, token).Stale(); // spawns the services logService.Info("Spawned all new fusion(s)."); await WaitForAnnouncements(newProcesses, token); // wait for all port callbacks logService.Info("Received all announcements from the new fusion(s)."); await StartupMultipleAsync(newProcesses, token); // calls all the startups + nurse statusses logService.Info("Started all new fusion(s) and checked their patient(s)."); ResumeAll(token); logService.Info("Resumed all drainers, deployment completed."); if (!announcement.IsDelta()) { isFullCompleted = true; } } finally { syncLock.Release(); } }