ЗаданиеВыгрузка (БСП)

Автор: 1С
ОбщийМодуль.МиграцияПриложений
БСП

Задание выгрузка. Регламентное задание МиграцияПриложенийВыгрузка.

// Регламентное задание МиграцияПриложенийВыгрузка.
//
Процедура ЗаданиеВыгрузка(ЗавершитьМиграцию = Ложь) Экспорт
	
 	ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(Метаданные.РегламентныеЗадания.МиграцияПриложенийВыгрузка);
	
	УстановитьПривилегированныйРежим(Истина);
	
	СостояниеВыгрузки = РегистрыСведений.МиграцияПриложенийСостояниеВыгрузки.СоздатьМенеджерЗаписи();
	СостояниеВыгрузки.Прочитать();
	Если Не СостояниеВыгрузки.Выбран() Тогда
		ПредставлениеОшибки = НСтр("ru = 'Состояние выгрузки не найдено.'");
		РегистрацияОшибки(НСтр("ru = 'Выгрузка'", ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка()), ПредставлениеОшибки);
		РегламентныеЗаданияСервер.УдалитьЗадание(Метаданные.РегламентныеЗадания.МиграцияПриложенийВыгрузка);
		Возврат;
	КонецЕсли;
	
	УзелОбмена = СостояниеВыгрузки.УзелОбмена;
	
	Если Не ЗначениеЗаполнено(УзелОбмена) Тогда
		ПредставлениеОшибки = НСтр("ru = 'Не найден узел обмена.'");
		ЗавершитьВыгрузкуСОшибкой(СостояниеВыгрузки, ПредставлениеОшибки, ПредставлениеОшибки);
		Возврат;
	КонецЕсли;
	
	Попытка
		ЗаблокироватьДанныеДляРедактирования(УзелОбмена);
		КлючЗаписи = РегистрыСведений.МиграцияПриложенийСостояниеВыгрузки.СоздатьКлючЗаписи(Новый Структура);
		ЗаблокироватьДанныеДляРедактирования(КлючЗаписи);
	Исключение
		Возврат;
	КонецПопытки;
	
	// Регистрация объектов идет до обращения к сервису, т.к. приложение может быть еще не готово.
	Если СостояниеВыгрузки.НомерОтправленногоСообщения = 0 Тогда
		Для Каждого КлючИЗначение Из МиграцияПриложенийПовтИсп.ВыгружаемыеОбъекты() Цикл
			ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, КлючИЗначение.Ключ);
			Если Метаданные.РегистрыРасчета.Содержит(КлючИЗначение.Ключ) Тогда
				Для Каждого Перерасчет Из КлючИЗначение.Ключ.Перерасчеты Цикл
					ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, Перерасчет);
				КонецЦикла;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	УстановитьПривилегированныйРежим(Истина);
	ПараметрыДоступа = ИнтеграцияПодсистемБТС.ПрочитатьДанныеИзБезопасногоХранилища(УзелОбмена, "ПараметрыДоступа");
	УстановитьПривилегированныйРежим(Ложь);
	
	Если ПараметрыДоступа = Неопределено Тогда
		ПредставлениеОшибки = НСтр("ru = 'Не найдены параметры подключения.'");
		ЗавершитьВыгрузкуСОшибкой(СостояниеВыгрузки, ПредставлениеОшибки, ПредставлениеОшибки);
		Возврат;
	КонецЕсли;
		
	Попытка
		СостояниеЗагрузки = СостояниеЗагрузкиИзСервиса(ПараметрыДоступа);
	Исключение
		// Сервис может быть недоступен, это не ошибка.
		ПредставлениеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		Шаблон = НСтр("ru = 'Не удалось получить состояние загрузки, возможно сервис временно недоступен: %1 %1'", ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка());
		Комментарий = СтрШаблон(Шаблон, Символы.ПС, ПредставлениеОшибки);
		РегистрацияПримечания(НСтр("ru = 'Выгрузка'", ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка()), Комментарий);
		ДатаПроверки = ?(ЗначениеЗаполнено(СостояниеВыгрузки.ДатаСостоянияЗагрузки), СостояниеВыгрузки.ДатаСостоянияЗагрузки, СостояниеВыгрузки.ДатаНачала);
		Если (ТекущаяУниверсальнаяДата() - ДатаПроверки) > (86400) Тогда
			ПредставлениеОшибки = НСтр("ru = 'Сервис недоступен 24 часа, выгрузка прервана.'");
			ЗавершитьВыгрузкуСОшибкой(СостояниеВыгрузки, ПредставлениеОшибки, ПредставлениеОшибки);
		КонецЕсли;
		Возврат;
	КонецПопытки;
	
	Если СостояниеЗагрузки.ИмяКонфигурации <> Метаданные.Имя Тогда
		ПредставлениеОшибки = НСтр("ru = 'Имя конфигурации не совпадает.'");
		ЗавершитьВыгрузкуСОшибкой(СостояниеВыгрузки, ПредставлениеОшибки, ПредставлениеОшибки);
	КонецЕсли;
	
	Если СостояниеВыгрузки.НомерПринятогоСообщения < СостояниеЗагрузки.НомерПринятогоСообщения Тогда
		СостояниеВыгрузки.НомерПринятогоСообщения = СостояниеЗагрузки.НомерПринятогоСообщения;
		ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, СостояниеЗагрузки.НомерПринятогоСообщения);
	КонецЕсли;
	
	Если СостояниеЗагрузки.ТребуетсяПовторнаяОтправка Тогда
		
		// Значит версия в приемнике обновилась и нужно повторно отправить уже выгруженные объекты.
		ЗарегистрироватьИзмененияПовторно(УзелОбмена, СостояниеВыгрузки.НомерОтправленногоСообщения);
		
		НачатьТранзакцию();
		Попытка
			// В приемнике очередь очищена, здесь тоже нужно сбросить номер отправленного
			СостояниеВыгрузки.НомерОтправленногоСообщения = СостояниеЗагрузки.НомерПринятогоСообщения;
			
			СостояниеЗагрузки = ПодтвердитьПовторнуюЗагрузкуВСервисе(ПараметрыДоступа);
			
			ЗаполнитьСостояниеВыгрузки(СостояниеВыгрузки, СостояниеЗагрузки, УзелОбмена);
			СостояниеВыгрузки.Записать();
			
			ЗафиксироватьТранзакцию();
		Исключение
			ОтменитьТранзакцию();
			ВызватьИсключение;
		КонецПопытки;
		
	КонецЕсли;
	
	Если СостояниеЗагрузки.ВерсияКонфигурации <> Метаданные.Версия Тогда
		СостояниеВыгрузки.Состояние = Перечисления.СостоянияМиграцииПриложения.ОжиданиеОбновления;
		СостояниеВыгрузки.Комментарий = СостояниеЗагрузки.ВерсияКонфигурации;
		ЗаполнитьСостояниеВыгрузки(СостояниеВыгрузки, СостояниеЗагрузки, УзелОбмена);
		СостояниеВыгрузки.Записать();
	ИначеЕсли СостояниеВыгрузки.Состояние = Перечисления.СостоянияМиграцииПриложения.ОжиданиеОбновления Тогда
		СостояниеВыгрузки.Состояние = Перечисления.СостоянияМиграцииПриложения.Выполняется;
		СостояниеВыгрузки.Записать();
		Возврат;
	КонецЕсли;
	
	
	НомерСообщения = СостояниеВыгрузки.НомерОтправленногоСообщения + 1;
		
	Если (СостояниеВыгрузки.НомерОтправленногоСообщения - СостояниеЗагрузки.НомерПринятогоСообщения) >= МаксимальнаяОчередьЗагрузки() Тогда
		
		ЗаполнитьСостояниеВыгрузки(СостояниеВыгрузки, СостояниеЗагрузки, УзелОбмена);
		СостояниеВыгрузки.Записать();
		
		Возврат;
		
	ИначеЕсли СостояниеЗагрузки.ЗавершеноСОшибками Тогда
		
		ЗаполнитьСостояниеВыгрузки(СостояниеВыгрузки, СостояниеЗагрузки, УзелОбмена);
		СостояниеВыгрузки.ДатаЗавершения = ТекущаяУниверсальнаяДата();
		РегламентныеЗаданияСервер.УдалитьЗадание(Метаданные.РегламентныеЗадания.МиграцияПриложенийВыгрузка);
		УзелОбмена.ПолучитьОбъект().Удалить();
		СостояниеВыгрузки.Записать();
		
		Возврат;
		
	ИначеЕсли СостояниеВыгрузки.Состояние = Перечисления.СостоянияМиграцииПриложения.ОжиданиеЗагрузки Тогда
		// Сообщения больше не формируются, а только ожидается когда все будет загружено.
		НачатьТранзакцию();
		Попытка
			Если Не СостояниеЗагрузки.ВыполняетсяЗагрузка Тогда
				СостояниеВыгрузки.ДатаЗавершения = ТекущаяУниверсальнаяДата();
				СостояниеВыгрузки.Состояние = Перечисления.СостоянияМиграцииПриложения.ЗавершенаУспешно;
				СостояниеВыгрузки.Комментарий = НСтр("ru = 'Переход завершен.'");
				СостояниеВыгрузки.УзелОбмена = Неопределено;
				РегламентныеЗаданияСервер.УдалитьЗадание(Метаданные.РегламентныеЗадания.МиграцияПриложенийВыгрузка);
				УзелОбмена.ПолучитьОбъект().Удалить();
			КонецЕсли;
			ЗаполнитьСостояниеВыгрузки(СостояниеВыгрузки, СостояниеЗагрузки, УзелОбмена);
			СостояниеВыгрузки.Записать();
			ЗафиксироватьТранзакцию();
		Исключение
			ОтменитьТранзакцию();
			ВызватьИсключение;
		КонецПопытки;
		Возврат;
	КонецЕсли;
	
	КаталогВыгрузки = ПолучитьИмяВременногоФайла("AppMigrationOut") + ПолучитьРазделительПути();
	СоздатьКаталог(КаталогВыгрузки);
	
	
	НачатьТранзакцию();
	Попытка
		
		Результат = ВыгрузитьДанныеВКаталог(КаталогВыгрузки, 
			УзелОбмена, 
			НомерСообщения, 
			СостояниеВыгрузки.ПоследнийОбъектМетаданных, 
			СостояниеВыгрузки.ВыгружатьНастройкиПользователей.Получить(), 
			СостояниеВыгрузки.ЗавершитьМиграциюАвтоматически Или ЗавершитьМиграцию);
		
	Исключение
		
		ОтменитьТранзакцию();
		ИнформацияОбОшибке = ИнформацияОбОшибке();
		СостояниеВыгрузки.КоличествоПопыток = СостояниеВыгрузки.КоличествоПопыток + 1;
		СостояниеВыгрузки.ДатаПоследнейВыгрузки = ТекущаяУниверсальнаяДата();
			
		ЗаполнитьСостояниеВыгрузки(СостояниеВыгрузки, СостояниеЗагрузки, УзелОбмена);
		
		Если СостояниеВыгрузки.КоличествоПопыток >= 3 Тогда
						
			ЗавершитьВыгрузкуСОшибкой(СостояниеВыгрузки, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке), КраткоеПредставлениеОшибки(ИнформацияОбОшибке));			
			
		Иначе
			
			СостояниеВыгрузки.Комментарий = КраткоеПредставлениеОшибки(ИнформацияОбОшибке);
			СостояниеВыгрузки.Записать();
			
			РегистрацияОшибки(НСтр("ru = 'Выгрузка'", ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка()), ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
			
		КонецЕсли;
		
		Возврат;
		
	КонецПопытки;
	
	Попытка
		// Сообщение отправляется только если в нем есть данные.
		Если Результат.КоличествоОбъектов > 0 Или Результат.ЭтоПоследнееСообщение Тогда
		
			ИмяФайлаАрхива = ПолучитьИмяВременногоФайла("zip");
			ЗаписьZIP = Новый ЗаписьZipФайла(ИмяФайлаАрхива);
			ЗаписьZIP.Добавить(КаталогВыгрузки + "*", РежимСохраненияПутейZIP.СохранятьОтносительныеПути, РежимОбработкиПодкаталоговZIP.ОбрабатыватьРекурсивно);
			ЗаписьZIP.Записать();
			
			СостояниеВыгрузки.НомерОтправленногоСообщения = НомерСообщения;
			СостояниеВыгрузки.ВыгруженоОбъектов = СостояниеВыгрузки.ВыгруженоОбъектов + Результат.КоличествоОбъектов;
			СостояниеВыгрузки.КоличествоПопыток = 0;
			СостояниеВыгрузки.ДатаПоследнейВыгрузки = ТекущаяУниверсальнаяДата();
			СостояниеВыгрузки.Комментарий = "";
			Если Результат.ЭтоПоследнееСообщение Тогда
				СостояниеВыгрузки.Состояние = Перечисления.СостоянияМиграцииПриложения.ОжиданиеЗагрузки;
			КонецЕсли;
			СостояниеВыгрузки.Записать();
			
			СостояниеЗагрузки = ОтправитьСообщениеВСервис(ПараметрыДоступа, ИмяФайлаАрхива);
			
		КонецЕсли;
		
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
	ЗаполнитьСостояниеВыгрузки(СостояниеВыгрузки, СостояниеЗагрузки, УзелОбмена);
	СостояниеВыгрузки.Записать();
	
	Попытка
		УдалитьФайлы(ИмяФайлаАрхива);
	Исключение
		ПредставлениеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		РегистрацияОшибки(НСтр("ru = 'Выгрузка'", ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка()), ПредставлениеОшибки);
	КонецПопытки;
			
	Попытка
		УдалитьФайлы(КаталогВыгрузки);
	Исключение
		ПредставлениеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		РегистрацияОшибки(НСтр("ru = 'Выгрузка'", ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка()), ПредставлениеОшибки);
	КонецПопытки;
	
КонецПроцедуры

///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

Рекомендации

Похожие публикации

ЭкспортОценкиПроизводительности (БСП)

НаименованиеФоновогоРезервногоКопирования (БСП)

ИмяМетодаФоновогоРезервногоКопирования (БСП)

НачатьВыгрузку (БСП)

ОтменитьВыгрузку (БСП)

СостояниеВыгрузки (БСП)

ПриВыгрузкеОбъекта (БСП)

ПриВыгрузкеДанных (БСП)

Выгрузка запроса в XML. Выгрузка объекта

Обновлятор-1С: групповое (пакетное) обновление и обслуживание всех баз за один раз