Имя: Пароль:
1C
1С v8
Номера сообщений при обмене с внешней системой через JSON
0 Антиквар
 
11.10.21
08:54
Всем привет!
Требуется реализовать обмен с внешней системой по формату JSON. Причем требуется получать подтверждение загрузки пакета от этой внешней системы, следовательно придется вести учет номеров отправленных пакетов.
Если бы формат был XML, то всё понятно:
1. СообщениеXML.НачатьЗапись() – сообщению присваивается номер (на 1 больше последнего отправленного), ставится блокировка на изменение данных узла.
2. ПланыОбмена.ВыбратьИзменения(Узел, Номер) – присвоенный сообщению номер пишется в таблицу регистрации изменений по выбранным объектам.
3. СообщениеXML.ЗакончитьЗапись() – в план обмена для выбранного узла записывается номер отправленного сообщения и снимается блокировка для узла.

С форматом JSON у нас нет методов НачатьЗапись() и ЗакончитьЗапись(), следовательно нумерацию сообщений нужно вести самим. Также нужно самим позаботиться о блокировке данных.
Что касается нумерации, то вижу это так:
Перед вызовом ВыбратьИзменения() мы обращаемся к плану обмена к записи с выбранным узлом, читаем номер отправленного, увеличиваем на единицу, и полученный новый номер передаем в ВыбратьИзменения().
Таким образом в таблицу регистрации изменений по всем выгружаемым объектам проставится нужный новый номер сообщения.
После чего мы сами должны сразу прописать в план обмена для данного узла новый номер отправленного пакета.
Когда получим подтверждение от внешней системы об удачной загрузке пакета, делаем:
ПланыОбмена.УдалитьРегистрациюИзменений(Узел, Номер)
Если пакет не принят, то повторяем всё заново, в итоге в новую выборку изменений кроме новых объектов попадут и все объекты из предыдущего пакета, только в таблице регистрации изменений им уже присвоится следующий новый номер сообщения.

Просьба подсказать, всё ли правильно я понял, или в случае JSON есть какой-то другой путь. Может более удобный? Проблема в учете подтверждения загрузки, и тут видимо без номеров пакетов не обойтись.

И вопрос у меня про блокировку, как лучше её организовать. Я не совсем понимаю, какая блокировка ставится при СообщениеXML.НачатьЗапись(). Блокируется только запись плана обмена, соответствующая нашему узлу, либо же блокируются и все данные (Справочники, Документы,…), изменения которых регистрируются для данного узла обмена?
1 ДенисЧ
 
11.10.21
08:56
Чем жисон в этом случае отличается от хамээля?
2 Галахад
 
гуру
11.10.21
09:06
(0) Выгружай в XML и конвертируй в JSON. :-)
3 DrShad
 
11.10.21
09:10
(1) +100500
4 Kassern
 
11.10.21
09:12
(0) ну так начинай запись xml, чтобы получить изменения, а дальше все в json запиши. Только зачем такие велосипеды хз. Сколько секунд выиграет принимающая/отдающая сторона, если формат будет json вместо xml?)
5 Антиквар
 
11.10.21
09:15
(1) Я выше написал чем отличается на мой взгляд. Тем, что стандартными методами обмена можно пользоваться только создавая сообщение формата XML. Поскольку только НачатьЗапись() и ЗакончитьЗапись() управляют блокировкой и автоматически увеличивают номер сообщения. Почему и спрашиваю, может для JSON в 1С тоже что-то есть, а если нет, то правильно ли я описал как нужно делать.
6 Антиквар
 
11.10.21
09:19
(4) Формат обсуждать нет смысла, система работает только с JSON. Причем файл не создается, JSON в строку.
За вариант применять стандартные НачатьЗапись() и ЗакончитьЗапись() , а между ними делать свой JSON, спасибо, но как-то бы не хотелось таким путем идти.
7 Cyberhawk
 
11.10.21
09:26
"Если пакет не принят, то повторяем всё заново, в итоге в новую выборку изменений кроме новых объектов попадут и все объекты из предыдущего пакета, только в таблице регистрации изменений им уже присвоится следующий новый номер сообщения"
Нет, ВыбратьИзменения присвоит номер только тем записям у которых номер = null
8 Kassern
 
11.10.21
09:28
(6) Создай тогда свою систему через регистр сведений, со своими номерами сообщений и регистрацией. Перед выгрузкой меняй номер сообщения (какая нить константа) и делай запрос к регистру. После выгрузки очищай это добро. Будет свой лисапед. Можно и еще круче, создай внешнюю очередь через какого нить RabbitMQ, внешней компонентой с ним любайся.
9 Антиквар
 
11.10.21
09:34
(7) А как тогда повторно отправить потерянный пакет? т.е. повторно выбрать эти изменения
10 Garykom
 
гуру
11.10.21
09:36
(0) Эээ вставлять уиды пакетов-сообщений или объектов

И да json вам не xml
Не принято все в один json пихать, тут лучше отдельные маленькие json'чики на каждую сущность ))
11 Kassern
 
11.10.21
09:36
(9) Можешь запросом по номеру сообщения получить.
12 Garykom
 
гуру
11.10.21
09:38
(0) Надеюсь понимаешь что номера пакетов все увеличивающиеся нужны только при накопительных-кумулятивных
Чтоб даже если что пропустили то без подтверждения в следующем снова придет
И вышестоящий номер подтверждает-закрывает все ниже
13 Kassern
 
11.10.21
09:39
(9) или делай в транзакции, вот как 1с советует когда данные большие:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайла);

ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
ЧтениеСообщения.НачатьЧтение(ЧтениеXML);

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

Счетчик = 0;
Пока ВозможностьЧтенияДанных(ЧтениеXML) Цикл
  
   Данные = ПрочитатьXML(ЧтениеXML);
   Данные.ОбменДанными.Отправитель = ЧтениеСообщения.Отправитель;
   Данные.ОбменДанными.Загрузка = Истина;
   Данные.Записать();
  
   Счетчик = Счетчик + 1;
   Если Счетчик % 1000 = 0 Тогда
      ЗафиксироватьТранзакцию();
      НачатьТранзакцию();
   КонецЕсли;

КонецЦикла;

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

ЧтениеСообщения.ЗакончитьЧтение();
ЧтениеXML.Закрыть();
14 Kassern
 
11.10.21
09:39
15 Антиквар
 
11.10.21
09:40
(8) свою систему запилить всегда можно, но как правило в итоге оказывается, что много всего нужно учитывать и в самом деле получается изобретение велосипеда. Хотелось бы к стандартным возможностям привязаться. Тем более с блокировками данных там реализовано. Хотя может это как раз таки будет тормозить и лучше своё писать)
"Можно и еще круче, создай внешнюю очередь через какого нить RabbitMQ" - так и предполагается, но отправление пакета брокеру не значит подтверждение его загрузки во внешней системе. Подтверждение также придет из брокера в 1С через какое-то время. Вот и надо будет это в 1С обработать
16 Garykom
 
гуру
11.10.21
09:44
(15) >RabbitMQ" - так и предполагается, но отправление пакета брокеру не значит подтверждение его загрузки во внешней системе. Подтверждение также придет из брокера в 1С через какое-то время. Вот и надо будет это в 1С обработать

эээ вы фигню хотите
отвечайте только за себя а внешняя система будет отвечать за себя
т.е. возвращать ответы только об ошибках загрузки и вы их обрабатывайте

раббит и прочее они гарантируют доставку в конечную
если конечная теряет пакеты то это упс
17 Антиквар
 
11.10.21
09:51
(16) "раббит и прочее они гарантируют доставку в конечную" - я с этим пока не работал, и для меня непривычно, что какая-то прослойка (пусть даже мегакрутая) может что-то гарантировать) Хотелось бы получать подтверждения.
18 Kassern
 
11.10.21
09:51
На практике проблема возникает в основном на загрузке данных. Выгрузка может закосячиться, если только меняли протокол обмена, либо вырубили сервер в момент выгрузки. В первом случае множество отладок перед продакшеном, а во втором - УПС. Да это не 100% гарантия, но даже, если и произойдет сбой и синий экран смерти на серваке, то можно же логировать обмены, если нет информации о завершении обмена, то можно заново отправить выгрузку с этим номером сообщения. Только после успешной выгрузки надо удалять изменения с этим номером.
19 Антиквар
 
11.10.21
09:53
(12) "Чтоб даже если что пропустили то без подтверждения в следующем снова придет" - я так и хочу реализовать. Но если следующая выборка изменений не включает в себя то что уже ушло, но не удалено из регистрации, то нужно что-то своё писать, как в посте (11). Стандартных методов нет как я понимаю.
20 Kassern
 
11.10.21
09:54
Сколько времени занимает полная выгрузка данных?
21 Антиквар
 
11.10.21
09:59
(18) "можно заново отправить выгрузку с этим номером сообщения"
Т.е. можно сделать запрос к таблице регистрации изменений, указав номер сообщения?
Просто не изучал этот вопрос. Знаю что у каждого объекта метаданных есть таблица изменений, т.е. можно сделать запрос, выборку из например Справочник.Контрагенты.Изменения
Но это все объекты перечислять и есть ли тут фильтр по номеру сообщения...
22 Антиквар
 
11.10.21
10:00
(20) пока не знаю. Предлагаешь раз в день полную выгрузку делать и не заморачиваться с подтверждением загрузки? )
23 Kassern
 
11.10.21
10:02
(22) на некоторых проектах так и было реализовано. Полная выгрузка не занимала там дофига времени. Если и происходил сбой то, выполнялась полная выгрузка.
(21) В запросе есть такой значок "отображать таблицы изменений", нажимая на него, появляются данные таблицы. Там можно по узлу и номеру сообщения получить нужные данные.
24 Garykom
 
гуру
11.10.21
10:04
(19) А оно точно надо?
Раббит и прочее подразумевает очередь! Т.е. в порядке очереди все работает
Если одно сообщение (при отправке или отгрузке) упало то обычно на этом все останавливается и ждем вмешательства ответственных
25 Garykom
 
гуру
11.10.21
10:05
(24)+ Последующие сообщения после упавшего не отсылаются и не загружаются
Ибо предполагают что нельзя последовательность нарушать сообщений
26 Антиквар
 
11.10.21
10:45
(25) Я с брокерами ранее не работал, мне спокойнее самому отработать подтверждение загрузки. Но тут я  возможно не прав в силу неопытности в данном вопросе
27 Garykom
 
гуру
11.10.21
11:06
(26) это просто иная методология

в случае обмена через RPC (http и веб-сервисы или com-соединение) ты же не будешь проверять что оно успешно записалось путем чтения и проверки что совпадает да?
суть та же

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

очереди можно настроить что одна конфа 1С отправляет, а получают пакеты две и более других конф 1С или иных учетных систем
не надо в каждую отдельно и свои отправлять, пакеты универсальные и клонируются в каждую систему и там или грузятся если нужны или игнорируются
28 Kassern
 
11.10.21
11:12
(27) здесь имелось в виду подтверждение, что брокер получил от тебя данные. А не то что конечный получатель их получил. В общем, можно в транзакции отправлять данные в брокер, если все успешно, то очищать данные по номеру, если нет, то произойдет откат транзакции и по идее следующая выгрузка заново отправит, то что не ушло.
29 Kassern
 
11.10.21
11:16
(27) простой пример, у тебя списали товар на складе, провели соответствующий документ. 1с по таймауту попыталась отправить данные о списании в брокер, но в момент выгрузки кто-то вырубил агент сервера 1с. Что тогда? В вашем случае, пофиг на этот пакет, отправим следующий. А ТС надо, чтобы при запуске службы следующая выгрузка отправила пакет с списанием, чтобы обновить остатки на сайте к примеру.
30 Garykom
 
гуру
11.10.21
11:20
(28) (29) да для этого Справочник или РС в 1С надо, где хранить до того как брокеру передали
31 Cyberhawk
 
11.10.21
17:34
(9) Ну в результат (выборку) ВыбратьИзменения все подряд попадет, включая и старые (с уже заполненным номером сообщения)
32 Антиквар
 
12.10.21
15:00
(31) Ааа, ну это другое дело. То что не поменяет номер сообщения - это не страшно, главное чтоб в выборку попало для повторной отправки.
Программист всегда исправляет последнюю ошибку.