diff --git a/Libs/YPermitin.FIASToolSet.DistributionLoader/FIASDistributionLoader.cs b/Libs/YPermitin.FIASToolSet.DistributionLoader/FIASDistributionLoader.cs index de64e25..f2e3455 100644 --- a/Libs/YPermitin.FIASToolSet.DistributionLoader/FIASDistributionLoader.cs +++ b/Libs/YPermitin.FIASToolSet.DistributionLoader/FIASDistributionLoader.cs @@ -74,6 +74,7 @@ public async Task> FixStuckInstallationExists() } await _fiasInstallationManagerService.SaveAsync(); + _fiasInstallationManagerService.ClearChangeTracking(); return stuckInstallations; } @@ -102,8 +103,26 @@ public async Task InitVersionInstallationToLoad() } } + public async Task SetVersionInstallationToLoad(Guid versionInstallationId) + { + var foundInstallation = await _fiasInstallationManagerService.GetInstallation(versionInstallationId, true); + if (foundInstallation == null) + return false; + + _distributionDirectory = null; + _distributionReader = null; + _installation = null; + CurrentVersion = null; + Distribution = null; + + _installation = foundInstallation; + CurrentVersion = _installation.FIASVersion; + return true; + } + public async Task DownloadAndExtractDistribution( - Action onDownloadFileProgressChangedEvent = null) + Action onDownloadFileProgressChangedEvent = null, + bool initOnly = false) { // 1. В зависимости от типа установки скачиваем файл дистрибутива ФИАС // 1.1. Если файл дистрибутива уже был успешно скачен ранее, то пропускаем шаг. @@ -124,10 +143,17 @@ public async Task DownloadAndExtractDistribution( distributionFileType = DistributionFileType.GARFIASXmlComplete; else distributionFileType = DistributionFileType.GARFIASXmlDelta; - await Distribution.DownloadDistributionByFileTypeAsync(distributionFileType, onDownloadFileProgressChangedEvent); + + if(!initOnly) + { + await Distribution.DownloadDistributionByFileTypeAsync(distributionFileType, onDownloadFileProgressChangedEvent); + } // 2. Распаковываем файлы базовых справочников (если уже были ранее распакованы, то повторяем операцию) - distribution.ExtractDistributionFile(distributionFileType); + if (!initOnly) + { + distribution.ExtractDistributionFile(distributionFileType); + } _distributionDirectory = Distribution.GetExtractedDirectory(distributionFileType); } @@ -179,9 +205,10 @@ public List GetAvailableRegions() /// Распаковка данных для указанного региона /// /// Регион для распаковки данных + /// Только инициализация каталогов без распаковки /// Путь к каталогу с данными по региону /// Регион с указанным кодом не найден - public string ExtractDataForRegion(Region region) + public string ExtractDataForRegion(Region region, bool initOnly = false) { DistributionFileType distributionFileType; if (_installation.InstallationTypeId == FIASVersionInstallationType.Full) @@ -197,8 +224,11 @@ public string ExtractDataForRegion(Region region) $"Не найден регион с кодом \"{region.Code}\" среди доступных регионов в дистрибутиве ФИАС.", region.ToString()); } - - Distribution.ExtractDistributionRegionFiles(distributionFileType, region.Code.ToString("00")); + + if (!initOnly) + { + Distribution.ExtractDistributionRegionFiles(distributionFileType, region.Code.ToString("00")); + } return GetDataDirectoryForRegion(region); } @@ -328,6 +358,19 @@ public async Task SetRegionInstallationStatusToInstalled(int regionCode) #endregion #region BaseCatalogs + + public async Task LoadAllBaseCatalogs() + { + await LoadObjectLevels(); + await LoadApartmentTypes(); + await LoadHouseTypes(); + await LoadOperationTypes(); + await LoadRoomTypes(); + await LoadParameterTypes(); + await LoadAddressObjectTypes(); + await LoadNormativeDocKinds(); + await LoadNormativeDocTypes(); + } public async Task LoadAddressObjectTypes() { @@ -402,7 +445,6 @@ public async Task LoadAddressObjectTypes() } installationStep.TotalItemsLoaded += 1; - //installationStep.PercentageCompleted = (int)((double)installationStep.TotalItemsLoaded / installationStep.TotalItemsToLoad * 100); } installationStep.PercentageCompleted = 100; @@ -1262,7 +1304,9 @@ public async Task LoadRoomTypes() /// Загрузка адресных объектов по региону /// /// Регион для загрузки данных адресных объектов - public async Task LoadAddressObjects(Region region) + /// Токен для отмены операции + public async Task LoadAddressObjects(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -1332,6 +1376,9 @@ public async Task LoadAddressObjects(Region region) await SaveAddressObjectsPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -1354,7 +1401,9 @@ public async Task LoadAddressObjects(Region region) /// Загрузка информации о переподчинении адресных объектов /// /// Регион для загрузки данных о переодчинении адресных объектов - public async Task LoadAddressObjectDivisions(Region region) + /// Токен для отмены операции + public async Task LoadAddressObjectDivisions(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -1424,6 +1473,9 @@ public async Task LoadAddressObjectDivisions(Region region) await SaveAddressObjectDivisionsPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -1446,7 +1498,9 @@ public async Task LoadAddressObjectDivisions(Region region) /// Загрузка информации о параметрах адресных объектов /// /// Регион для загрузки данных о параметрах адресных объектов - public async Task LoadAddressObjectParameters(Region region) + /// Токен для отмены операции + public async Task LoadAddressObjectParameters(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -1516,6 +1570,9 @@ public async Task LoadAddressObjectParameters(Region region) await SaveAddressObjectParametersPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -1538,7 +1595,9 @@ public async Task LoadAddressObjectParameters(Region region) /// Загрузка информации о иерархии административного деления адресных объектов /// /// Регион для загрузки данных о иерархии административного деления адресных объектов - public async Task LoadAddressObjectsAdmHierarchy(Region region) + /// Токен для отмены операции + public async Task LoadAddressObjectsAdmHierarchy(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -1609,6 +1668,9 @@ public async Task LoadAddressObjectsAdmHierarchy(Region region) await SaveAddressObjectsAdmHierarchyPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -1631,7 +1693,9 @@ public async Task LoadAddressObjectsAdmHierarchy(Region region) /// Загрузка информации о иерархии муниципального деления адресных объектов /// /// Регион для загрузки данных о иерархии муниципального деления адресных объектов - public async Task LoadAddressObjectsMunHierarchy(Region region) + /// Токен для отмены операции + public async Task LoadAddressObjectsMunHierarchy(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -1701,6 +1765,9 @@ public async Task LoadAddressObjectsMunHierarchy(Region region) await SaveAddressObjectsMunHierarchyPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -1723,7 +1790,9 @@ public async Task LoadAddressObjectsMunHierarchy(Region region) /// Загрузка информации о квартирах /// /// Регион для загрузки данных о квартирах - public async Task LoadApartments(Region region) + /// Токен для отмены операции + public async Task LoadApartments(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -1793,6 +1862,9 @@ public async Task LoadApartments(Region region) await SaveApartmentsPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -1815,7 +1887,9 @@ public async Task LoadApartments(Region region) /// Загрузка информации о параметрах квартир /// /// Регион для загрузки данных о параметрах квартир - public async Task LoadApartmentParameters(Region region) + /// Токен для отмены операции + public async Task LoadApartmentParameters(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -1885,6 +1959,9 @@ public async Task LoadApartmentParameters(Region region) await SaveApartmentParametersPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -1907,7 +1984,9 @@ public async Task LoadApartmentParameters(Region region) /// Загрузка информации о машино-местах /// /// Регион для загрузки данных о машино-местах - public async Task LoadCarPlaces(Region region) + /// Токен для отмены операции + public async Task LoadCarPlaces(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -1977,6 +2056,9 @@ public async Task LoadCarPlaces(Region region) await SaveCarPlacesPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -1999,7 +2081,9 @@ public async Task LoadCarPlaces(Region region) /// Загрузка информации о параметрах машино-мест /// /// Регион для загрузки данных о параметрах машино-мест - public async Task LoadCarPlaceParameters(Region region) + /// Токен для отмены операции + public async Task LoadCarPlaceParameters(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -2069,6 +2153,9 @@ public async Task LoadCarPlaceParameters(Region region) await SaveCarPlaceParametersPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -2091,7 +2178,9 @@ public async Task LoadCarPlaceParameters(Region region) /// Загрузка информации о строениях /// /// Регион для загрузки данных о строениях - public async Task LoadHouses(Region region) + /// Токен для отмены операции + public async Task LoadHouses(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -2161,6 +2250,9 @@ public async Task LoadHouses(Region region) await SaveHousesPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -2183,7 +2275,9 @@ public async Task LoadHouses(Region region) /// Загрузка информации о параметрах строений /// /// Регион для загрузки данных о параметрах строений - public async Task LoadHouseParameters(Region region) + /// Токен для отмены операции + public async Task LoadHouseParameters(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -2252,6 +2346,9 @@ public async Task LoadHouseParameters(Region region) await SaveHouseParametersPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -2274,7 +2371,9 @@ public async Task LoadHouseParameters(Region region) /// Загрузка информации о комнатах /// /// Регион для загрузки данных о комнатах - public async Task LoadRooms(Region region) + /// Токен для отмены операции + public async Task LoadRooms(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -2344,6 +2443,9 @@ public async Task LoadRooms(Region region) await SaveRoomsPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -2366,7 +2468,9 @@ public async Task LoadRooms(Region region) /// Загрузка информации о параметрах комнат /// /// Регион для загрузки данных о параметрах комнат - public async Task LoadRoomParameters(Region region) + /// Токен для отмены операции + public async Task LoadRoomParameters(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -2436,6 +2540,9 @@ public async Task LoadRoomParameters(Region region) await SaveRoomParametersPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -2458,7 +2565,9 @@ public async Task LoadRoomParameters(Region region) /// Загрузка информации о земельных участках /// /// Регион для загрузки данных о земельных участках - public async Task LoadSteads(Region region) + /// Токен для отмены операции + public async Task LoadSteads(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -2528,6 +2637,9 @@ public async Task LoadSteads(Region region) await SaveSteadsPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -2550,7 +2662,9 @@ public async Task LoadSteads(Region region) /// Загрузка информации о параметрах земельных участков /// /// Регион для загрузки данных о параметрах земельных участков - public async Task LoadSteadParameters(Region region) + /// Токен для отмены операции + public async Task LoadSteadParameters(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -2621,6 +2735,8 @@ public async Task LoadSteadParameters(Region region) _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -2643,7 +2759,9 @@ public async Task LoadSteadParameters(Region region) /// Загрузка информации о нормативных документах /// /// Регион для загрузки данных о нормативных документах - public async Task LoadNormativeDocuments(Region region) + /// Токен для отмены операции + public async Task LoadNormativeDocuments(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -2712,6 +2830,12 @@ public async Task LoadNormativeDocuments(Region region) await SaveNormativeDocumentsPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -2734,7 +2858,9 @@ public async Task LoadNormativeDocuments(Region region) /// Загрузка истории изменений адресных объектов /// /// Регион для загрузки данных о истории изменений адресных объектов - public async Task LoadChangeHistory(Region region) + /// Токен для отмены операции + public async Task LoadChangeHistory(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -2804,6 +2930,9 @@ public async Task LoadChangeHistory(Region region) await SaveChangeHistoryPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } @@ -2826,7 +2955,9 @@ public async Task LoadChangeHistory(Region region) /// Загрузка реестра адресных элементов /// /// Регион для загрузки данных о реестре адресных элементов - public async Task LoadObjectsRegistry(Region region) + /// Токен для отмены операции + public async Task LoadObjectsRegistry(Region region, + CancellationToken cancellationToken = default(CancellationToken)) { var fiasDistributionReader = GetDistributionReader(); var fiasDistributionRegion = fiasDistributionReader @@ -2896,6 +3027,9 @@ public async Task LoadObjectsRegistry(Region region) await SaveObjectsRegistryPortion(currentPortion); _fiasInstallationManagerService.UpdateInstallationStep(installationStep); await _fiasInstallationManagerService.SaveAsync(); + + if(cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); } } diff --git a/Libs/YPermitin.FIASToolSet.DistributionLoader/IFIASDistributionLoader.cs b/Libs/YPermitin.FIASToolSet.DistributionLoader/IFIASDistributionLoader.cs index 9df3f5d..0b1df05 100644 --- a/Libs/YPermitin.FIASToolSet.DistributionLoader/IFIASDistributionLoader.cs +++ b/Libs/YPermitin.FIASToolSet.DistributionLoader/IFIASDistributionLoader.cs @@ -32,6 +32,13 @@ public interface IFIASDistributionLoader /// /// Объект асинхронной операции Task SetInstallationToStatusNew(); + + /// + /// Установка версии ФИАС для установки или обновления + /// + /// Идентификатор версии установки + /// + Task SetVersionInstallationToLoad(Guid versionInstallationId); /// /// Определение версии ФИАС для установки или обновления @@ -44,7 +51,8 @@ public interface IFIASDistributionLoader /// /// Объект асинхронной операции Task DownloadAndExtractDistribution( - Action onDownloadFileProgressChangedEvent = null); + Action onDownloadFileProgressChangedEvent = null, + bool initOnly = false); /// /// Удалениие архива данных для версии ФИАС @@ -66,9 +74,10 @@ Task DownloadAndExtractDistribution( /// Распаковка данных для указанного региона /// /// Информация о региоре + /// Только инициализация каталогов без распаковки /// Путь к каталогу с данными по региону /// Регион с указанным кодом не найден - string ExtractDataForRegion(Region region); + string ExtractDataForRegion(Region region, bool initOnly = false); /// /// Полусение пути к каталогу с данными региона @@ -112,6 +121,12 @@ Task DownloadAndExtractDistribution( Task SetRegionInstallationStatusToInstalled(int regionCode); #region BaseCatalogs + + /// + /// Загрузка всех базовых справочников + /// + /// Объект асинхронной операции + Task LoadAllBaseCatalogs(); /// /// Загрузка типов адресных объектов @@ -175,109 +190,127 @@ Task DownloadAndExtractDistribution( /// Загрузка адресных объектов по региону /// /// Регион для загрузки данных адресных объектов - Task LoadAddressObjects(Region region); + /// Токен для отмены операции + Task LoadAddressObjects(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о переподчинении адресных объектов /// /// Регион для загрузки данных о переодчинении адресных объектов - Task LoadAddressObjectDivisions(Region region); + /// Токен для отмены операции + Task LoadAddressObjectDivisions(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о параметрах адресных объектов /// /// Регион для загрузки данных о параметрах адресных объектов - Task LoadAddressObjectParameters(Region region); + /// Токен для отмены операции + Task LoadAddressObjectParameters(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о иерархии административного деления адресных объектов /// /// Регион для загрузки данных о иерархии административного деления адресных объектов - Task LoadAddressObjectsAdmHierarchy(Region region); + /// Токен для отмены операции + Task LoadAddressObjectsAdmHierarchy(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о иерархии муниципального деления адресных объектов /// /// Регион для загрузки данных о иерархии муниципального деления адресных объектов - Task LoadAddressObjectsMunHierarchy(Region region); + /// Токен для отмены операции + Task LoadAddressObjectsMunHierarchy(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о квартирах /// /// Регион для загрузки данных о квартирах - Task LoadApartments(Region region); + /// Токен для отмены операции + Task LoadApartments(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о параметрах квартир /// /// Регион для загрузки данных о параметрах квартир - Task LoadApartmentParameters(Region region); + /// Токен для отмены операции + Task LoadApartmentParameters(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о машино-местах /// /// Регион для загрузки данных о машино-местах - Task LoadCarPlaces(Region region); + /// Токен для отмены операции + Task LoadCarPlaces(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о параметрах машино-мест /// /// Регион для загрузки данных о параметрах машино-мест - Task LoadCarPlaceParameters(Region region); + /// Токен для отмены операции + Task LoadCarPlaceParameters(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о строениях /// /// Регион для загрузки данных о строениях - Task LoadHouses(Region region); + /// Токен для отмены операции + Task LoadHouses(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о параметрах строений /// /// Регион для загрузки данных о параметрах строений - Task LoadHouseParameters(Region region); + /// Токен для отмены операции + Task LoadHouseParameters(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о комнатах /// /// Регион для загрузки данных о комнатах - Task LoadRooms(Region region); + /// Токен для отмены операции + Task LoadRooms(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о параметрах комнат /// /// Регион для загрузки данных о параметрах комнат - Task LoadRoomParameters(Region region); + /// Токен для отмены операции + Task LoadRoomParameters(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о земельных участках /// /// Регион для загрузки данных о земельных участках - Task LoadSteads(Region region); + /// Токен для отмены операции + Task LoadSteads(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о параметрах земельных участков /// /// Регион для загрузки данных о параметрах земельных участков - Task LoadSteadParameters(Region region); + /// Токен для отмены операции + Task LoadSteadParameters(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка информации о нормативных документах /// /// Регион для загрузки данных о нормативных документах - Task LoadNormativeDocuments(Region region); + /// Токен для отмены операции + Task LoadNormativeDocuments(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка истории изменений адресных объектов /// /// Регион для загрузки данных о истории изменений адресных объектов - Task LoadChangeHistory(Region region); + /// Токен для отмены операции + Task LoadChangeHistory(Region region, CancellationToken cancellationToken = default(CancellationToken)); /// /// Загрузка реестра адресных элементов /// /// Регион для загрузки данных о реестре адресных элементов - Task LoadObjectsRegistry(Region region); + /// Токен для отмены операции + Task LoadObjectsRegistry(Region region, CancellationToken cancellationToken = default(CancellationToken)); #endregion } \ No newline at end of file diff --git a/Libs/YPermitin.FIASToolSet.DistributionLoader/YPermitin.FIASToolSet.DistributionLoader.xml b/Libs/YPermitin.FIASToolSet.DistributionLoader/YPermitin.FIASToolSet.DistributionLoader.xml index e887744..84463fb 100644 --- a/Libs/YPermitin.FIASToolSet.DistributionLoader/YPermitin.FIASToolSet.DistributionLoader.xml +++ b/Libs/YPermitin.FIASToolSet.DistributionLoader/YPermitin.FIASToolSet.DistributionLoader.xml @@ -20,11 +20,12 @@ Коллекция доступных регионов - + Распаковка данных для указанного региона Регион для распаковки данных + Только инициализация каталогов без распаковки Путь к каталогу с данными по региону Регион с указанным кодом не найден @@ -57,113 +58,131 @@ Установка статуса установки региона на "Установлено" - + Загрузка адресных объектов по региону Регион для загрузки данных адресных объектов + Токен для отмены операции - + Загрузка информации о переподчинении адресных объектов Регион для загрузки данных о переодчинении адресных объектов + Токен для отмены операции - + Загрузка информации о параметрах адресных объектов Регион для загрузки данных о параметрах адресных объектов + Токен для отмены операции - + Загрузка информации о иерархии административного деления адресных объектов Регион для загрузки данных о иерархии административного деления адресных объектов + Токен для отмены операции - + Загрузка информации о иерархии муниципального деления адресных объектов Регион для загрузки данных о иерархии муниципального деления адресных объектов + Токен для отмены операции - + Загрузка информации о квартирах Регион для загрузки данных о квартирах + Токен для отмены операции - + Загрузка информации о параметрах квартир Регион для загрузки данных о параметрах квартир + Токен для отмены операции - + Загрузка информации о машино-местах Регион для загрузки данных о машино-местах + Токен для отмены операции - + Загрузка информации о параметрах машино-мест Регион для загрузки данных о параметрах машино-мест + Токен для отмены операции - + Загрузка информации о строениях Регион для загрузки данных о строениях + Токен для отмены операции - + Загрузка информации о параметрах строений Регион для загрузки данных о параметрах строений + Токен для отмены операции - + Загрузка информации о комнатах Регион для загрузки данных о комнатах + Токен для отмены операции - + Загрузка информации о параметрах комнат Регион для загрузки данных о параметрах комнат + Токен для отмены операции - + Загрузка информации о земельных участках Регион для загрузки данных о земельных участках + Токен для отмены операции - + Загрузка информации о параметрах земельных участков Регион для загрузки данных о параметрах земельных участков + Токен для отмены операции - + Загрузка информации о нормативных документах Регион для загрузки данных о нормативных документах + Токен для отмены операции - + Загрузка истории изменений адресных объектов Регион для загрузки данных о истории изменений адресных объектов + Токен для отмены операции - + Загрузка реестра адресных элементов Регион для загрузки данных о реестре адресных элементов + Токен для отмены операции @@ -191,13 +210,20 @@ Объект асинхронной операции + + + Установка версии ФИАС для установки или обновления + + Идентификатор версии установки + + Определение версии ФИАС для установки или обновления Истина при успешном определении версии, Ложь в противном случае - + Скачивание и распаковка дистрибутива ФИАС @@ -219,11 +245,12 @@ Коллекция доступных регионов - + Распаковка данных для указанного региона Информация о региоре + Только инициализация каталогов без распаковки Путь к каталогу с данными по региону Регион с указанным кодом не найден @@ -268,6 +295,12 @@ Установка статуса установки региона на "Установлено" + + + Загрузка всех базовых справочников + + Объект асинхронной операции + Загрузка типов адресных объектов @@ -322,113 +355,131 @@ Объект асинхронной операции - + Загрузка адресных объектов по региону Регион для загрузки данных адресных объектов + Токен для отмены операции - + Загрузка информации о переподчинении адресных объектов Регион для загрузки данных о переодчинении адресных объектов + Токен для отмены операции - + Загрузка информации о параметрах адресных объектов Регион для загрузки данных о параметрах адресных объектов + Токен для отмены операции - + Загрузка информации о иерархии административного деления адресных объектов Регион для загрузки данных о иерархии административного деления адресных объектов + Токен для отмены операции - + Загрузка информации о иерархии муниципального деления адресных объектов Регион для загрузки данных о иерархии муниципального деления адресных объектов + Токен для отмены операции - + Загрузка информации о квартирах Регион для загрузки данных о квартирах + Токен для отмены операции - + Загрузка информации о параметрах квартир Регион для загрузки данных о параметрах квартир + Токен для отмены операции - + Загрузка информации о машино-местах Регион для загрузки данных о машино-местах + Токен для отмены операции - + Загрузка информации о параметрах машино-мест Регион для загрузки данных о параметрах машино-мест + Токен для отмены операции - + Загрузка информации о строениях Регион для загрузки данных о строениях + Токен для отмены операции - + Загрузка информации о параметрах строений Регион для загрузки данных о параметрах строений + Токен для отмены операции - + Загрузка информации о комнатах Регион для загрузки данных о комнатах + Токен для отмены операции - + Загрузка информации о параметрах комнат Регион для загрузки данных о параметрах комнат + Токен для отмены операции - + Загрузка информации о земельных участках Регион для загрузки данных о земельных участках + Токен для отмены операции - + Загрузка информации о параметрах земельных участков Регион для загрузки данных о параметрах земельных участков + Токен для отмены операции - + Загрузка информации о нормативных документах Регион для загрузки данных о нормативных документах + Токен для отмены операции - + Загрузка истории изменений адресных объектов Регион для загрузки данных о истории изменений адресных объектов + Токен для отмены операции - + Загрузка реестра адресных элементов Регион для загрузки данных о реестре адресных элементов + Токен для отмены операции diff --git a/Libs/YPermitin.FIASToolSet.Jobs/JobItems/InstallAndUpdateFIASJob.cs b/Libs/YPermitin.FIASToolSet.Jobs/JobItems/InstallAndUpdateFIASJob.cs index 366575c..c1fbb63 100644 --- a/Libs/YPermitin.FIASToolSet.Jobs/JobItems/InstallAndUpdateFIASJob.cs +++ b/Libs/YPermitin.FIASToolSet.Jobs/JobItems/InstallAndUpdateFIASJob.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -5,6 +6,8 @@ using YPermitin.FIASToolSet.DistributionBrowser.Models; using YPermitin.FIASToolSet.DistributionLoader; using YPermitin.FIASToolSet.DistributionLoader.Exceptions; +using YPermitin.FIASToolSet.DistributionLoader.Models; +using YPermitin.FIASToolSet.Storage.Core.Models.Versions; namespace YPermitin.FIASToolSet.Jobs.JobItems; @@ -22,6 +25,7 @@ public class InstallAndUpdateFIASJob : IJob private readonly List _availableRegions; private readonly bool _removeArchiveDistributionFiles; private readonly bool _removeExtractedDistributionFiles; + private readonly int _maxParallelTasks; public InstallAndUpdateFIASJob( IServiceProvider provider, @@ -54,6 +58,8 @@ public InstallAndUpdateFIASJob( _configuration.GetValue("FIASToolSet:ClearTempDistributionFiles:RemoveArchiveDistributionFiles", false); _removeExtractedDistributionFiles = _configuration.GetValue("FIASToolSet:ClearTempDistributionFiles:RemoveExtractedDistributionFiles", true); + _maxParallelTasks = + _configuration.GetValue("FIASToolSet:MaxParallelTasks", 1); } public async Task Execute(IJobExecutionContext context) @@ -73,12 +79,19 @@ public async Task Execute(IJobExecutionContext context) private async Task ExecuteInstallOrUpdateFIAS() { + // TODO Привести в порядок кодовую базу задания, вынести в отдельные классы функционал, + // а также избавиться от дублирования кода. _logger.LogInformation("Запущена обработка шагов по установке / обновлению классификатора ФИАС."); + Guid installationVersionId = Guid.Empty; + List availableRegions = null; + + // Этап №1: Подготовка задания загрузки данных ФИАС и обновление статусов задания. + // Распаковка архива ФИАС и подготовка файлов дистрибутива. Загрузка базовых справочников ФИАС. using (var scope = _provider.CreateScope()) { IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); - + await loader.FixStuckInstallationExists(); if (await loader.ActiveInstallationExists()) @@ -91,17 +104,37 @@ private async Task ExecuteInstallOrUpdateFIAS() if (await loader.InitVersionInstallationToLoad()) { await loader.SetInstallationToStatusInstalling(); - + if (loader.VersionInstallation.InstallationTypeId == FIASVersionInstallationType.Full) + { + if (string.IsNullOrEmpty(loader.VersionInstallation.FIASVersion.GARFIASXmlComplete)) + { + _logger.LogWarning( + $"Версия ФИАС с типом FULL не содержит ссылки на загрузку полной версии дистрибутива ФИАС. Установка пропущена."); + await loader.SetInstallationToStatusInstalled(); + return; + } + } + else if (loader.VersionInstallation.InstallationTypeId == FIASVersionInstallationType.Update) + { + if (string.IsNullOrEmpty(loader.VersionInstallation.FIASVersion.GARFIASXmlDelta)) + { + _logger.LogWarning( + $"Версия ФИАС с типом DELTA не содержит ссылки на загрузку обновлений версии дистрибутива ФИАС. Установка пропущена."); + await loader.SetInstallationToStatusInstalled(); + return; + } + } + bool downloadSuccess = true; DateTime downloadStarted = DateTime.UtcNow; DateTime lastProgressShow = DateTime.MinValue; double lastProgressPercentage = 0; - + await loader.DownloadAndExtractDistribution(args => { double progress = Math.Round(args.ProgressPercentage, 2); double progressChanged = lastProgressPercentage - progress; - + var showProgressTimeLeft = DateTime.UtcNow - lastProgressShow; if (args.State != DownloadDistributionFileProgressChangedEventType.Downloading || showProgressTimeLeft.TotalSeconds > 10 @@ -109,7 +142,7 @@ await loader.DownloadAndExtractDistribution(args => { lastProgressPercentage = progress; lastProgressShow = DateTime.UtcNow; - + var downloadDuration = DateTime.UtcNow - downloadStarted; _logger.LogInformation( $"{args.State}. Загружено: {progress} %. " + @@ -128,86 +161,476 @@ await loader.DownloadAndExtractDistribution(args => return; } - await loader.LoadObjectLevels(); - await loader.LoadApartmentTypes(); - await loader.LoadHouseTypes(); - await loader.LoadOperationTypes(); - await loader.LoadRoomTypes(); - await loader.LoadParameterTypes(); - await loader.LoadAddressObjectTypes(); - await loader.LoadNormativeDocKinds(); - await loader.LoadNormativeDocTypes(); + await loader.LoadAllBaseCatalogs(); - var availableRegions = loader.GetAvailableRegions(); + availableRegions = loader.GetAvailableRegions(); if (_availableRegions.Count > 0) { - availableRegions = availableRegions - .Where(e => _availableRegions.Contains(e.Code)) - .ToList(); + availableRegions = availableRegions + .Where(e => _availableRegions.Contains(e.Code)) + .ToList(); } - - foreach (var availableRegion in availableRegions) + + installationVersionId = loader.VersionInstallation.Id; + } + else + { + _logger.LogInformation("Не обнаружены версии ФИАС для установки или обновления. Действие пропущено."); + return; + } + } + + // Этап №2: Формирование заданий по загрузке данных в разрезе регионов. + // Может использоваться многопоточная загрузка, если разрешена. + CancellationTokenSource cancelTokenSourceForLoadOperations = new CancellationTokenSource(); + CancellationToken cancellationToken = cancelTokenSourceForLoadOperations.Token; + if (availableRegions != null) + { + foreach (var availableRegion in availableRegions) + { + using (var scope = _provider.CreateScope()) { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation("Не удалось настроить версии ФИАС для установки или обновления. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + bool regionWasLoaded = await loader.RegionWasLoaded(availableRegion.Code); if (regionWasLoaded) { - _logger.LogWarning($"Регион с кодом \"{availableRegion.Code}\" уже был загружен. Пропускаем обработки файлов данных."); + _logger.LogWarning( + $"Регион с кодом \"{availableRegion.Code}\" уже был загружен. Пропускаем обработки файлов данных."); continue; } - + try { loader.ExtractDataForRegion(availableRegion); } catch (RegionNotFoundException) { - _logger.LogError($"Не найден регион с кодом ${availableRegion.Code} среди доступных регионов в дистрибутиве ФИАС. Загрузка пропущена."); + _logger.LogError( + $"Не найден регион с кодом ${availableRegion.Code} среди доступных регионов в дистрибутиве ФИАС. Загрузка пропущена."); continue; } await loader.SetRegionInstallationStatusToInstalling(availableRegion.Code); - - await loader.LoadNormativeDocuments(availableRegion); - await loader.LoadAddressObjects(availableRegion); - await loader.LoadAddressObjectDivisions(availableRegion); - await loader.LoadAddressObjectParameters(availableRegion); - await loader.LoadAddressObjectsAdmHierarchy(availableRegion); - await loader.LoadAddressObjectsMunHierarchy(availableRegion); - await loader.LoadApartments(availableRegion); - await loader.LoadApartmentParameters(availableRegion); - await loader.LoadCarPlaces(availableRegion); - await loader.LoadCarPlaceParameters(availableRegion); - await loader.LoadHouses(availableRegion); - await loader.LoadHouseParameters(availableRegion); - await loader.LoadRooms(availableRegion); - await loader.LoadRoomParameters(availableRegion); - await loader.LoadSteads(availableRegion); - await loader.LoadSteadParameters(availableRegion); - await loader.LoadChangeHistory(availableRegion); - await loader.LoadObjectsRegistry(availableRegion); - - await loader.SetRegionInstallationStatusToInstalled(availableRegion.Code); - - if (_removeExtractedDistributionFiles) + } + + List tasksIsRunning = new List(); + ConcurrentQueue> tasksToRun = new ConcurrentQueue>(); + + #region Tasks + Func taskLoadNormativeDocuments = async () => + { + using (var scope = _provider.CreateScope()) { - loader.RemoveDistributionRegionDirectory(availableRegion); + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + + await loader.LoadNormativeDocuments(availableRegion, cancellationToken); } - } + }; + tasksToRun.Enqueue(taskLoadNormativeDocuments); + Func taskLoadAddressObjects = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadAddressObjects(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadAddressObjects); + Func taskLoadAddressObjectDivisions = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadAddressObjectDivisions(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadAddressObjectDivisions); + Func taskLoadAddressObjectsAdmHierarchy = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadAddressObjectsAdmHierarchy(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadAddressObjectsAdmHierarchy); + Func taskLoadAddressObjectsMunHierarchy = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadAddressObjectsMunHierarchy(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadAddressObjectsMunHierarchy); + Func taskLoadApartments = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadApartments(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadApartments); + Func taskLoadCarPlaces = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadCarPlaces(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadCarPlaces); + Func taskLoadHouses = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadHouses(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadHouses); + Func taskLoadRooms = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadRooms(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadRooms); + Func taskLoadSteads = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadSteads(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadSteads); + Func taskLoadAddressObjectParameters = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadAddressObjectParameters(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadAddressObjectParameters); + Func taskLoadApartmentParameters = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadApartmentParameters(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadApartmentParameters); + Func taskLoadCarPlaceParameters = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadCarPlaceParameters(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadCarPlaceParameters); + Func taskLoadHouseParameters = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadHouseParameters(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadHouseParameters); + Func taskLoadRoomParameters = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadRoomParameters(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadRoomParameters); + Func taskLoadSteadParameters = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadSteadParameters(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadSteadParameters); + Func taskLoadChangeHistory = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadChangeHistory(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadChangeHistory); + Func taskLoadObjectsRegistry = async () => + { + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + await loader.LoadObjectsRegistry(availableRegion, cancellationToken); + } + }; + tasksToRun.Enqueue(taskLoadObjectsRegistry); + #endregion - await loader.SetInstallationToStatusInstalled(); - if (_removeExtractedDistributionFiles) + while (tasksToRun.Count > 0 || tasksIsRunning.Count > 0) { - loader.RemoveVersionDataDirectory(); + // Запускаем задачи для заполнения пула активных задач + while (tasksIsRunning.Count < _maxParallelTasks && tasksToRun.Count > 0) + { + try + { + if (tasksToRun.TryDequeue(out Func taskItemToRun)) + { + var startedTask = taskItemToRun(); + tasksIsRunning.Add(startedTask); + } + } + catch + { + continue; + } + } + + // Ждем завершения хотя бы одной задачи + Task.WaitAny(tasksIsRunning.ToArray()); + + foreach (var taskRunning in tasksIsRunning) + { + if (taskRunning.IsFaulted) + { + cancelTokenSourceForLoadOperations.Cancel(); + _logger.LogError(taskRunning.Exception, $"Ошибка при загрузке данных ФИАС."); + + try + { + Task.WaitAll(tasksIsRunning.ToArray()); + } + catch (Exception ex) + { + _logger.LogError(ex, + $"Отменены операции загрузки данных из-за ошибки в одном из заданий. Подробности см. выше."); + } + finally + { + cancelTokenSourceForLoadOperations.Dispose(); + } + + throw new Exception("Ошибка при загрузке данных ФИАС.", taskRunning.Exception); + } + } + + // Удаляем выполненные задачи из пула + tasksIsRunning = tasksIsRunning + .Where(e => !e.IsCompleted) + .ToList(); } - if (_removeArchiveDistributionFiles) + using (var scope = _provider.CreateScope()) { - loader.RemoveVersionDataArchive(); + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) + { + _logger.LogInformation($"Не удалось настроить версии ФИАС для установки или обновления по региону {availableRegion.Code}. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + loader.ExtractDataForRegion(availableRegion, true); + + await loader.SetRegionInstallationStatusToInstalled(availableRegion.Code); + + if (_removeExtractedDistributionFiles) + { + loader.RemoveDistributionRegionDirectory(availableRegion); + } } } - else + } + + // Этап №3: Установка финального статуса для задания установки / обновления ФИАС. + // Очистка временных файлов в соответствии с настройками. + using (var scope = _provider.CreateScope()) + { + IFIASDistributionLoader loader = scope.ServiceProvider.GetRequiredService(); + bool installationConfigured = await loader.SetVersionInstallationToLoad(installationVersionId); + if (!installationConfigured) { - _logger.LogInformation("Не обнаружены версии ФИАС для установки или обновления. Действие пропущено."); + _logger.LogInformation("Не удалось настроить версии ФИАС для установки или обновления. Действие пропущено."); + return; + } + await loader.DownloadAndExtractDistribution(null, true); + + await loader.SetInstallationToStatusInstalled(); + if (_removeExtractedDistributionFiles) + { + loader.RemoveVersionDataDirectory(); + } + + if (_removeArchiveDistributionFiles) + { + loader.RemoveVersionDataArchive(); } } diff --git a/Libs/YPermitin.FIASToolSet.Storage.Core/Services/IFIASInstallationManagerRepository.cs b/Libs/YPermitin.FIASToolSet.Storage.Core/Services/IFIASInstallationManagerRepository.cs index c49e415..fca95cd 100644 --- a/Libs/YPermitin.FIASToolSet.Storage.Core/Services/IFIASInstallationManagerRepository.cs +++ b/Libs/YPermitin.FIASToolSet.Storage.Core/Services/IFIASInstallationManagerRepository.cs @@ -8,7 +8,7 @@ public interface IFIASInstallationManagerRepository Task> GetInstallations(Guid? statusId = null, Guid? typeId = null, bool includeDetails = false); - Task GetInstallation(Guid id); + Task GetInstallation(Guid id, bool includeDetails = false); Task GetLastInstallation(); Task GetPreviousInstallation(Guid installationId); void AddInstallation(FIASVersionInstallation installation); diff --git a/Libs/YPermitin.FIASToolSet.Storage.PostgreSQL/Services/FIASInstallationManagerRepository.cs b/Libs/YPermitin.FIASToolSet.Storage.PostgreSQL/Services/FIASInstallationManagerRepository.cs index 2f1682c..1a4b158 100644 --- a/Libs/YPermitin.FIASToolSet.Storage.PostgreSQL/Services/FIASInstallationManagerRepository.cs +++ b/Libs/YPermitin.FIASToolSet.Storage.PostgreSQL/Services/FIASInstallationManagerRepository.cs @@ -44,9 +44,19 @@ public async Task> GetInstallations(Guid? statusId return result; } - public async Task GetInstallation(Guid id) + public async Task GetInstallation(Guid id, bool includeDetails = false) { - return await _context.FIASVersionInstallations + var query = _context.FIASVersionInstallations.AsQueryable(); + + if (includeDetails) + { + query = query + .Include(e => e.FIASVersion).AsNoTracking() + .Include(e => e.Status).AsNoTracking() + .Include(e => e.InstallationType).AsNoTracking(); + } + + return await query .AsNoTracking() .FirstOrDefaultAsync(e => e.Id == id); } diff --git a/Libs/YPermitin.FIASToolSet.Storage.SQLServer/Services/FIASInstallationManagerRepository.cs b/Libs/YPermitin.FIASToolSet.Storage.SQLServer/Services/FIASInstallationManagerRepository.cs index 755edae..3f8d9a0 100644 --- a/Libs/YPermitin.FIASToolSet.Storage.SQLServer/Services/FIASInstallationManagerRepository.cs +++ b/Libs/YPermitin.FIASToolSet.Storage.SQLServer/Services/FIASInstallationManagerRepository.cs @@ -44,9 +44,19 @@ public async Task> GetInstallations(Guid? statusId return result; } - public async Task GetInstallation(Guid id) + public async Task GetInstallation(Guid id, bool includeDetails = false) { - return await _context.FIASVersionInstallations + var query = _context.FIASVersionInstallations.AsQueryable(); + + if (includeDetails) + { + query = query + .Include(e => e.FIASVersion).AsNoTracking() + .Include(e => e.Status).AsNoTracking() + .Include(e => e.InstallationType).AsNoTracking(); + } + + return await query .AsNoTracking() .FirstOrDefaultAsync(e => e.Id == id); }