Столкнулись с проблемой решить самостоятельно которую нам не удается,
возможно опыт и экспертность сообщества позволит понять и как следствие найти решение для сложившейся ситуации.
Изначально:
Есть самописная конфигурация работающая в режиме "Обычное приложение", экземпляры которой развернуты на нескольких сотнях
рабочих станций (все windows 10, платформа 1С 8.3.18), часть в файловом режиме, часть клиент-серверном (СУБД MSSQL 2012)
Ситуация:
В качестве пилота перевели несколько экземпляров ИБ на клиент-серверное взаимодействие с использованием СУБД PostgeSQL:
Windows 10 с виртуальной машиной Ubuntu, на которой в свою очередь установлены Сервер приложений 1С 8.3.18, СУБД PostgeSQL.
Соответственно база живет в СУБД, и подключена к 1С Серверу.
На этих реализациях появилось странное поведение при исполнении внешних обработок, периодически переменные методов модуля объекта обработки или реквизиты обработки будто теряют значение, становятся не инициализированными, как следствие нарушение логики и падения программы.
Падения в модуле могут происходить при обращении к свойствам объектов где к этим же самым свойствам обращались несколькими строками ранее (в рамках одного метода)
Пример в виде изображения прикреплен к посту
Внешние обработки создаются и исполняются программно, закономерностей в падениях пока не зафиксировано, кроме уже описанных ранее (Все Виртуальная машина Ubuntu, Сервером 1С, PostgeSQL)
Картина следующая:
Одинаковые конфигурации, внешние обработки, платформа 1с:
ОС Win + 1C(клиент-сервер) + MSSQL = Ошибка не происходит.
ОС Win + 1С(файловая база) = Ошибка не происходит.
ОС Win + Окружение Linux(Ubuntu + 1C(клиент-сервер) + PostgeSQL) = Ошибка происходит на всех инстансах, с различной периодичностью.
Куда можно посмотреть, на что обратить внимание, во что залезть куда копнуть, быстрая и не очень гуглежка результата, к сожалению не дала, за сем обращаюсь к Вам
(1) Похоже, что это глюк внешней компоненты под Linux.
Хотя, из описания "ОС Win + Окружение Linux(Ubuntu + 1C(клиент-сервер) + PostgeSQL)" вообще непонятно что где выполняется
(5) Там ComОбъект, который инициируется и работа с которым происходит на клиенте который работает под Win, он никуда не перебрасывается, никаких вызовов сервера куда бы он мог передаваться тоже нет.
Ну вот в нем всё и дело. Возможно он приходит в состояние, когда поле стновится доступным только для записи. Или вообще весь теряется, например из-за кривого кэширования в модуле повторного использования.
Вот еще пример.
Тоже внешняя обработка, только теперь "потерялись" данные находящиеся в типе Структура.
Извиняюсь за это полотно, но как показать нагляднее не придумал.
Листинг метода
Функция ВыполнитьРасчетСкидки(ДП, ДД, ЗначенияПараметров, ТекСкидки, ПараметрыЧека) Экспорт
Результат = Новый Структура;
Результат.Вставить("Результат", Ложь);
Результат.Вставить("Комментарий", "");
Результат.Вставить("Скидка", 0);
Результат.Вставить("ПараметрыЧека", Новый Структура("ДанныеСистемыЛояльности,УстройствоПечати,ДанныеКупона,ИспользоватьКартуКупона", Неопределено, Неопределено, Неопределено, Неопределено));
Результат.Вставить("Слип", "");
Результат.Вставить("ДанныеТоваровCRM", Неопределено);
Если НЕ ПроверкаОнлайна(ВернутьНастройкуПоИдентификатору("ПроверкаОнлайна_Продолжительность")) Тогда
Результат.Результат = Ложь;
Результат.Комментарий = "Проверка связи с CRM: связь не установлена, система не доступна. Выполнение оперции не возможно";
Предупреждение(ВернутьФорматныйКомментарий(Результат.Комментарий, "Расчет скидки"), , "Система лояльности " + ВернутьНастройкуПоИдентификатору("ДП_НаименованиеСистемыЛояльности") + ".");
Возврат Результат;
КонецЕсли;
Если ЭтоПервыйВызовРасчетаСкидки(ПараметрыЧека) Тогда
УстановитьНачальныеЗначенияДанных();
НомерКарты = ДД.Наименование;
Если (НЕ ЗначениеЗаполнено(НомерКарты)) ИЛИ (СтрСравнить(ПараметрыЧека.ДанныеСистемыЛояльности.ТипКарты, "ЕКП") = 0) Тогда
Попытка
НомерКарты = ПараметрыЧека.ДанныеСистемыЛояльности.НомерКартыВместе;
Исключение
ВыполнитьЗаписьЖурналаРегистрацииПриОшибки(ИнформацияОбОшибке());
Результат.Результат = Ложь;
Результат.Комментарий = "Расчет скидки CRM: Ошибка при получение номера карты";
Возврат Результат;
КонецПопытки;
КонецЕсли;
Если ПараметрыЧека.ДанныеСистемыЛояльности.ИспользуетсяКартаКупона Тогда
НомерКартыВместе = НомерКарты;
Иначе
Результат_ВТИФНК = Новый Структура;
ВернутьТипИФорматныйНомерКарты(Результат_ВТИФНК, Новый Структура("НомерКарты", НомерКарты));
НомерКартыВместе = Результат_ВТИФНК.ФорматныйНомерКарты;
Если Результат_ВТИФНК.ТипКарты = Неопределено Тогда
Результат.Результат = Ложь;
Результат.Комментарий = "Расчет скидки CRM: Тип карты " + НомерКартыВместе + " не определен";
Возврат Результат;
КонецЕсли;
КонецЕсли;
ДанныеСистемыЛояльности = Новый Структура;
ДанныеСистемыЛояльности.Вставить("КоличествоВызововРасчетаСкидки", 0);
ДанныеСистемыЛояльности.Вставить("БонусовСписано", 0);
ДанныеСистемыЛояльности.Вставить("БонусовНачислено", Неопределено);
ДанныеСистемыЛояльности.Вставить("TransactionID", Неопределено);
ДанныеСистемыЛояльности.Вставить("НомерКартыВместе", НомерКартыВместе);
ДанныеСистемыЛояльности.Вставить("ДанныеКупона", ПараметрыЧека.ДанныеСистемыЛояльности.ДанныеКупона);
ДанныеСистемыЛояльности.Вставить("ИспользуетсяКартаКупона", ПараметрыЧека.ДанныеСистемыЛояльности.ИспользуетсяКартаКупона);
ДанныеСистемыЛояльности.Вставить("ТипКарты", ПараметрыЧека.ДанныеСистемыЛояльности.ТипКарты);
ДанныеСистемыЛояльности.Вставить("ЭлПочта", СокрЛП(глОбъектСистемыЛояльностиВместе.ClientPrivOffice.ContactData.Email));
ДанныеСистемыЛояльности.Вставить("Сотрудник", Ложь);
ДанныеСистемыЛояльности.Вставить("РазрешениеНаЭлектронныйЧек", Ложь);
Если ЗначенияПараметров.Свойство("УстройствоПечати") Тогда
УстройствоПечати = ЗначенияПараметров.УстройствоПечати;
ОписаниеОповещения = Новый ОписаниеОповещения("ОО_ПолучениеТекущегоСостоянияФискальногоУстройства", ЭтотОбъект, "ТекСостояниеФР");
МенеджерОборудованияКлиент.НачатьПолучениеТекущегоСостоянияФискальногоУстройства(ОписаниеОповещения, Неопределено, УстройствоПечати.Ссылка);
ПараметрыЧека.Вставить("ТекущееСостояниеККТ", ТекущееСостояниеККТ);
Иначе
УстройствоПечати = Неопределено;
ЗначенияПараметров.Вставить("УстройствоПечати", УстройствоПечати);
ТекущееСостояниеККТ = Неопределено;
ПараметрыЧека.Вставить("ТекущееСостояниеККТ", ТекущееСостояниеККТ);
КонецЕсли;
Иначе
НомерКартыВместе = ПараметрыЧека.ДанныеСистемыЛояльности.НомерКартыВместе;
ТекущееСостояниеККТ = ПараметрыЧека.ТекущееСостояниеККТ;
ДанныеСистемыЛояльности = ПараметрыЧека.ДанныеСистемыЛояльности;
КонецЕсли;
// Получим баланс карты
РезПолучитьБалансКарты = Новый Структура;
ПолучитьБалансКарты(РезПолучитьБалансКарты, Новый Структура("НомерКарты,ПрямойЗапрос", НомерКартыВместе, Ложь));
Если НЕ РезПолучитьБалансКарты.Результат Тогда
Результат.Результат = Ложь;
Результат.Комментарий = СтрШаблон("%1, %2", "Расчет дисконта", РезПолучитьБалансКарты.Комментарий);
Возврат Результат;
КонецЕсли;
АктивныйБалансКарты = РезПолучитьБалансКарты.Баланс;
ВсеТоварыЧека = Справочники.НаборУсловий.ПолучитьЗначениеПараметра(ЗначенияПараметров, "Товары");
// Выявим и оставим только товары в чеке которые следует обрабатывать (показывать их CRM, считать дисконт)
ТоварыЧека = ПолучитьТоварыЧекаДляОбработки(ВсеТоварыЧека);
Если ТоварыЧека.Количество() = 0 Тогда
Результат.Результат = Ложь;
Результат.Комментарий = "В чеке отсутствуют товары которые отвечают требованиям к расчету дисконта";
Предупреждение(ВернутьФорматныйКомментарий(Результат.Комментарий, "Расчет скидки"), , "Система лояльности " + ВернутьНастройкуПоИдентификатору("ДП_НаименованиеСистемыЛояльности") + ".");
Возврат Результат;
КонецЕсли;
ТаблицаДисконта = СоздатьТаблицуДисконта(ТоварыЧека);
ДополнительныеКлючи = Неопределено;
ЗначенияПараметров.Свойство("ДополнительныеКлючи", ДополнительныеКлючи);
АтрибутыПозицииЧека = ПолучитьдополнительныйАтрибутПозицииЧека(ДополнительныеКлючи);
АтрибутыЧека = ПолучитьДополнительныеАтрибутыЧека(ДополнительныеКлючи, ПараметрыЧека);
НомерЧекаККТ = ?(ТипЗнч(ТекущееСостояниеККТ) = Тип("Структура") И ТекущееСостояниеККТ.Свойство("НомерЧекаККТ"), ТекущееСостояниеККТ.НомерЧекаККТ, Неопределено);
Результат_ПТЧ = Новый Структура;
ВП_ПТЧ = Новый Структура("МягкийЧек,ТоварыЧека,ИдентификаторыПартий,КупоныВместе,АтрибутыЧека,АтрибутыПозицииЧека,Кассир",
Истина, ТоварыЧека, Новый ТаблицаЗначений, ЗначенияПараметров.КупоныВместе, АтрибутыЧека, АтрибутыПозицииЧека, ЗначенияПараметров.Пользователь);
ПередатьТоварыЧека(Результат_ПТЧ, ВП_ПТЧ);
Если НЕ Результат_ПТЧ.Результат Тогда
Результат.Результат = Ложь;
Результат.Комментарий = "Ошибка операции записи товаров чека в 'объект интеграции Золотой Середины'";
Возврат Результат;
КонецЕсли;
ПараметрыТранзакции = Новый Структура;
ПараметрыТранзакции.Вставить("НомерКартыВместе", НомерКартыВместе);
ПараметрыТранзакции.Вставить("НомерЧекаККТ", НомерЧекаККТ);
ПараметрыТранзакции.Вставить("МягкийЧек", Истина);
ПараметрыТранзакции.Вставить("Тип", "Списание");
ПараметрыТранзакции.Вставить("СуммаЧека", ЗначенияПараметров.СуммаЧекаБезСкидки);
ПараметрыТранзакции.Вставить("СуммаСписания", ЗначенияПараметров.СуммаЧека);
Резултат_ВТ = Новый Структура;
ВыполнитьТранзакциюCRM(Резултат_ВТ, ПараметрыТранзакции); //Списание и начисление бонусов
Если НЕ Резултат_ВТ.Результат Тогда
Результат.Результат = Ложь;
Результат.Комментарий = Резултат_ВТ.Комментарий;
Предупреждение(ВернутьФорматныйКомментарий(Результат.Комментарий, "Расчет скидки"), , "Система лояльности " + ВернутьНастройкуПоИдентификатору("ДП_НаименованиеСистемыЛояльности") + ".");
Возврат Результат;
КонецЕсли;
ДанныеСистемыЛояльности.РазрешениеНаЭлектронныйЧек = ПолучитьРазрешениеНаЭлектронныйЧек();
ЛюбимыеТовары = Новый Массив;
Если ПараметрыЧека.ДанныеСистемыЛояльности.ИспользуетсяКартаКупона Тогда
ДанныеСотрудника = Новый Структура("Сотрудник", Ложь);
Данные = Новый Структура("ИспользоватьБонусов", 0);
Иначе
ИспользоватьСервисЛюбимыйТовар = МожноИспользоватьСервисЛюбимыйТовар();
СтатусКарты = ПолучитьСтатусКартыПоСлипу(Резултат_ВТ.ДанныеВыполнения.Слип).СтатусКарты;
ДанныеСотрудника = ВернутьДанныеСотрудника();
Параметры = Новый Структура("Действие,ИмяФормы,СуммаЧека,БонусовСписано,КартаСотрудника,СтатусКарты,ИспользоватьСервисЛюбимыйТовар,АктивныйБалансКарты",
"ПрименитьДисконт", "ФормаПримененияДисконта", ЗначенияПараметров.СуммаЧека, ДанныеСистемыЛояльности.БонусовСписано,
ДанныеСотрудника.Сотрудник, СтатусКарты, ИспользоватьСервисЛюбимыйТовар, АктивныйБалансКарты);
Данные = ИспользоватьФорму(Параметры);
Если НЕ ТипЗнч(Данные) = Тип("Структура") Тогда
Результат.Результат = Ложь;
Результат.Комментарий = "Применение карты " + ВернутьНастройкуПоИдентификатору("ДП_НаименованиеСистемыЛояльности") + ": отмена";
Возврат Результат;
КонецЕсли;
//Получим актуальный Любимый товар для карты
Если ИспользоватьСервисЛюбимыйТовар
И НЕ СтатусКарты = Неопределено Тогда
Состояние("Получение данных 'Любимого товара' ...");
Попытка
ЛюбимыеТовары = ПолучитьВыбранныйЛюбимыйТовар(НомерКартыВместе, СтатусКарты).Список;
Исключение
ВыполнитьЗаписьЖурналаРегистрацииПриОшибки(ИнформацияОбОшибке(), УровеньЖурналаРегистрации.Предупреждение);
Состояние("");
КонецПопытки;
Состояние("");
КонецЕсли;
КонецЕсли;
Если ДанныеСотрудника.Сотрудник Тогда
// Не применияем для сотрудников любимые товары, обнуляем список товаров.
ЛюбимыеТовары = Новый Массив;
КонецЕсли;
ДанныеСистемыЛояльности.Сотрудник = ДанныеСотрудника.Сотрудник;
ОбновитьДД(ДД, , Истина, ДанныеСотрудника.Сотрудник);
Результат_ПТЧ = Новый Структура;
ВП_ПТЧ = Новый Структура("МягкийЧек,ТоварыЧека,ИдентификаторыПартий,КупоныВместе,АтрибутыЧека,АтрибутыПозицииЧека,Кассир,ЛюбимыеТовары",
Истина, ТоварыЧека, Новый ТаблицаЗначений, ЗначенияПараметров.КупоныВместе, АтрибутыЧека, АтрибутыПозицииЧека, ЗначенияПараметров.Пользователь, ЛюбимыеТовары);
ПередатьТоварыЧека(Результат_ПТЧ, ВП_ПТЧ);
Если НЕ Результат_ПТЧ.Результат Тогда
Результат.Результат = Ложь;
Результат.Комментарий = "Ошибка операции записи товаров чека в 'объект интеграции Золотой Середины'";
Возврат Результат;
КонецЕсли;
ПараметрыТранзакции = Новый Структура;
ПараметрыТранзакции.Вставить("НомерКартыВместе", НомерКартыВместе);
ПараметрыТранзакции.Вставить("НомерЧекаККТ", НомерЧекаККТ);
ПараметрыТранзакции.Вставить("МягкийЧек", Истина);
ПараметрыТранзакции.Вставить("Тип", Неопределено);
ПараметрыТранзакции.Вставить("СуммаЧека", ЗначенияПараметров.СуммаЧекаБезСкидки);
ПараметрыТранзакции.Вставить("СуммаСписания", Неопределено);
Если Данные.ИспользоватьБонусов = 0 Тогда
ПараметрыТранзакции.Тип = "Начисление";
ПараметрыТранзакции.СуммаСписания = 0;
Иначе
ПараметрыТранзакции.Тип = "Списание";
ПараметрыТранзакции.СуммаСписания = Данные.ИспользоватьБонусов;
КонецЕсли;
Резултат_ВТ = Новый Структура;
ВыполнитьТранзакциюCRM(Резултат_ВТ, ПараметрыТранзакции); //Только начисление бонусов
//ЗаписатьДанныеТранзакцииВРегистр(,струк_Рез.ДанныеВыполнения);
Если НЕ Резултат_ВТ.Результат Тогда
Результат.Результат = Ложь;
Результат.Комментарий = Резултат_ВТ.Комментарий;
Предупреждение(ВернутьФорматныйКомментарий(Результат.Комментарий, "Расчет скидки"), , "Система лояльности " + ВернутьНастройкуПоИдентификатору("ДП_НаименованиеСистемыЛояльности") + ".");
Возврат Результат;
КонецЕсли;
ИдентификаторыПартий = ВП_ПТЧ.ИдентификаторыПартий;
ТаблицаДисконтаCRM = СоздатьТаблицуДисконта(ТоварыЧека);
Резултат_ВТТ = ВернутьТаблицуРасчетаДисконтаCRM(ТаблицаДисконтаCRM);
Если НЕ Резултат_ВТТ.Результат Тогда
Результат.Результат = Ложь;
Результат.Комментарий = Резултат_ВТТ.Комментарий;
Предупреждение(ВернутьФорматныйКомментарий(Результат.Комментарий, "Расчет скидки"), , "Система лояльности " + ВернутьНастройкуПоИдентификатору("ДП_НаименованиеСистемыЛояльности") + ".");
Возврат Результат;
КонецЕсли;
ТаблицаДисконтСотруднику = СоздатьТаблицуДисконта(ТоварыЧека);
Если ДанныеСотрудника.Сотрудник Тогда
ЗаполнитьТаблицуВнутреннийДисконтСотруднику(ТоварыЧека, ДанныеСотрудника, ТаблицаДисконтСотруднику);
КонецЕсли;
ИтоговыйДисконтПоЧеку = РасчитатьИтоговыйДисконтПоЧеку(ТоварыЧека, ТаблицаДисконтаCRM, ТаблицаДисконтСотруднику);
ДанныеСистемыЛояльности.БонусовСписано = ВернутьЧисло(ПараметрыТранзакции.СуммаСписания); //ВернутьЧисло(глОбъектСистемыЛояльностиВместе.AvailablePayment);
ДанныеСистемыЛояльности.БонусовНачислено = ВернутьЧисло(глОбъектСистемыЛояльностиВместе.ChargedBonus);
ДанныеСистемыЛояльности.TransactionID = глОбъектСистемыЛояльностиВместе.TransactionID;
ДанныеСистемыЛояльности.КоличествоВызововРасчетаСкидки = ДанныеСистемыЛояльности.КоличествоВызововРасчетаСкидки + 1;
Результат.Результат = Истина;
Результат.Комментарий = "Мягкий чек: бонусов списано " + Строка(глОбъектСистемыЛояльностиВместе.AvailablePayment) + ", начислено " + Строка(глОбъектСистемыЛояльностиВместе.ChargedBonus);
Результат.ПараметрыЧека.ДанныеСистемыЛояльности = ДанныеСистемыЛояльности;
Результат.ПараметрыЧека.УстройствоПечати = УстройствоПечати;
Для Каждого ПозицияДисконт Из ИтоговыйДисконтПоЧеку Цикл
ИдентификаторПартии = ИдентификаторыПартий.Найти(ПозицияДисконт.НомерСтроки, "НомерСтроки").Идентификатор;
Партия = Справочники.Партии.ПолучитьСсылку(Новый УникальныйИдентификатор(ИдентификаторПартии));
Если ТоварыЧека.Найти(Партия, "Партия") = Неопределено Тогда
Продолжить;
КонецЕсли;
НовСкидка = ТекСкидки.Добавить();
НовСкидка.Партия = Партия;
НовСкидка.НомерСтроки = ПозицияДисконт.НомерСтроки;
НовСкидка.ДП = ДП;
НовСкидка.ДД = ДД;
НовСкидка.Приоритет = ДП.Приоритет;
НовСкидка.Транзакция = ВернутьНастройкуПоИдентификатору("ДП_ИдентификаторСистемы"); //глОбъектСистемыЛояльностиВместе.TransactionID;
НовСкидка.Комментарий = СокрЛП(?(ПозицияДисконт.Бонус_Списан > 0, ПозицияДисконт.Комментарий + " Бонусов списано: " + Строка(ПозицияДисконт.Бонус_Списан), ПозицияДисконт.Комментарий));
НовСкидка.СуммаСкидки = ПозицияДисконт.Скидка_Итог;
Результат.Скидка = Результат.Скидка + НовСкидка.СуммаСкидки;
КонецЦикла;
ПодготовленныйСлип = "";
Слип = ПолучитьСлип(Ложь, НомерКартыВместе, ПолучитьПредставлениеСтатусаКарты(СтатусКарты),
глОбъектСистемыЛояльностиВместе.ChargedBonus, глОбъектСистемыЛояльностиВместе.AvailablePayment,
глОбъектСистемыЛояльностиВместе.FullBalance, глОбъектСистемыЛояльностиВместе.Balance, ДанныеСотрудника.Сотрудник);
Если НЕ ПустаяСтрока(Слип) Тогда
ПодготовленныйСлип = ПодготовитьСлип(
Новый Структура("Слип,ВидОперации", Слип, "РасчетСкидки"));
КонецЕсли;
Если НЕ ПараметрыЧека.ДанныеСистемыЛояльности.ИспользуетсяКартаКупона Тогда
Результат.Слип = ПодготовленныйСлип;
КонецЕсли;
Попытка
Результат.ДанныеТоваровCRM = ПолучитьДанныеТоваровCRM();
Исключение
ВыполнитьЗаписьЖурналаРегистрацииПриОшибки(ИнформацияОбОшибке());
КонецПопытки;
Возврат Результат;
КонецФункции
ну не используйте виртуальные машины для СУБД !!!!
установите на отдельном системнике для теста
реально живую линус, посгрес,1с и тогда (!!!!) сравнивайте
(10) Спасибо за мнение. Понятно, что варианты компоновки железок и ПО существует множество, но все же хочется понять почему текущая схема так себя показывает, по сути сама схема распространена и успешно применяется, а наш опыт с ловлей подобного поведения частность.
(11)
О чем нужно подумать
• Уровни системы:
• Безопасность
• Отличие реализации физического хранения
• Системные моменты
• Влияющие на код
• Collation
• Ограничений объектам БД (типы данных, наименования, индексы)
• Блокировки и hint
• Отличия в работе временных объектов
• Обращение к другим БД
• Отсутствие встроенного авто-обработчика (pg agent)
• Отличия в языке
• Пакетные скрипты и особенности динамика
• Отличия в работе хранимых процедур
• Отличия в работе транзакций
• Триггеры