Механизм обмена данными

Механизм обмена данными — это набор средств, предназначенных для организации обмена данными между «1С:Шиной» и:
  • другими приложениями «1С:Шины»;
  • информационными базами «1С:Предприятия»;
  • иными внешними информационными системами.

Центром механизма обмена данными являются планы обмена. В одном проекте можно определить произвольное количество планов обмена. Элементами данных плана обмена являются узлы плана обмена, подобно тому как элементами данных справочника являются элементы справочника. Каждый из узлов плана обмена обозначает участника обмена данными по данному плану обмена. Один из узлов соответствует данной информационной базе, а остальные — другим участникам, с которыми данная информационная база может обмениваться данными:

В планах обмена можно выделить три значимые составляющие:

Для реализации механизма обмена изменениями в «1С:Шине» предназначен элемент проекта План Обмена. Данный элемент позволяет описать:
  • элементы проекта, в которых будет осуществляться регистрация изменения в данных;
  • Участников обмена.
Приложения, которые обмениваются изменениями данных, называются узлами плана обмена. Узлы добавляются администратором в конкретном приложении, аналогично добавлению элементов справочника.

Состав плана обмена (элементы проекта, в которых регистрируются изменения данных) распространяется на все узлы данного плана обмена. Если с разными узлами нужно обмениваться разным составом информации, то необходимо создавать несколько планов обмена, в которых следует объединить узлы, обменивающиеся одинаковым составом информации.

Планы обмена подходят для относительно редких обменов данными, например, с периодичностью переноса изменений 1 раз в 10 минут.

Инфраструктура сообщений

Данные переносятся с помощью сообщений. Сообщения передаются в рамках плана обмена от одного узла другому. Средства работы с сообщениями образуют инфраструктуру сообщений. Каждое сообщение:
  • относится к определенному плану обмена;
  • имеет определенный узел-отправитель и определенный узел-получатель.
Сообщение не может быть отправлено неизвестному узлу и не может быть принято от неизвестного узла. Каждое сообщение имеет свой собственный целочисленный номер. С точки зрения инфраструктуры сообщений у узла существуют два свойства:
  • Номер отправленного сообщения,
  • Номер принятого сообщения.

Для узла, соответствующий текущему приложению, эти свойства смысла не имеют (база данных сама с собой данными не обменивается).

Важнейшей составляющей инфраструктуры сообщений являются сами сообщения. Сообщение оформляется как документ XML, имеющий определенную структуру. В качестве примера рассмотрим следующее сообщение:
<v8msg:Message xmlns:v8msg="http://v8.1c.ru/messages">
   <v8msg:Header>
      <v8msg:ExchangePlan>УдаленныеСклады</v8msg:ExchangePlan>
      <v8msg:To>Оптовый</v8msg:To>
      <v8msg:From>ЦентрОфис</v8msg:From>
      <v8msg:MessageNo>20</v8msg:MessageNo>
      <v8msg:ReceivedNo>15</v8msg:ReceivedNo>
   </v8msg:Header>
   <v8msg:Body>
      <!— Тело сообщения -->
   </v8msg:Body>
</v8msg:Message>
Всё сообщение находится внутри элемента XML с именем Message, относящимся к пространству имен http://v8.1c.ru/messages. Сообщение состоит из:
  • заголовка — Header;
  • тела сообщения — Body.

Они также относятся к пространству имен http://v8.1c.ru/messages.

Структура заголовка жестко задана. Информация заголовка представлена в нескольких элементах XML, вложенных в элемент Header. Все элементы, вложенные в элемент Header, относятся к пространству имен http://v8.1c.ru/messages.

  • Элемент с именем ExchangePlan содержит имя плана обмена, к которому относится сообщение. Имена планов обмена должны совпадать в системах, взаимодействующих через планы обмена.
  • Элемент с именем From содержит код узла-отправителя.
  • Элемент с именем To содержит код узла-получателя.
  • Элемент с именем MessageNo содержит номер данного сообщения. Номер сообщения является положительным целым числом и присваивается узлом-отправителем. Номер каждого последующего сообщения равен номеру предыдущего отправленного сообщения плюс 1.
  • Элемент с именем ReceivedNo содержит максимальный номер сообщения, которое узел-отправитель данного сообщения принял от узла-получателя данного сообщения. Данное значение включено в состав заголовка сообщения для подтверждения приема сообщений.
Тело сообщения содержится в элементе XML с именем Body, относящимся к пространству имен http://v8.1c.ru/messages. Данный элемент может иметь произвольное содержимое, определяемое прикладными потребностями. Инфраструктурой сообщений содержимое тела сообщения никак не регламентируется.
Важно: Если вы настраиваете обмен данными с информационными базами «1С:Предприятия», при формировании тела сообщения важно придерживаться формата XML-сериализации, который используется в механизмах обмена данными «1С:Предприятия».
Сообщение для отправки может быть создано следующим образом:
метод ЗаписатьСообщениеОбмена(КодУзлаПолучателя : Строка, ИмяФайла : Строка)
    пер Узел = УдаленныеСклады.НайтиПоКоду(КодУзлаПолучателя)
 
    пер ФайлСообщенияОбмена = новый Файл(ИмяФайла)
    пер ЗаписьXml = новый ЗаписьXml(ФайлСообщенияОбмена.ОткрытьПотокЗаписи())
    исп ОбработкаИсходящегоСообщения = УдаленныеСклады.СоздатьОбработкуИсходящегоСообщения(ЗаписьXml,  Узел)
     
        // Заполнение тела сообщения
        для Данные из УдаленныеСклады.ВыбратьИзмененияВСообщение(Узел, НомерСообщения)
           // Запись данных, делает разработчик проекта
            ЗаписатьДанныеВСообщениеОбмена(ОбработкаИсходящегоСообщения, Данные)
       ;
 ;

В результате вызова метода СоздатьОбработкуИсходящегоСообщения() создается объект типа ОбработкаИсходящегоСообщенияОбмена, с помощью которого может быть произведена запись одного или нескольких сообщений обмена данными, а также вызывается начало записи этих сообщений. В качестве первого параметра метода передается объект типа ЗаписьXML, в качестве второго — ссылка на узел-получатель плана обмена.

При обращении к методу сообщению присваивается номер, определяемый как номер предыдущего отправленного сообщения, увеличенный на 1. Далее производится запись в XML заголовка сообщения, а также записывается начало элемента XML, соответствующего телу сообщения. В начале записи сообщения устанавливается блокировка на запись базы данных, соответствующую узлу плана обмена, чтобы предотвратить на время записи сообщения другие операции чтения и записи сообщений, относящихся к данному узлу, а также не допустить изменения данных узла. Сообщение считается отправленным только тогда, когда будет произведено обращение к методу Закончить()

В результате вызова метода ВыбратьИзмененияВСообщение() из таблиц регистрации изменений объектов формируется выборка измененных данных для передачи их в тот или иной узел плана обмена. При этом, в процессе выборки изменений, если в записи регистрации изменений не проставлен номер сообщения, то проставляется номер сообщения обмена данными, в котором должны передаваться изменения. Номер сообщения в записи регистрации проставляется для того, чтобы при подтверждении приема сообщения, в котором передавались изменения, соответствующие записи регистрации изменений были удалены и в дальнейшем изменения больше не передавались.

Метод ЗаписатьДанныеВСообщениеОбмена() разработчику следует определить самостоятельно.

Завершить запись сообщения можно с помощью трех методов объекта ОбработкаИсходящегоСообщенияОбмена:
  • Завершить()

    Осуществляет нормальное завершение записи сообщения. При нормальном завершении в сообщение записывается конец элемента XML, представляющего тело сообщения, а в запись узла плана обмена записывается номер сообщения обмена данными. Блокировка с записи узла плана обмена снимается, и сообщение считается отправленным.

  • Отменить()

    Прерывает запись сообщения. Сообщение при этом считается неотправленным. Запись сообщения обмена может быть завершена либо обращением к методу Завершить(), либо обращением к методу Отменить().

  • Закрыть() (вызывается автоматически при выходе из области видимости)

    Выполняется метод Отменить(), если закрытие произошло из-за выброса исключения. В ином случае выполняется метод Завершить()

Для чтения записанного в файл сообщения обмена в базе узла-получателя может использоваться следующий фрагмент кода:
метод ПрочитатьXmlСообщениеОбмена(Отправитель: Склады.Ссылка, ПотокФайла: ПотокЧтения)
    знч ЧтениеXml = новый ЧтениеXml(ПотокФайла)
    исп ГрупповаяОперация.Начать(РежимЗагрузкиДанных = Истина)
    // TODO убрать после отладки ДопустимыйНомерСообщения.Любой
    исп ОбработкаВходящегоСообщенияОбмена = Склады.СоздатьОбработкуВходящегоСообщения(ЧтениеXml, 
                                                                                       ДопустимыйНомерСообщения.Больший)
    знч ОтправительСсылка = ОбработкаВходящегоСообщенияОбмена.Отправитель как Склады.Ссылка
    если ОтправительСсылка != Отправитель
        выбросить новый ИсключениеНедопустимоеСостояние("Отправитель в сообщении отличается от отправителя каталога")
    ;
    Склады.УдалитьРегистрациюИзмененийПоСообщению(ОтправительСсылка, ОбработкаВходящегоСообщенияОбмена.НомерПринятого)
    пока ЧтениеXml.ВидУзла == ВидУзлаXml.НачалоЭлемента
        ПрочитатьИзменениеДанных(ЧтениеXml, ОтправительСсылка)
    ;
;    

При вызове метода СоздатьОбработкуВходящегоСообщения(ЧтениеXml) создается объект, с помощью которого может быть произведено чтение одного или нескольких сообщений обмена данными. При этом производится чтение заголовка сообщения обмена данными и проверяются содержащиеся в заголовке данные. Если какие-либо данные указаны неправильно (задан неизвестный план обмена, указан узел, не входящий в план обмена, номер сообщения не соответствует ожидаемому), вызывается исключение. В начале чтения сообщения устанавливается блокировка на запись базы данных, соответствующую узлу плана обмена, чтобы предотвратить на время чтения сообщения другие операции чтения и записи сообщений, относящихся к данному узлу, а также не допустить изменения данных узла.

Используя второй параметр ДопустимыйНомерСообщения, можно установить вариант ожидаемого номера сообщения:

  • Любой (фактически контроль номеров сообщения не производится);
  • Больший (любой номер, больший чем максимальный номер принятого сообщения);
  • Следующий (строго больший на единицу, чем предыдущий).

Следует обратить внимание на тот факт, что в приведенном фрагменте кода нет указания ни на используемый план обмена (их в конфигурации может быть несколько), ни на узел-отправитель. Данная информация получается из заголовка сообщения.

Завершить чтение сообщения можно с использованием трех методов:

  • Завершить()

    Вызывает попытку нормального завершения чтения сообщения. При этом проверяется нормальное завершение сообщения. Если обнаружен конец элемента XML, соответствующего телу сообщения, то в случае превышения номером сообщения максимального номера принятого сообщения, он помещается в реквизит НомерПринятого узла плана обмена. Блокировка записи узла плана обмена снимается и сообщение считается принятым.

  • Отменить()

    Вызывает немедленное прерывание чтения сообщения. Блокировка с записи базы данных, соответствующей узлу плана обмена, снимается, и в нее не вносится никаких изменений.

  • Закрыть() (вызывается автоматически при выходе из области видимости)

    Выполняется метод Отменить(), если закрытие произошло из-за выброса исключения. В ином случае выполняется метод Завершить()

При вызове метода УдалитьРегистрациюИзмененийПоНомеру() из таблиц регистрации изменений объектов удаляются регистрации изменений, относящиеся к указанному узлу, с номером сообщения меньшим или равным значению переданного номера сообщения.

Метод ПрочитатьИзмененияИзСообщенияОбмена() разработчику следует определить самостоятельно.

Служба регистрации изменений

Служба регистрации изменений предназначена для регистрации изменений данных, производимых «1С:Шиной», чтобы при обмене данными иметь возможность передавать не все данные, а только новые, измененные или удаленные. Эти элементы данных должны быть переданы в очередном сообщении тому или иному узлу, с которым производится обмен данными. При каждом изменении данных должно быть зарегистрировано, что имеются изменения и их предстоит передать во все узлы, с которыми поддерживается обмен этими данными. При получении подтверждения приема сообщения, в котором были отправлены изменения, записи регистрации изменений должны быть удалены.

При определении состава объектов, для которых производится регистрация изменений (свойство Состав элемента проекта План обмена), для каждого объекта можно определить свойство АвтоРегистрация: Включено. Авторегистрацию можно разрешить или запретить. Если авторегистрация разрешена, то при изменении данных регистрация будет выполнена автоматически. Если запрещена, то регистрацию изменения необходимо выполнять «вручную» (определив код на встроенном языке). Следует отметить, что можно «корректировать» результат регистрации даже в том случае, когда авторегистрация объекта включена.

Регистрация изменений может выполняться для следующих элементов проекта:

Для каждого из приведенных элементов проекта ведется своя таблица регистрации изменений. Таблицы имеют разную структуру в зависимости от того, для каких элементов данных регистрируются изменения, однако структуры таблиц подобны. В структуре можно выделить три составляющих:

  • Ключ элемента данных, для которого регистрируются изменения;
  • Ссылка на узел, в который изменение должно быть передано;
  • Номер сообщения, в котором изменение передано в первый раз.

Следует отметить, что в конфигурации может быть определено несколько планов обмена. Для каждого из них может включаться регистрация изменений какого-либо объекта. Вне зависимости от количества планов обмена, в рамках которого регистрируются изменения какого-либо объекта, таблица регистрации изменений у объекта одна (таким образом, поле таблицы регистрации изменений, содержащее ссылку на узел плана обмена, может иметь составной тип).

Подтверждение приема сообщений

При использовании плана обмена осуществляется подтверждение приема-передачи сообщений. Эта функциональность реализуется благодаря тому, что заголовок сообщения, как было сказано ранее, содержит два обязательных элемента:
  • Элемент с именем MessageNo, который содержит номер данного сообщения.
  • Элемент с именем ReceivedNo, который содержит максимальный номер сообщения, которое узел-отправитель данного сообщения принял от узла-получателя данного сообщения. Данное значение включено в состав заголовка сообщения для подтверждения приема сообщений.
Структура элемента проекта План обмена подобна справочнику, где элементами являются узлы плана обмена. Для каждого узла существует четыре обязательных реквизита:
  • Код — код узла обмена, который используется для идентификации узла в другом узле обмена.
  • Номер отправленного — номер последнего сообщения, которое было отправлено в соответствующий узел обмена (MessageNo).
  • Номер принятого — номер последнего сообщения, которое было принято соответствующим узлом обмена (ReceivedNo).
  • Этот узел — узел, соответствующий данному приложению. Соответственно, для данного узла значения полей Номер отправленного и Номер принятого всегда равняются нулю.
Кроме того, существует один стандартный, однако необязательный реквизит:
  • Наименование — наименование узла обмена.

Рассмотрим на примере, каким образом реализуется подтверждение приема сообщений. Есть два приложения: «Офис» и «Склад», которые обмениваются изменениями данных в рамках плана обмена Склады:

  1. «Офис» отправляет сообщение на «Склад» с номером 1. В этот момент в заголовок сообщения, помимо прочих, будут записаны следующие значения:
    • MessageNo: 1 — номер сообщения, которое «Офис» отправляет на «Склад»
    • ReceivedNo: 0 — информации о том, что «Склад» принял какое-либо сообщение, пока нет.
    В приложении «Офис», в плане обмена для узла «Склад», изменится значение полей:
    • Номер отправленного: 0 > 1

  2. «Склад» принимает сообщение из «Офиса» с номером 1. Далее «Склад» отправляет сообщение в «Офис» с номером 1. В этот момент в заголовок сообщения, помимо прочих, будут записаны следующие значения:
    • MessageNo: 1 — номер сообщения, которое «Склад» отправляет в «Офис»
    • ReceivedNo: 1 — номер последнего сообщения, которое «Склад» принял от приложения «Офис».
    В приложении «Склад», в плане обмена для узла «Офис», изменится значение поля:
    • Номер отправленного: 0 > 1

  3. «Офис» принимает сообщение от приложения «Склад» с номером 1. Из заголовка сообщения будет считан номер последнего полученного складом сообщения: ReceivedNo: 1, после чего в приложении «Офис» в плане обмена для узла «Склад» изменится значение поля:
    • Номер принятого: 0 > 1

    • Затем сообщение из «Офиса» будет отправлено на «Склад». В этот момент в заголовок сообщения, помимо прочих, будут записаны следующие значения:
      • MessageNo: 2 — номер сообщения, которое «Офис» отправляет на «Склад»
      • ReceivedNo: 1 — номер последнего сообщения, которое «Офис» принял от приложения «Склад».
      В приложении «Офис», в плане обмена для узла «Склад», изменится значение поля:
      • Номер отправленного: 1 > 2

  4. «Склад» принимает сообщение от приложения «Офис» с номером 2. Из заголовка сообщения будет считан номер последнего полученного офисом сообщения: ReceivedNo: 1, после чего в приложении «Склад» в плане обмена для узла «Офис» изменится значение поля:
    • Номер принятого: 0 > 1

    • Затем сообщение со склада будет отправлено в офис. В этот момент в заголовок сообщения, помимо прочих, будут записаны следующие значения:
      • MessageNo: 2 — номер сообщения, которое «Склад» отправляет в «Офис»
      • ReceivedNo: 2 — номер последнего сообщения, которое «Склад» принял от приложения «Офис».
      В приложении «Склад», в плане обмена для узла «Офис», изменится значение полей:
      • Номер отправленного: 1 > 2

Прочая функциональность

Элемент проекта План Обмена также предоставляет следующую функциональность и логику работы с данными:
Порождаемые типы встроенного языка
План обмена, добавленный в проект, порождает во встроенном языке несколько типов. Они позволяют вам работать как с самим планом обмена, так и с его узлами. Некоторые из этих типов имеют модули. С помощью этих модулей вы можете изменять стандартное поведение плана обмена (обрабатывая его события) и расширять функциональность типа, которому принадлежит модуль (добавляя собственные методы)
Таблица языка запросов
Вы можете обращаться к данным плана обмена с помощью языка запросов. Для этого используйте таблицу плана обмена
Реквизиты плана обмена
Вы как разработчик можете создать для узлов плана обмена необходимое количество реквизитов. Реквизит — это составная часть элемента проекта, описывающая одно поле таблицы базы данных.
Совет: Реквизиты плана обмена могут реализовывать контракт типа и контракты сущности.
Множественные реквизиты
Реквизиты плана обмена, которые вы добавляете в проект, могут быть множественными. Это значит, что такой реквизит хранит не одно значение, а сразу несколько значений — Массив. Например, план обмена Офисы может иметь множественный реквизит Почты, в котором для каждого офиса хранятся все адреса электронной почты руководителей офиса
Табличная часть
Вместе с каждым элементом плана обмена может потребоваться хранить информацию, однородную по своей структуре. Количество строк такой информации заранее неизвестно и может быть разным у разных узлов плана обмена. Например, в каждом элементе плана обмена Офисы нужно хранить список руководителей офиса: их имена, номера телефонов и почты. Для этого можно использовать множественный реквизит плана обмена и хранимую структуру
Хранение двоичных данных
Реквизиты плана обмена, которые вы добавляете в проект, могут быть предназначены для хранения двоичных данных: файлов документов, изображений, видео и т. д. Как правило двоичные данные имеют большой размер, поэтому «1С:Шина» хранит их в специальных хранилищах, отдельно от других данных
Представление элемента
Представление — это строка, которая будет обозначать для пользователя тот или иной элемент (узел) плана обмена во время работы приложения. Вы можете настроить представление в соответствии со своими потребностями
Поиск узлов при вводе по строке
Во время работы приложения, чтобы выбрать один из узлов плана обмена, пользователь может просто начать вводить в поле ввода известный ему фрагмент названия, кода или другого реквизита плана обмена. «1С:Шина» автоматически подберет ему подходящие элементы. Вы можете задать список тех реквизитов плана обмена, в которых «1С:Шина» будет искать текст, введенный пользователем
Индексы базы данных
Для того чтобы запросы к данным выполнялись быстро, «1С:Шина» стандартно создает в СУБД для таблицы, хранящей данные плана обмена, один индекс: по полю Ссылка. Этот индекс удобны в общем случае, но может не подходить для конкретных операций поиска и чтения элементов плана обмена в вашем приложении. Тогда вы можете описать в проекте, какие дополнительные индексы «1С:Шина» должен создать в таблицах плана обмена
Представление плана обмена в командном интерфейсе
Во время работы приложения «1С:Шина» автоматически генерирует все команды и формы, которые требуются для работы с элементами (узлами) плана обмена. Однако они могут не подходить вам в каких-то сложных или особенных случаях. Тогда вы можете создать собственные формы и указать, в каких ситуациях их должна использовать «1С:Шина» для работы с элементами (узлами) этого плана обмена
Права
Элемент проекта вида План Обмена обладает следующими правами: Создание, Чтение, Изменение и Удаление (подробнее).
События ВычислитьРазрешенияДоступа и ВычислитьРазрешенияДоступаДляОбъектов следует обрабатывать в модуле плана обмена
Дополнительные пространства управляемых блокировок
Помимо стандартных пространств управляемых блокировок вы можете создать для плана обмена одно или несколько дополнительных пространств. Это позволит вам более гибко устанавливать управляемые блокировки
Запись данных в оптимизированном режиме
Во время массовой загрузки данных с помощью типа ГрупповаяОперация можно отключить обработчики, выполняемые во время записи узлов плана обмена, а также отключить расчет прав. Это позволяет ускорить запись данных
Все свойства плана обмена
Здесь описано назначение всех свойств плана обмена, которые вы можете менять в проекте