Тип: Число. Размер тела сообщения. Пока сообщение не отправлено, возвращает размер записанных данных.
Полное описание, параметры и ограничения
СообщениеСервисаИнтеграции.РазмерТела (IntegrationServiceMessage.BodySize)
СообщениеСервисаИнтеграции (IntegrationServiceMessage)
РазмерТела (BodySize)
Доступен, начиная с версии 8.3.21.
Использование:
Только чтение.
Описание:
Тип: Число.
Размер тела сообщения.
Пока сообщение не отправлено, возвращает размер записанных данных.
Доступность:
Сервер, толстый клиент, внешнее соединение, мобильное приложение (сервер), мобильный автономный сервер.
Использование в версии:
Доступен, начиная с версии 8.3.21.
Методическая информация
Практические примеры
Собственный черновик интеграции: счет 1050, конверт и 125 байт без отправки
Полный producer разбирает три свои строки, реальная фабрика создает native message, writable-only body принимает собственные UTF-8 bytes. До и после записи проверяется весь конечный конверт; равный размер не выдается за чтение тела обратно или доставку.
Где и как запускать
Полный ОбщийМодуль.ЧерновикКонверта85: nonglobalServer/ServerCall, обаClientНет/externalНет/privilegedНет/reuseNo. Полные managedFORM и APP ниже; opaque message/stream/binary черезRPC не возвращаются.
Подготовка
Создайте вручную НОВУЮ пустую файловую ИБ только по пути C:\1c-labs\OwnIntegrationDraft85_597a5b91-7d4d-462a-8e52-57af3a60e9f2\IB. Не копию рабочей базы. Платформа 8.5.1.1343, русский встроенный язык. Создание ИБ, запуск и все native действия агентом не выполнялись.
Конфигуратор → корень конфигурации: Имя = УчебныйЧерновикИнтеграции85, РежимСовместимости = НеИспользовать, ОсновнойРежимЗапуска = УправляемоеПриложение, интерфейс Такси. Прикладные справочники, документы, регистры, планы, константы, отчеты и обработки не создавайте. Никаких общих реквизитов/разделителей, расширений, HTTP/Web сервисов, подписок и своих заданий.
Общие → Сервисы интеграции: единственный УчебныйКонверт85. АдресВнешнегоСервисаИнтеграции пустой, каналов НЕТ, модуль сервиса пустой; обработчиков получения сообщений не назначайте. В Предприятии никаких записей активности/настроек не делайте. Для нового неразделяемого сервиса при отсутствующей активности native ПолучитьАктивность возвращает Ложь. Код проверяет реальный результат, но ничего не деактивирует.
Роли → единственная Черновик85: Администрирование для ПолучитьПользователей; АктивныеПользователи для ПолучитьСоединенияИнформационнойБазы; АдминистрированиеДанных для ПолучитьАктивность сервиса без разделителей, необходимые клиентские права и просмотр/использование своей общей формы. Эти права перед СоздатьСообщение проверяются соответствующими настоящими native вызовами, без использования ПравоДоступа для корня конфигурации. Выбранная страница справки не подтверждает такой тип второго параметра; это ограничение доказательства данного урока, а не утверждение о недопустимости корректного двухпараметрического вызова. Совпадение имени/принадлежности роли не доказывает ее права. Администрирование → Пользователи: только Черновик85Ученик с единственной Черновик85. Пароль выбирает человек, в пример не помещает. Это только права отдельного учебного стенда, не production-рекомендация.
ОбщиеМодули → ЧерновикКонверта85: Глобальный Нет, Сервер Да, ВызовСервера Да, оба Клиент Нет, ВнешнееСоединение Нет, Привилегированный Нет, ПовторноеИспользованиеВозвращаемыхЗначений = НеИспользовать. В модуль вставьте CODE целиком. Нужны все функции и проверки ниже, не вырезайте только семь native строк. MAIN принадлежит этому настоящему серверному общему модулю.
ОбщиеФормы → управляемая ПультКонверта85. Реквизит ТекстОтчета85: Строка неограниченной длины; многострочное поле с ПутьКДанным = ТекстОтчета85 и ТолькоПросмотр = Да. Команда ПроверитьЧерновик85, действие ПроверитьЧерновик85, кнопка этой команды. Вставьте FORM целиком; назначьте настоящие события ПриСозданииНаСервере с двумя параметрами и ПриОткрытии с одним. События и command action вручную не вызывайте.
Корень конфигурации → Модуль управляемого приложения: APP целиком, настоящий ПриНачалеРаботыСистемы без параметров. Проверьте F7, обновите только свою CF. Закройте Конфигуратор/другие соединения и запустите свою ИБ управляемым клиентом под Черновик85Ученик. Код требует один реальный сеанс, не игнорирует лишние подключения. Никаких внешних URL/DSN/каналов/очередей/ключей/сертификатов не нужно.
На пульте нажмите настоящую кнопку ПроверитьЧерновик85. Строго заданный собственный JSON имеет только items и три строки: A, количество 2, цена 100; B, количество 3, цена 250; C, количество 1, цена 100. Проверяются все имена/типы/значения каждой строки. Сумма вычисляется из настоящего разобранного массива: 200 + 750 + 100 = 1050, не присваивается готовым числом.
Тот же собственный producer текст преобразуется в UTF-8 с явным ЗаписатьBOM = Ложь. Native ДвоичныеДанные.Размер должен показать 125; обратное преобразование producer bytes в свою строку проверяется ДО native message stream. 125 получено предварительно только кодировкой собственной ASCII-строки в Python-памяти; это ожидаемое значение будущего native опыта, а не уже измеренный runtime 1С.
СоздатьСообщение вызывается только у своего compiled сервиса и с явной датой ТекущаяДатаСеанса() + 86400. ДатаУстаревания читается и сравнивается с этой же датой сеанса; UTC вручную не конструируется. В течение ручного опыта не меняйте часы/часовой пояс сеанса. Статический native контракт не требует канала или активации для фабрики; это документированная композиция, не доказанный успешный запуск в1С. При native отказе СТОП, не добавляйте канал/адрес/активацию автоматически.
Параметры — собственное Соответствие только со строковыми ключами и строковыми значениями. own-draft-uuid — UUID нашего локального опыта, НЕ native ID сообщения; own-purpose = invoice-preview-only, own-total = строка 1050. КодОтправителя = OwnInvoiceSource85 и КодПолучателя = OwnPreviewConsumer85 дают native aliases Participant-Sender-Code и Participant-Receiver-Codes. Итоговая карта содержит ровно эти пять пар; проверяется каждая, неизвестные или лишние пары не допускаются. Эти коды только локальные метки своего consumer, не зарегистрированные участники интеграции.
Тело нового сообщения по native контракту дает поток ДоступнаЗапись = Истина, ДоступноЧтение = Ложь, ДоступноИзменениеПозиции = Ложь. Своё binary значение открывает отдельный настоящий поток чтения с исходной позицией0; КопироватьВ вызывается без присваивания результата. После единственной попытки Close каждого потока читаются только поля СООБЩЕНИЯ, а не методы закрытого потока. Ошибки копирования/закрытия сохраняют первичную диагностику и отдельные ошибки cleanup; неизвестный частичный исход остается СТОП, rollback/retry нет.
Успех показывает только три строки, сумму исходного producer1050, native РазмерТела125 и совпадение полного собственного конверта до/после записи. Readback байтов native тела отсутствует: write-only поток не читается и не seek-ится. Равный размер не доказывает содержание, hash, JSON целевого тела или доставку. Нет обещания полной неизменности скрытых внутренних полей платформы или атомарности; внутренний temporary/storage I/O платформы здесь не исследовался.
Идентификатор, ИдентификаторСообщенияЗапроса и ДатаОтправки в данном уроке не используются: они относятся к настоящей отправке/запросу-ответу, их не выдумываем для черновика. ОтправитьСообщение, ВыбратьСообщения, УдалитьСообщения, ВыполнитьОбработку, УстановитьАктивность/Настройки и очередь отсутствуют. Закройте свой пульт после опыта. При отказе сначала выясните причину, не запускайте опыт автоматически снова. Программа не удаляет файлы/данные и не сохраняет конверт явно.
Функция ПостроитьЧерновик85() Экспорт
ПроверитьКонтекст85();
Исходник = ИсточникСчета85();
Момент = ТекущаяДатаСеанса();
Срок = Момент + 86400;
ПакетUUID = НРег(Строка(Новый УникальныйИдентификатор));
Черновик = СервисыИнтеграции.УчебныйКонверт85.СоздатьСообщение(Срок);
Если ТипЗнч(Черновик) <> Тип("СообщениеСервисаИнтеграции") Тогда
ВызватьИсключение "Нужен настоящий собственный черновик штатной фабрики";
КонецЕсли;
ИсточникПоток = Неопределено;
ТелоПоток = Неопределено;
ЗакрытиеИсточникаНачато = Ложь;
ЗакрытиеТелаНачато = Ложь;
Попытка
ТелоПоток = Черновик.ПолучитьТелоКакПоток();
Если ТипЗнч(ТелоПоток) <> Тип("Поток") Или Не ТелоПоток.ДоступнаЗапись
Или ТелоПоток.ДоступноЧтение Или ТелоПоток.ДоступноИзменениеПозиции Тогда
ВызватьИсключение "Нужен native creation-поток: только запись, без чтения и seek";
КонецЕсли;
Если ТипЗнч(Черновик.РазмерТела) <> Тип("Число") Или Черновик.РазмерТела <> 0 Тогда
ВызватьИсключение "До записи собственный новый черновик не должен содержать тело";
КонецЕсли;
Поля = Новый Соответствие;
Поля.Вставить("own-draft-uuid", ПакетUUID);
Поля.Вставить("own-purpose", "invoice-preview-only");
Поля.Вставить("own-total", "1050");
Черновик.Параметры = Поля;
Черновик.КодОтправителя = "OwnInvoiceSource85";
Черновик.КодПолучателя = "OwnPreviewConsumer85";
СверитьКонверт85(Черновик, ПакетUUID, Срок, Исходник.Сумма);
ИсточникПоток = Исходник.Данные.ОткрытьПотокДляЧтения();
Если ТипЗнч(ИсточникПоток) <> Тип("Поток") Или Не ИсточникПоток.ДоступноЧтение Тогда
ВызватьИсключение "Штатный собственный binary source должен дать настоящий поток чтения";
КонецЕсли;
ИсточникПоток.КопироватьВ(ТелоПоток);
ЗакрытиеИсточникаНачато = Истина;
ИсточникПоток.Закрыть();
ЗакрытиеТелаНачато = Истина;
ТелоПоток.Закрыть();
Исключение
ПервичнаяОшибка = ОписаниеОшибки();
ОшибкиЗакрытия = "";
Если ИсточникПоток <> Неопределено И Не ЗакрытиеИсточникаНачато Тогда
Попытка
ИсточникПоток.Закрыть();
Исключение
ОшибкиЗакрытия = ОшибкиЗакрытия + "; source Close: " + ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
Если ТелоПоток <> Неопределено И Не ЗакрытиеТелаНачато Тогда
Попытка
ТелоПоток.Закрыть();
Исключение
ОшибкиЗакрытия = ОшибкиЗакрытия + "; body Close: " + ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
ВызватьИсключение "СТОП: первичная ошибка: " + ПервичнаяОшибка + ОшибкиЗакрытия
+ "; состояние потоков/частично записанного собственного черновика неизвестно. Retry/откат не выполняются";
КонецПопытки;
СверитьКонверт85(Черновик, ПакетUUID, Срок, Исходник.Сумма);
РазмерТела = Черновик.РазмерТела;
Если ТипЗнч(РазмерТела) <> Тип("Число") Или РазмерТела <> Исходник.Байт Или РазмерТела <> 125 Тогда
ВызватьИсключение "Native размер записанного тела не совпал со своим 125-байтным источником";
КонецЕсли;
Если Срок <= ТекущаяДатаСеанса() Или Срок - Момент <> 86400 Тогда
ВызватьИсключение "Собственный срок истек или изменилась подготовка TTL";
КонецЕсли;
ПроверитьКонтекст85();
Текст = "Проверен только собственный неотправленный черновик: строк=" + Строка(Исходник.Строк)
+ "; сумма producer=" + Строка(Исходник.Сумма) + "; native body bytes=" + Строка(РазмерТела)
+ Символы.ПС + "Параметры/aliases/срок совпали до и после записи собственного тела."
+ Символы.ПС + "Тело native write-only: назад не читали; размер не доказывает содержимое или доставку."
+ Символы.ПС + "OwnInvoiceSource85/OwnPreviewConsumer85 — только локальные метки нашего consumer, не зарегистрированные участники."
+ Символы.ПС + "Отправки, очереди, настоящего ID/ответа, активации и внешнего сервиса нет.";
Возврат Новый Структура("Строк,Сумма,Байт,Текст", Исходник.Строк, Исходник.Сумма, РазмерТела, Текст);
КонецФункции
Функция ИсточникСчета85()
JSON = "{""items"":[{""code"":""A"",""quantity"":2,""price"":100},{""code"":""B"",""quantity"":3,""price"":250},{""code"":""C"",""quantity"":1,""price"":100}]}";
Читатель = Новый ЧтениеJSON;
ЗакрытиеЧитателяНачато = Ложь;
Попытка
Читатель.УстановитьСтроку(JSON);
Пакет = ПрочитатьJSON(Читатель);
ЗакрытиеЧитателяНачато = Истина;
Читатель.Закрыть();
Исключение
ПервичнаяОшибка = ОписаниеОшибки();
ОшибкаЗакрытия = "";
Если Не ЗакрытиеЧитателяНачато Тогда
Попытка
Читатель.Закрыть();
Исключение
ОшибкаЗакрытия = "; reader Close: " + ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
ВызватьИсключение "СТОП: собственный JSON: " + ПервичнаяОшибка + ОшибкаЗакрытия + "; состояние reader неизвестно";
КонецПопытки;
Если ТипЗнч(Пакет) <> Тип("Структура") Или Пакет.Количество() <> 1
Или Не Пакет.Свойство("items", Строки) Или ТипЗнч(Строки) <> Тип("Массив") Или Строки.Количество() <> 3 Тогда
ВызватьИсключение "Нужен полный собственный пакет items из трех строк";
КонецЕсли;
Коды = СтрРазделить("A,B,C", ",");
Количества = Новый Массив;
Количества.Добавить(2);
Количества.Добавить(3);
Количества.Добавить(1);
Цены = Новый Массив;
Цены.Добавить(100);
Цены.Добавить(250);
Цены.Добавить(100);
Сумма = 0;
Для Индекс = 0 По 2 Цикл
СтрокаСчета = Строки[Индекс];
Если ТипЗнч(СтрокаСчета) <> Тип("Структура") Или СтрокаСчета.Количество() <> 3
Или Не СтрокаСчета.Свойство("code", Код) Или ТипЗнч(Код) <> Тип("Строка") Или Код <> Коды[Индекс]
Или Не СтрокаСчета.Свойство("quantity", Количество) Или ТипЗнч(Количество) <> Тип("Число") Или Количество <> Количества[Индекс]
Или Не СтрокаСчета.Свойство("price", Цена) Или ТипЗнч(Цена) <> Тип("Число") Или Цена <> Цены[Индекс] Тогда
ВызватьИсключение "Не совпали все ключи/типы/значения своей конкретной строки счета";
КонецЕсли;
Сумма = Сумма + Количество * Цена;
КонецЦикла;
Если Сумма <> 1050 Тогда
ВызватьИсключение "Фактическая сумма producer не равна 200+750+100";
КонецЕсли;
Данные = ПолучитьДвоичныеДанныеИзСтроки(JSON, "UTF-8", Ложь);
Если ТипЗнч(Данные) <> Тип("ДвоичныеДанные") Или Данные.Размер() <> 125
Или ПолучитьСтрокуИзДвоичныхДанных(Данные, "UTF-8") <> JSON Тогда
ВызватьИсключение "Не совпал собственный UTF-8 producer roundtrip без BOM";
КонецЕсли;
Возврат Новый Структура("Данные,Строк,Сумма,Байт", Данные, Строки.Количество(), Сумма, Данные.Размер());
КонецФункции
Процедура СверитьКонверт85(Черновик, ПакетUUID, Срок, Сумма)
Если ТипЗнч(Черновик) <> Тип("СообщениеСервисаИнтеграции") Или ТипЗнч(ПакетUUID) <> Тип("Строка")
Или СтрДлина(ПакетUUID) <> 36 Или ТипЗнч(Срок) <> Тип("Дата") Или ТипЗнч(Сумма) <> Тип("Число") Тогда
ВызватьИсключение "Проверяется только свой типизированный конверт";
КонецЕсли;
Если ТипЗнч(Черновик.ДатаУстаревания) <> Тип("Дата") Или Черновик.ДатаУстаревания <> Срок
Или Черновик.КодОтправителя <> "OwnInvoiceSource85" Или Черновик.КодПолучателя <> "OwnPreviewConsumer85" Тогда
ВызватьИсключение "Срок в часовом поясе сеанса/локальные route labels не совпали";
КонецЕсли;
Ожидаемые = Новый Соответствие;
Ожидаемые.Вставить("own-draft-uuid", ПакетUUID);
Ожидаемые.Вставить("own-purpose", "invoice-preview-only");
Ожидаемые.Вставить("own-total", "1050");
Ожидаемые.Вставить("Participant-Sender-Code", "OwnInvoiceSource85");
Ожидаемые.Вставить("Participant-Receiver-Codes", "OwnPreviewConsumer85");
Фактические = Черновик.Параметры;
Если ТипЗнч(Фактические) <> Тип("Соответствие") Или Фактические.Количество() <> 5 Тогда
ВызватьИсключение "Нужна полная собственная пятистрочная карта, не часть неизвестных параметров";
КонецЕсли;
Для Каждого Поле Из Фактические Цикл
Если ТипЗнч(Поле.Ключ) <> Тип("Строка") Или ТипЗнч(Поле.Значение) <> Тип("Строка")
Или Ожидаемые.Получить(Поле.Ключ) = Неопределено Или Поле.Значение <> Ожидаемые.Получить(Поле.Ключ) Тогда
ВызватьИсключение "Не совпал ключ/тип/значение полного собственного native map";
КонецЕсли;
КонецЦикла;
Если Фактические.Получить("Participant-Sender-Code") <> Черновик.КодОтправителя
Или Фактические.Получить("Participant-Receiver-Codes") <> Черновик.КодПолучателя
Или Число(Фактические.Получить("own-total")) <> Сумма Тогда
ВызватьИсключение "Native aliases/заявленная строковая сумма расходятся с нашим producer";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьКонтекст85() Экспорт
Если СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnIntegrationDraft85_597a5b91-7d4d-462a-8e52-57af3a60e9f2\IB"";" Тогда
ВызватьИсключение "Только новая собственная файловая ИБ по точному учебному пути";
КонецЕсли;
Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или ПривилегированныйРежим() Или ТранзакцияАктивна() Тогда
ВызватьИсключение "Не совпали версия/своя конфигурация/NoUse/непривилегированный контекст";
КонецЕсли;
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0
Или Метаданные.Константы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0
Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0
Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0
Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0
Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0
Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0
Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0
Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Или Метаданные.HTTPСервисы.Количество() <> 0
Или Метаданные.WebСервисы.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0
Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.Отчеты.Количество() <> 0
Или Метаданные.Обработки.Количество() <> 0 Тогда
ВызватьИсключение "Только собственная пустая прикладная модель без интеграционных обработчиков и заданий";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации()
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.БазаДанных).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансОтключенные).Количество() <> 0 Тогда
ВызватьИсключение "Расширения своей ИБ/сеанса запрещены";
КонецЕсли;
Если Метаданные.ОбщиеМодули.Количество() <> 1 Или Метаданные.ОбщиеФормы.Количество() <> 1
Или Метаданные.ОбщиеФормы.Найти("ПультКонверта85") = Неопределено Или Метаданные.Роли.Количество() <> 1
Или Метаданные.СервисыИнтеграции.Количество() <> 1 Тогда
ВызватьИсключение "Нужны только свои единственные модуль/пульт/роль/сервис";
КонецЕсли;
Модуль = Метаданные.ОбщиеМодули.Найти("ЧерновикКонверта85");
СервисМД = Метаданные.СервисыИнтеграции.Найти("УчебныйКонверт85");
Если Модуль = Неопределено Или СервисМД = Неопределено Тогда
ВызватьИсключение "Нет собственного модуля или compiled сервиса";
КонецЕсли;
Если Модуль.Глобальный Или Не Модуль.Сервер Или Не Модуль.ВызовСервера
Или Модуль.КлиентОбычноеПриложение Или Модуль.КлиентУправляемоеПриложение
Или Модуль.ВнешнееСоединение Или Модуль.Привилегированный Тогда
ВызватьИсключение "Модуль должен быть только неглобальным непривилегированным серверным";
КонецЕсли;
Если Модуль.ПовторноеИспользованиеВозвращаемыхЗначений <> Метаданные.СвойстваОбъектов.ПовторноеИспользованиеВозвращаемыхЗначений.НеИспользовать
Или СервисМД.Каналы.Количество() <> 0 Или СервисМД.АдресВнешнегоСервисаИнтеграции <> "" Тогда
ВызватьИсключение "Без module cache, каналов и адреса внешнего сервиса";
КонецЕсли;
Пользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
Если Пользователь = Неопределено Или ТипЗнч(Пользователь) <> Тип("ПользовательИнформационнойБазы") Тогда
ВызватьИсключение "Нет настоящего текущего пользователя";
КонецЕсли;
Если Пользователь.Имя <> "Черновик85Ученик" Тогда
ВызватьИсключение "Другой пользователь не допускается";
КонецЕсли;
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Если ТипЗнч(Пользователи) <> Тип("Массив") Или Пользователи.Количество() <> 1 Тогда
ВызватьИсключение "Должен быть только свой учебный пользователь";
КонецЕсли;
Свой = Пользователи[0];
Если ТипЗнч(Свой) <> Тип("ПользовательИнформационнойБазы") Или Свой.Имя <> Пользователь.Имя
Или Свой.УникальныйИдентификатор <> Пользователь.УникальныйИдентификатор Тогда
ВызватьИсключение "Свежий список не совпал с пользователем собственного сеанса";
КонецЕсли;
СвояРоль = Метаданные.Роли.Найти("Черновик85");
Если СвояРоль = Неопределено Или Не Свой.Роли.Содержит(СвояРоль) Тогда
ВызватьИсключение "Нет собственной роли";
КонецЕсли;
ЧислоРолей = 0;
Для Каждого Роль Из Свой.Роли Цикл
Если Роль <> СвояРоль Тогда
ВызватьИсключение "Чужая роль запрещена";
КонецЕсли;
ЧислоРолей = ЧислоРолей + 1;
КонецЦикла;
Если ЧислоРолей <> 1 Или ПолучитьСоединенияИнформационнойБазы().Количество() <> 1 Тогда
ВызватьИсключение "Нужны единственная собственная роль и одно соединение";
КонецЕсли;
Активность = СервисыИнтеграции.УчебныйКонверт85.ПолучитьАктивность();
Если ТипЗнч(Активность) <> Тип("Булево") Или Активность <> Ложь Тогда
ВызватьИсключение "Сервис неактивен по native getter либо СТОП, активацию/настройки не менять";
КонецЕсли;
КонецПроцедурыПолный управляемый пульт: genuine callbacks/command и scalar-only RPC
ОбщиеФормы → ПультКонверта85 → Модуль целиком
ПриСозданииНаСервере2/ПриОткрытии1/действиеКоманды1. Client stickySTOP, native message/stream/metadata только на сервере.
&НаКлиенте
Перем Остановлен85;
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ЧерновикКонверта85.ПроверитьКонтекст85();
ТекстОтчета85 = "Собственный preview черновика. Сообщения никуда не отправляются.";
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если Остановлен85 <> Неопределено Тогда
ВызватьИсключение "Повторная инициализация не сбрасывает СТОП";
КонецЕсли;
Остановлен85 = Истина;
Попытка
ПроверитьСеанс85();
Остановлен85 = Ложь;
Исключение
Остановлен85 = Истина;
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьЧерновик85(Команда)
Если Остановлен85 <> Ложь Тогда
ВызватьИсключение "СТОП: закройте собственный пульт и выясните причину, автоматического retry нет";
КонецЕсли;
Остановлен85 = Истина;
Попытка
Итог = ПостроитьНаСервере85();
Если ТипЗнч(Итог) <> Тип("Структура") Или Итог.Количество() <> 4
Или Не Итог.Свойство("Строк", Строк) Или ТипЗнч(Строк) <> Тип("Число") Или Строк <> 3
Или Не Итог.Свойство("Сумма", Сумма) Или ТипЗнч(Сумма) <> Тип("Число") Или Сумма <> 1050
Или Не Итог.Свойство("Байт", Байт) Или ТипЗнч(Байт) <> Тип("Число") Или Байт <> 125
Или Не Итог.Свойство("Текст", Текст) Или ТипЗнч(Текст) <> Тип("Строка") Тогда
ВызватьИсключение "Нужен полный безопасный scalar-only результат своего серверного producer";
КонецЕсли;
ТекстОтчета85 = Текст;
Остановлен85 = Ложь;
Исключение
Остановлен85 = Истина;
ТекстОтчета85 = "СТОП. Результат не подтвержден; повторная запись/откат/отправка не выполняются.";
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПостроитьНаСервере85()
Возврат ЧерновикКонверта85.ПостроитьЧерновик85();
КонецФункции
&НаСервереБезКонтекста
Процедура ПроверитьСеанс85()
ЧерновикКонверта85.ПроверитьКонтекст85();
КонецПроцедурыПолное настоящее открытие собственного управляемого пульта
Корень конфигурации → Модуль управляемого приложения
Настоящий ПриНачалеРаботыСистемы0, реальная ОбщаяФорма.ПультКонверта85; события вручную не доставляются.
Процедура ПриНачалеРаботыСистемы()
СвояФорма = ПолучитьФорму("ОбщаяФорма.ПультКонверта85");
Если СвояФорма = Неопределено Или ТипЗнч(СвояФорма) <> Тип("ФормаКлиентскогоПриложения") Тогда
ВызватьИсключение "Не найдена настоящая собственная управляемая форма";
КонецЕсли;
СвояФорма.Открыть();
КонецПроцедурыРазбор по шагам
Сначала exact новый File-путь/CF/версия/NoUse/пользователь/UUID/роль/схема/одно соединение; единственный compiled сервис без каналов/адреса, реальный GetActiveFalse.
Собственный JSON разбирается полностью: items1, строки3, каждый code/quantity/price с точными типами и значениями. Числовая сумма200+750+100 считается из массива.
Producer UTF-8 без BOM проверяется собственным обратным преобразованием и реальным BinaryData.Size125. Это roundtrip источника, не native message body.
Native СервисыИнтеграции.УчебныйКонверт85.СоздатьСообщение получает явный expiryDate; результат проверяется как настоящий СообщениеСервисаИнтеграции.
Реальный write-only body creation-state проверяется до записи параметров. Конечные5 String/String пар, два native property↔parameter aliases и собственный срок сверяются до/после.
Own Binary.OpenReadStream начинается с0; Source.CopyTo(Body) вызывается без недокументированного returntype. Каждому потоку одна попытка Close, ошибки cleanup не маскируют первичную.
ПослеClose читается Message.BodySize125, не закрытые потоки. Повторные expiry/конверт/context проверки завершают только local preview; клиент получает безопасные4scalars.
Как проверить результат
В новой своей CF будущая кнопка дает3/1050/125; все native объекты остаются на сервере.
Нет New СообщениеСервисаИнтеграции или New Поток: каждый объект имеет реальную фабрику и scoped owner.
Wrong user/path/role/лишняя схема/активный сервис/канал/адрес отказывают без изменения активности или настроек.
Missing/extra JSON keys, измененная цена/количество, нестроковый/лишний parameter, чужая route label, неверные native body capabilities или размер оставляютSTOP.
Ни Read/seek/GetPosition послеClose, ни чтение write-only body, ни ID/ответ/доставка не имитируются.
При первичной ошибке захватывается ее ОписаниеОшибки; cleanup каждого еще не закрывавшегося собственного потока предпринимается не больше одного раза, его ошибки сообщаются отдельно.
Ожидаемый результат
При будущем ручном выполнении собственной подготовки local producer дает3строки/1050, native черновик имеет точный собственный конверт и РазмерТела125. Байты тела назад не читались, отправка/доставка/настоящий запрос-ответ отсутствуют. Здесь 1С, CF и потоки не запускались.
На что обратить внимание
Native Params принимает String keys И String values. Число1050 в собственных строках и строка1050 в конверте — разные типы.
Participant-Receiver-Codes — точный native alias, не выдуманный Recipient-Code; пустой получатель потенциально означает всех, поэтому localconsumer требует свою явную непустую метку, хотя Sending отсутствует.
ExpirationDate native помечен readonly, несмотря на описательный текст о возможности установки: здесь только factoryDate+getter, никаких присваиваний.
Stream.CopyTo raw сообщает фактическое количество байтов, но не объявляет returnTYPE. Код не присваивает return, не выдумывает bool/Number result.
Stream.Close явно идемпотентен, но ни JSON reader Close, ни native failures не являются разрешением слепого повторного cleanup. Reader и каждый stream имеют свои markers.
GetActiveFalse не доказывает историческую неактивность или мгновенную синхронизацию других процессов. Нужен именно новый собственный стенд без конкурентных изменений.
Не гарантированы byteintegrity native body, отсутствие внутренних temporary/storage I/O, атомарность, rollback или успешная отправка. Actual runtime/CF/DB/UI/network0, backups0.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.