gifts2017

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

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

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

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

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

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

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

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


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

Я тащемто практик.
28. Анянов Михаил (insurgut) 30.03.14 13:33
(27) fixin, Я как раз таки больше практик, чем теоретик. :) А примем тут УТ-Розница? Решение же вы предлагаете универсальное, т.е. какие правила используются - не имеет значение. Будь они типовыми, или написанными самостоятельно.
Не спорю, что решение ваше имеет право на жизнь, просто с определенными условиями и ограничениями.
29. Осипов Сергей (fixin) 30.03.14 17:21
(28) мне кажется, что человек способный понять и внедрить это решение, по умолчанию обладает достаточной квалификацией, чтобы понять, применимо это решение или нет.
Все же это методика не для чайников 1С. ;-)
30. Анянов Михаил (insurgut) 31.03.14 09:39
(29) fixin, тут с вами соглашусь полностью :)
31. Павел Парамонов (anchovy) 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.
И если мы удаляем регистрацию по номеру сообщения - то удаляются только данные по тем объектам, которые были выгружены И НЕ ИЗМЕНЕНЫ за время выгрузки! Если удаляем просто по ссылке - то есть вероятность очистить регистрацию по измененным объектам в течении обмена, и соответственно, не выгрузить часть изменений.
Это нужно хорошо помнить, так как вероятность ошибки увеличивается при большом кол-ве изменений во время обмена и больших пакетах выгрузки.
Irwin; vlad.frost; agarych; tormozit; Mick2iS; +5 Ответить