Волшебное улучшение обменов по правилам через COM-соединение

Обмен - Перенос данных из 1C8 в 1C8

В типовых конфигурациях есть замечательный механизм обмена по правилам через COM-соединение. Объекты по одному передаются из базы-источника в базу-приемник, подключенную через COM. В результате не требуется промежуточный файл обмена, иногда большой и процесс обмена более контролируемый. Тем не менее, типовой механизм можно улучшить и добиться, чтобы, как только объект передавался в базу-получатель, сразу же бы удалялась и регистрация изменений для базы-получателя. Несколько строк кода приносят волшебный эффект!

Назначение улучшения

Улучшение позволяет принести много положительных эффектов в обмены через COM:

  1. Основная цель. Если выгрузка(загрузка) завершается с ошибкой, то уже переданные объекты не будут передаваться повторно. Особенно это хорошо в случаях, когда обмены не проходили длительное время и накопился большой объем изменений. Большие обмены длятся долго и могут вылететь, их приходится назначать сначала.
  2. Борьба с коллизиями. Если даже выгрузка происходит успешно, но не происходит загрузки, нет подтверждения о том, что объект получен, соответственно, он будет передаваться еще раз. Это может привести к коллизиям, т.к. за время между обменами объект могли изменить. Мы можем удалить регистрацию изменений и не дожидаясь подтверждения в виде загрузки из базы-получателя, ведь и так понятно, что объект туда ушел.
  3. Страх отложенных движений. Когда документ передается повторно, он распроводится. Это пугает пользователей, они видят, что документ был сперва проведен, потом распроводится. Особенно это страшно в случае больших обменов, когда могут распроводиться большие массивы документов. По этой схеме документ передается только один раз.

 

Реализация

Сначала я беспокоился, что обмен по COM-соединению реализован через выгрузку во временный файл обмена. Но, к счастью, передача идет по одному объекту.

 

Изменения нужно вносить в обработку ОбменДаннымиXML: в процедуру ВыполнитьВыгрузкуИзмененныхДанныхДляУзлаОбмена в цикл по перебору изменений. Добавляемый код выделен жирным курсивом:

ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель, ЗаписьСообщения.НомерСообщения, МассивВыгружаемыхМетаданных);

                                       

       Пока ВыборкаИзменений.Следующий() Цикл

 

              //Осипов - сразу удаляем регистрацию измений, отмечаем что передали...

              Если НепосредственноеЧтениеВИБПриемнике Тогда //Типовой флаг. Обозначает обмен через COM

                    ПланыОбмена.УдалитьРегистрациюИзменений(ЗаписьСообщения.Получатель, Данные);

             КонецЕсли;

 

      

             Если ИспользоватьТранзакцииПриВыгрузкеДляПлановОбмена

             И (КоличествоЭлементовВТранзакцииПриВыгрузкеДляПлановОбмена > 0)

             И (КоличествоНайденныхДляЗаписиОбъектов = КоличествоЭлементовВТранзакцииПриВыгрузкеДляПлановОбмена) Тогда

                          

                    // промежуточную транзакцию закрываем и открываем новую

                    ЗафиксироватьТранзакцию();

                     НачатьТранзакцию();

                    КоличествоНайденныхДляЗаписиОбъектов = 0;

             КонецЕсли;

                   

       КонецЦикла;

 

Важно! Изменения нужно добавить в код обработок обеих базах. Почему? Обычно обмен двухсторонний.

Обмен происходит в процедуре ПроцедурыОбменаДанными. ВыполнитьОбменДаннымиЧерезComСоединение.

Сначала происходит загрузка из базы-приемника, при этом вызывается экземпляр обработки обмена из базы-приемника  ОбработкаОбменаПриемника.ВыполнитьВыгрузку. Поэтому важно, чтобы в базе-приемнике обработка тоже была пропатчена аналогичным образом.

Затем идет выгрузка из базы-отправителя, используется уже обработка из базы-отправителя

ВыполнитьВыгрузку.     

 

Проверка

В журнале регистрации базы-получателя видим, что пришел документ РОТ 3006:

 

 

 

В мониторе обмена в базе-отправителе видим, что объект зарегистрирован:

 

Теперь выполним код по удалению, посмотрим монитор обмена, однако вместо ожидаемого удаления документа РОТ из зарегистрированных изменений увидим ошибку:

Дело в том, что в настройке обмена указан размер транзакции – 200 объектов:

Поэтому нужно подождать буквально несколько секунд, транзакция завершится и мы увидим, что документ исчез из зарегистрированных изменений.

Еще одно свидетельство, до обмена количество зарегистрированных изменений было большим:

После обмена добавились только свежие изменения (в тестовой базе активно работают пользователи):

Заключение

Эта статья замечательно показывает, как минимальное, точечное вмешательство, может привести к потрясающему эффекту. Как тут не вспомнить анекдот про сантехника, который приходит, тыкает пальцем и берет за это 1000 рублей, объясняя – сам тык стоит 1 рубль, но время, в течении которого я изучал этот тык стоит 999 рублей.

 

Сначала я обсуждал эту проблему на инфостарте в контексте:

1С:Предприятие 8.1 (8.1.15.14)
"Управление торговлей", редакция 10.3 (10.3.7.9)
В УТ настроен обмен с Розницей по правилам обмена через COM-соединение.
Хочу, чтобы при выгузке из УТ в Розницу (из базы-отправителя в базу-получатель), когда документ передан в базу-получатель и зарегистрирован в отложенных движениях, чтобы он удалялся из плана-обмена базы-отправителя (УТ).
Т.к. иногда выгрузка не доходит до конца, или же не получает подтверждения, чтобы данные повторно не гонялись
.

 

К сожалению, никто мне там не подсказал этого замечательного решения, пришлось до всего додумываться самому.

См. также

Комментарии
1. Сергѣй Батанов (baton_pk) 205 13.08.13 09:48 Сейчас в теме
Разумно. У нас дабы не менять конфу удаление регистрации сделано в правилах обмена в обработчике "После выгрузки в файл". Если б дали конфу менять, то сделал бы скорее всего так же.
2. Осипов Сергей (fixin) 3557 13.08.13 11:16 Сейчас в теме
(1) возможно, но сложно. Так проще. главное, что я к этому долго шел и не получалось все никак.
3. Сергѣй Батанов (baton_pk) 205 13.08.13 11:32 Сейчас в теме
4. Осипов Сергей (fixin) 3557 13.08.13 11:59 Сейчас в теме
(3) видишь ли, я мечтал об этом год. А оказалось, что все так просто. Теперь если слетает обмен, то ничего страшного, то что уже прошло, повторно не пойдет....
5. Игорь Дзеса (Kamikadze) 44 15.08.13 10:50 Сейчас в теме
У себя пошел подобным путем, но есть одно НО - ошибки при обменах трудно ловить, так как в режиме сервера сообщения не выводяться. Сейчас думаю над сообщениями об ошибках и впринципе - все будет работать как часики.
6. Осипов Сергей (fixin) 3557 15.08.13 10:59 Сейчас в теме
(5) журнал регистрации на что? ;-)
или регистр сведений.
7. Игорь Дзеса (Kamikadze) 44 15.08.13 11:26 Сейчас в теме
Журнал регистрации 1С меня не устраивает по быстродействию.
8. Осипов Сергей (fixin) 3557 15.08.13 11:46 Сейчас в теме
(7) пиши в свой лог в файл. или в регистр сведений.
9. Роман Сюзев (sorb) 04.09.13 12:21 Сейчас в теме
О-О-О! Долго руки не доходили разобраться, а тут такой подарок, спасибо! Для обменов на базе БСП это тоже действительно?
10. Роман Сюзев (sorb) 04.09.13 12:48 Сейчас в теме
Посмотрел, для БСП можно аналогично поправить обработку КонвертацияОбъектовИнформационныхБаз, процедура ВыполнитьВыгрузкуЗарегистрированныхДанных. Ищем текст:

УзелДляОбменаОбъект = УзелДляОбмена.ПолучитьОбъект();

дальше идет обход выборки:
Пока ВыборкаИзменений.Следующий() Цикл

Идем в конец цикла, видим условие:
Если ЭтоОбменЧерезВнешнееСоединение Тогда

внутрь добавляем:
ПланыОбмена.УдалитьРегистрациюИзменений(УзелДляОбмена, Данные);
11. Осипов Сергей (fixin) 3557 04.09.13 13:13 Сейчас в теме
(10) Интересно, Селезневские примут этот мой патч к сведению, или и дальше будут мучать пользователей COM-обменов?
12. Роман Сюзев (sorb) 04.09.13 16:14 Сейчас в теме
(11) fixin, думаю они на своем Такси вряд ли до этого доберутся :)
13. Осипов Сергей (fixin) 3557 04.09.13 16:57 Сейчас в теме
(12) жаль, что 1С не такая дружелюбная контора как хотелось бы. ;-)
Я считаю это упущенными возможностями конторы к развитию.
Если она общается только по закрытым каналам.
14. Антон Стеклов (asved.ru) 33 24.09.13 05:49 Сейчас в теме
Поправочка: закрываем мы не промежуточную транзакцию, а всю имеющуюся. Вложенные транзакции 1С не поддерживаются.
15. Димко Захарофф (DimkoZah) 4 07.10.13 21:47 Сейчас в теме
А по-моему поддерживаются... Натыкался на вложенность транзакций в РТ 1.0 при очередном обновлении платформы - документ ОРП создавался заполнялся и записывался а транзакция не закрыта даже после ЗафиксироватьТранзакцию(). Приходилось дополнительно проверять открыта транзакция или нет.
16. Ivan Kovtun (i.kovtun) 119 08.10.13 14:58 Сейчас в теме
(15)DimkoZah,
Предприятие 8 не поддерживает вложенные транзакции. Все "вложенные транзакции" сливаются в одну. Но это не значит, что транзакция завершится после первого вызова ЗафиксироватьТранзакцию() или ОтменитьТранзакцию().
Если количество вызовов метода НачатьТранзакцию() превышает количество вызовов методов ЗафиксироватьТранзакцию() или ОтменитьТранзакцию(), то система выполнит неявный вызов метода ОтменитьТранзакцию() в следующих случаях:

● при окончании выполнения встроенного языка (обработчик события, внешнее соединение, automation-сервер);

● при передаче управления с сервера на клиента.


1С:Предприятие 8.2. Документация/Глава 9. Работа с данными/9.2. Механизм транзакций/9.2.1. Использование явного вызова транзакций; 9.2.2. Вложенный вызов транзакций
17. Димко Захарофф (DimkoZah) 4 09.10.13 01:45 Сейчас в теме
(16) i.kovtun, Благодарю! Вот только у меня есть вопрос: Почему возникла такая ситуация, что при закрытии смены документ Отчет о розничных продажах НЕ СОХРАНЯЛСЯ в базе из-за незакрытой транзакции (отловил в журнале)? Конфигурация при этом не изменялась, не обновлялась. Точно не помню сохранялся ли первый документ... Конфигурация дорабатывалась под множество фискальников.
18. Ivan Kovtun (i.kovtun) 119 09.10.13 11:21 Сейчас в теме
(17) DimkoZah,
Трудно сказать. Чтобы разобраться нужно, во-первых, воспроизвести повторяемый кейс, проверить наличие исключений (в том числе завернутых в попытку), возможно придется продебажить. Ну и всегда остается очень маленькая вероятность ошибки в платформе.
19. Анянов Михаил (insurgut) 161 10.02.14 11:57 Сейчас в теме
Проще было сделать 2 односторонних обмена - результат тот же, доработок - никаких.
20. Анянов Михаил (insurgut) 161 10.02.14 12:00 Сейчас в теме
(11) fixin, какой патч? Если обмен двусторонний он будет являться успешным при одновременной выгрузке/загрузке. Идеология отличная, и ничего тут собственно менять не требуется. Для того, что вы реализовали есть типовое решение в комментарии выше.
21. Осипов Сергей (fixin) 3557 10.02.14 12:46 Сейчас в теме
(20) вы таки не поняли сути. вам - на перечитку.
22. Айтуар Баубериков (Bajo) 18 13.02.14 10:54 Сейчас в теме
(21) fixin, а где можно скачать обработку?
23. Осипов Сергей (fixin) 3557 13.02.14 13:52 Сейчас в теме
(22) какую обработку? это вмешательство в код, а не обработка.
24. Павел Парамонов (anchovy) 4 28.03.14 14:16 Сейчас в теме
Позволю себе немного критики.
Это только половина решения, т.к. подобное вмешательство отрезает часть логики типового обмена, отвечающую за проверку результата выгрузки. На что и указал в (5)Kamikadze. Про то, что нужно это как-то компенсировать, в статье ничего нет.
Если бы это было представлено как финальное сообщение в обсуждении тут http://forum.infostart.ru/forum42/topic58449/ , то было бы понятно. Но на статью это явно не тянет - не хватает завершенности.
25. Осипов Сергей (fixin) 3557 28.03.14 14:47 Сейчас в теме
(24) не понял вашего замечания. О каком отрезании логики идет речь?
Если объект передался по правилам, его можно исключть из регистрации в планах обмена. Не вижу тут проблем, может укажете?
26. Анянов Михаил (insurgut) 161 29.03.14 11:06 Сейчас в теме
(25) fixin, ну да, если запись регистра подчиненная регистратору передана - можно снимать с регистрации, ну если потом произойдет ошибка при передаче самого регистратора - ничего страшного :)
27. Осипов Сергей (fixin) 3557 29.03.14 15:52 Сейчас в теме
(26) Вы великий теоретик, да.
А ничего, что:
1. При обмене УТ-Розница движения не передаются, документы просто перепроводятся.
2. Если передастся только регистратор, со следующей порцией передаются и движения по регистрам.

Я тащемто практик.
28. Анянов Михаил (insurgut) 161 30.03.14 13:33 Сейчас в теме
(27) fixin, Я как раз таки больше практик, чем теоретик. :) А примем тут УТ-Розница? Решение же вы предлагаете универсальное, т.е. какие правила используются - не имеет значение. Будь они типовыми, или написанными самостоятельно.
Не спорю, что решение ваше имеет право на жизнь, просто с определенными условиями и ограничениями.
29. Осипов Сергей (fixin) 3557 30.03.14 17:21 Сейчас в теме
(28) мне кажется, что человек способный понять и внедрить это решение, по умолчанию обладает достаточной квалификацией, чтобы понять, применимо это решение или нет.
Все же это методика не для чайников 1С. ;-)
30. Анянов Михаил (insurgut) 161 31.03.14 09:39 Сейчас в теме
(29) fixin, тут с вами соглашусь полностью :)
31. Павел Парамонов (anchovy) 4 01.04.14 17:09 Сейчас в теме
(25) fixin, Я же вроде указал, что отрезается алгоритм проверки результата выгрузки. Запись со ссылкой на выгруженный объект удаляется из таблицы регистрации изменений сразу после выгрузки. Т.е. на стороне выгрузки не получаем сообщение об успешности загрузки и лишаемся возможности что-либо предпринять.
Соответственно это не волшебство улучшения типового механизма, а хак, да еще и с побочными явлениями. О чем и нужно предупреждать в статье. Речь только об этом.
32. Роман Сюзев (sorb) 04.10.14 21:44 Сейчас в теме
(31) anchovy, Хоть давно был последний пост, но... в случае БСП все алгоритмы после загрузки отрабатываются сразу после загрузки самого объекта, поэтому ничего не теряется. В случае до БСП действительно удаление нужно делать немного позже, чем предложено у fixin. Но это никоим образом не умаляет ценность статьи автора - лично я кучу времени сэкономил, так как очень долго не доходили руки выполнить анализ механизма.
33. Андрей Ромашов (LsrGroup) 16.10.14 12:00 Сейчас в теме
Такой подход можно применять, но только есть одно большое НО, которое надо всегда помнить.

Напомню, как работает ВыбратьИзменения: в процессе выборки изменений в записи регистрации изменений проставляется номер сообщения обмена данными, "фиксируя" старт обмена. Если после этого данные были изменены, то в номер сообщения проставляется Null.
И если мы удаляем регистрацию по номеру сообщения - то удаляются только данные по тем объектам, которые были выгружены И НЕ ИЗМЕНЕНЫ за время выгрузки! Если удаляем просто по ссылке - то есть вероятность очистить регистрацию по измененным объектам в течении обмена, и соответственно, не выгрузить часть изменений.
Это нужно хорошо помнить, так как вероятность ошибки увеличивается при большом кол-ве изменений во время обмена и больших пакетах выгрузки.
WellMaster; Irwin; vlad.frost; agarych; tormozit; Mick2iS; +6 Ответить
Оставьте свое сообщение