ЗавалЕнка

29.10.24

Разработка - Универсальные функции

ЗавалЕнка - наш ответ Зазеркалью !!

Золотые костыли

Мне кажется это название лучше всего подходит к тому, чем мы все занимаемся. Статья «Удачный пример блокировки», получилась небольшая, поэтому следующие заметки добавляю сюда же.

Сделал рестайлинг. Сменил "Золотые костыли" на "ЗавалЕнка".

21. Очистить кеш браузера - слишком грубо

Можно аккуратно очистить кеш одного сайта. Перейдите на страницу сайта, в котором нужно удалить кеш, и нажмите комбинацию клавиш Ctrl + Shift + I или F12 — так вы откроете консоль браузера для разработчиков. Правой кнопкой мыши нажмите на кнопку перезагрузки страницы в левом верхнем углу браузера и выберите опцию Очистка кеша и жесткая перезагрузка (Очистить кеш и выполнить принудительное обновление).

20. "Слетают" права Администраторов

Для пользователей с полными правами разрешено все. Но если мы установим дополнительные роли, значения могут потеряться при обновлении, кроме "ИнтерактивноеОткрытиеВнешнихОтчетовИОбработок". В процедуре "ОбновитьРолиПользователей", модуль "УправлениеДоступомСлужебный" видим код

    ДополнительныеРолиАдминистратора = Новый Соответствие;
    ДополнительныеРолиАдминистратора.Вставить("ИнтерактивноеОткрытиеВнешнихОтчетовИОбработок", Истина);

Сюда добавляйте дополнительные роли, чтобы не потерять при обновлении.

19. Вместо regsvr32

При регистрации DLL программных компонентов на сервере много (-много) лет подряд я использовал команду REGSVR32. Оказывается, есть лучший вариант! Команда regsrv32 DrvLP.dll завершается ошибкой, решение подсказала статья //infostart.ru/1c/articles/685924/. По статье создал com-приложение Мой DrvLP, создал компонент, указал файл DrvLP.dll. В дереве объектов видны даже методы объекта DrvLP. Чтобы не было проблем с правами доступа, убрал галочки «Принудительная проверка доступа для приложения», установил флаг «Проверка доступа только на уровне процесса». Как понимаете, новый способ позволяет больше ))

18. Неравномерное использование ядер

В рамках проверки производительности, возник вопрос: почему в процессоре E5-2687W v4 3ГГц происходит неравномерное использование ядер. Даже когда первая нода загружена, вторая нода почти бездействует. Платформа 1С обновляется регулярно.

 

Кто догадался - молодец! В ноде этого процессора ровно 12 ядер. Платформа ПРОФ, ограниченно использует первые 12 ядер. Если перейдете на лицензию КОРП и сделаете несколько процессов rphost - будут задействованы все ядра. Надо учитывать при планировании закупок сервера. Тактовая частота должна быть максимальной.

17. Один хост для СУБД и службы 1С

СУБД по умолчанию использует до 80% оперативной памяти. Cлужба кластера 1С по умолчанию  использует до 80% оперативной памяти. Если размещать обе программы на одном хосте, объем памяти нужно ограничивать. На рисунке: всего на сервере 64 Гб памяти, служба 1С использует 30 Гб (1), СУБД использует 22 Гб (2), для ОС остается 12 Гб.

16. Настройка http сервисов

Доступ к http сервисам 1С для IIS происходит под служебной записью IUSR. Чтобы настроить авторизацию без пароля, точное имя пользователя операционной системы можно узнать в технологическом журнале. Например, авторизация 1С пользователь windows "\\NT AUTHORITY\IUSR". Настройка журнала приведена ниже. Спасибо ИТС за подсказку https://its.1c.ru/db/metod8dev/content/5944/hdoc

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
 <log location="D:\1CLog\Conn\" history="1">
  <event> 
   <eq property="Name" value="CONN"/>
  </event>
  <event> 
   <eq property="Name" value="EXCP"/>
  </event>
  <property name="all"/>
 </log>
</config>

При работе с веб службами есть своя специфика. Например, служба зависала каждые 15 минут, веб-запрос выдавал ошибку 406. Приходилось перезапускать агент 1С. Потом догадался отредактировать файл default.vrd - установил reuseSessions="dontuse".
Из-за того, что код 1С не проходил синтакс-контроль, появлялась внутренняя ошибка сервера (код 500). Причем, при сохранении (тестировании) кода внутри 1С ошибки не было.

15. Запуск программы в режиме 32 бит

Необходим для установки эмулятора ККМ. Исполняемые файлы 32 бит находятся "C:\Program Files (x86)", в отличие от файлов 64 бит - которые находятся "C:\Program Files". Запускаем программу из "правильного" каталога, в настройках запуска выбираем разрядность 32 бит (фото - 1), запускаем ... Конфигуратор, из него - Предприятие. Проверяем в диспетчере задач (фото - 2). Упс !! Запущена программа 64 бит. Потому что Конфигуратор не бывает 32 бит. Если запустить режим Предприятие без Конфигуратора, то получается правильно. Проверяем в диспетчере задач (фото - 3). Кстати, после запуска Предприятие 32 бит, можно открыть Конфигуратор - Отладка - Подключение - (Доступные предметы отладки) - Подключить.

Благодарю Андрея Кеннунена за моральную, психологическую помощь после этой когнитивной травмы.

14. Когда медленный код лучше

Скачиваем данные, сохраняем во временный файл, открываем файл в Acrobat Reader для печати. Иногда при чтении файла возникает ошибка "Формат файла не поддерживается или файл был поврежден". В чем проблема? У объекта типа "ДвоичныеДанные" есть методы "Записать", "НачатьЗапись". Гарантирует ли метод "Записать", что процесс записи будет завершен? Программа Acrobat Reader находится в памяти постоянно, поэтому открытие файла происходит без задержки. Поместил между командами Записать..ЗапуститьПриложение строку Сообщить("."). Код стал выполняться медленнее, ошибка исчезла.

ДвоичныеДанныеФайл = HTTPОтвет.ПолучитьТелоКакДвоичныеДанные();
ИмяФайла = ПолучитьИмяВременногоФайла("pdf");	
ДвоичныеДанныеФайл.Записать( ИмяФайла );
ИмяФайла = """C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"" /n /t " + ИмяФайла;
ЗапуститьПриложение( ИмяФайла );

13. Портвейн, портер, портрет, портфель

 
 Если при определении службы 1С Агента нет порта - все просто. Стоит задать нестандартный порт - начинаются чудеса.
Для каждой программы требуется свое значение. Так и не привык за двадцать лет :-((

12. Скрыть рабочий стол

Обратите внимание модуль СтандартныеПодсистемыКлиент, фрагмент СкрытьРабочийСтолПриНачалеРаботыСистемы(Ложь). Рабочий стол не исчезает, а очищается. По-настоящему скрыть не удалось.

11. "Объект не найден"

В регистре "резервы товаров" появились битые записи. Создать документы по битым ссылкам, потом снять резервы обычным способом.

Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	ТоварыВРезервеНаСкладахОстатки.ДокументРезерва КАК ЗаказПокупателя
|ИЗ
|	РегистрНакопления.ТоварыВРезервеНаСкладах.Остатки(
|			,
|			ДокументРезерва ССЫЛКА Документ.ЗаказПокупателя
|				И ДокументРезерва.Ссылка ЕСТЬ NULL) КАК ТоварыВРезервеНаСкладахОстатки";
	
РезультатЗапроса = Запрос.Выполнить();	
ВыборкаДетальная = РезультатЗапроса.Выбрать();
	
Пока ВыборкаДетальная.Следующий() Цикл		
		
	НовыйОбъект = Документы.ЗаказПокупателя.СоздатьДокумент();
	НоваяСсылка = Документы.ЗаказПокупателя.ПолучитьСсылку(ВыборкаДетальная.ЗаказПокупателя.УникальныйИдентификатор());
	НовыйОбъект.УстановитьСсылкуНового( НоваяСсылка );
	НовыйОбъект.Дата = ТекущаяДата();
	НовыйОбъект.Записать();	
		
КонецЦикла;

10. МенеджерЗаписи или НаборЗаписей ?

Какой способ записи в регистр выбрать ? Преимущество набора записей в том, несколько несколько строк добавляется в одной транзакции, реже обращения к СУБД. Однако, запись менеджера записи тоже можно объединить с помощью начатьтранзакцию-зафиксироватьтранзакцию, это благотворно отражается в ожиданиях СУБД Writelog. Источник, минута 34.

Еще одна особенность набора записей: если есть повторяющиеся значения измерений, то произойдет ошибка. Если использовать записи менеджера, то ошибки не происходит, повторяющее значение перезаписывается. Контроль уникальности для записи менеджера занимает время. Если есть возможность гарантировать уникальность измерений - набор запишется быстрее, даже если все записи менеджера записываются в одной транзакции. Проверял на 20к записей, сравнение 14 секунд - 2 минуты.

9. Особенности SQL

Если в таблице Таблица1 сто миллионов строк, запрос вида "Выбрать Сумма(1) ИЗ Таблица1" выдает ошибку переполнения.

Ошибка при выполнении операции над данными:
Microsoft OLE DB Provider for SQL Server: Ошибка арифметического переполнения при преобразовании numeric к типу данных numeric.
HRESULT=80040E57, SQLSrvr: SQLSTATE=22003, state=8, Severity=10, native=8115, line=1

Однако, запрос вида "Выбрать Сумма(1/1000000) ИЗ Таблица1" покажет результат )))

8. Поиск на инфостарте.

Для сложных условий поиска можно пользоваться сторонними средствами.

Пример поисковой строки в Yandex.

site:infostart.ru "РегистрНакопления.Продажи"&&"РегистрСведений.ЦеныНоменклатуры"

Постоянно пользуюсь, дает очень точные результаты.

7. Группировка документов по произвольным реквизитам.

В типовой 1С версии 11.4 есть возможность создавать документ Приобретения на основании массива Заказов поставщику. При этом, само собой, происходит проверка что ключевые реквизиты для всех Заказов поставщику совпадают. Проверка выполняется в модуле ЗакупкиВызовСервера.СформироватьДанныеЗаполненияПоступления, обратите внимание какой громоздкий запрос возвращает ТекстЗапросаПоЗаказам(). Допустим, у нас есть массив ЗаказыПоставщику (различающихся документов Заказ поставщику), мы хотим этот массив перегруппировать в несколько массивов одинаковых документов и создать несколько документов Приобретения. Перечень реквизитов - массив со строками например "Контрагент, Договор, Соглашение". Имя документа - строка "Документ.ЗаказПоставщику". Чтобы было можно обрабатывать документы любых типов.

Функция РазбитьПоПризнакам(ЗаказыПоставщику, ПереченьРеквизитов, ИмяДокумента) Экспорт
	
	РезультатФункции = Новый Массив;
	
	ТекстРеквизиты = "";	
	
	Для каждого Реквизит Из ПереченьРеквизитов Цикл
		НакоплениеСтроки(ТекстРеквизиты, Реквизит);
	КонецЦикла;

	РеквизитыВТаблице = РеквизитыВТаблице(ЗаказыПоставщику, ТекстРеквизиты, ИмяДокумента);	
	НаборыРеквизитов = РеквизитыВТаблице.Скопировать();	
	НаборыРеквизитов.Свернуть(ТекстРеквизиты,"");
	
	Для каждого НаборРеквизитов Из НаборыРеквизитов Цикл
		
		ОтборРеквизитов = Новый Структура;
		Для каждого Элемент Из ПереченьРеквизитов Цикл
			ОтборРеквизитов.Вставить( Элемент, НаборРеквизитов[Элемент] );
		КонецЦикла; 
		
		ЗаказыПоставщикуРазбитые = Новый Массив;
		
		РеквизитыСтроки = РеквизитыВТаблице.НайтиСтроки(ОтборРеквизитов);
		Для каждого Элемент из РеквизитыСтроки Цикл
			ЗаказыПоставщикуРазбитые.Добавить(Элемент.Ссылка);
		КонецЦикла;
		
		РезультатФункции.Добавить(ЗаказыПоставщикуРазбитые);
		
	КонецЦикла;
	
	Возврат РезультатФункции;

КонецФункции

Функция РеквизитыВТаблице(ЗаказыПоставщику, ПереченьРеквизитов, ИмяДокумента)

	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ЗаказПоставщику.Ссылка КАК Ссылка
	|ИЗ
	|	Документ.ЗаказПоставщику КАК ЗаказПоставщику
	|ГДЕ
	|	ЗаказПоставщику.Ссылка В(&ЗаказыПоставщику)";
	
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "Документ.ЗаказПоставщику", "Документ."+ИмяДокумента);
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "КАК Ссылка", ","+ПереченьРеквизитов);

	Запрос.УстановитьПараметр("ЗаказыПоставщику", ЗаказыПоставщику);
	
	Возврат Запрос.Выполнить().Выгрузить();	

КонецФункции

Процедура НакоплениеСтроки(Основа, Добавление)

	Если Основа = "" Тогда
		Основа = Строка(Добавление);
	Иначе
		Основа = Основа + "," +Добавление;
	КонецЕсли;	

КонецПроцедуры

6. Проверка html средствами 1С.

Похожие задачи дают в ЕГЭ, на первом курсе некоторых институтов. Так что сын-студент мне помог. В нашей базе для каждого товара содержится небольшой html-текст, возникла потребность проверять, чтобы количество открытых и количество закрытых тегов были равны на каждом уровне вложенности. Процедура ПроверитьПолеHTML вызывается при записи номенклатуры. Теги <br /> ,<hr /> являются исключениями: их проверять не нужно. Штатная процедура проверки работает немного иначе, для решения не подходит. Код для обычного (не-управляемого) приложения.

Процедура ПроверитьПолеHTML(Отказ)
	
	СуществующиеТеги = СуществующиеТеги();
	СуществующиеТеги.Свернуть("ИмяТега, Уровень", "Знак");
	
	ТекстОшибки = "Не совпадает количество открытых/закрытых тегов.";
	
	Для каждого Тег Из СуществующиеТеги Цикл
		
		Если Тег.Знак <> 0 Тогда
			
			ТекстОшибки = ТекстОшибки  + Символы.ПС + "Имя тега " + Тег.ИмяТега + " Уровень " + Тег.Уровень;
			
		КонецЕсли;	
		
	КонецЦикла; 
	
	Если СтрЧислоСтрок(ТекстОшибки) > 1 Тогда
		
		ОбщегоНазначения.СообщитьОбОшибке( ТекстОшибки, Отказ);
		
	КонецЕсли;	

КонецПроцедуры

Функция СуществующиеТеги() 
	
	РезультатФункции = Новый ТаблицаЗначений;
	РезультатФункции.Колонки.Добавить("ИмяТега");
	РезультатФункции.Колонки.Добавить("Уровень");
	РезультатФункции.Колонки.Добавить("Знак");
	
	ТекущийСимвол = "";
	ПозицияВСтроке = 1;
	
	Пока ПозицияВСтроке < СтрДлина(ДополнительноеОписаниеНоменклатурыHTML) Цикл
		
		ПрошлыйСимвол = ТекущийСимвол;		
		ТекущийСимвол = Сред(ДополнительноеОписаниеНоменклатурыHTML,ПозицияВСтроке,1);
		
		Если ПрошлыйСимвол = "<" 
			И ТекущийСимвол = "/" Тогда
			
			ПозицияВСтроке = ПозицияВСтроке+1;
			ДобавитьТег(ПозицияВСтроке, РезультатФункции, -1);
			
		ИначеЕсли ПрошлыйСимвол = "<" 
			И ТекущийСимвол <> "/" Тогда
			
			ДобавитьТег(ПозицияВСтроке, РезультатФункции, 1);
			
		Иначе
			
			ПозицияВСтроке = ПозицияВСтроке + 1;			
			
		КонецЕсли;
		
	КонецЦикла; 
	
	Возврат РезультатФункции;
	
КонецФункции

Процедура ДобавитьТег(ПозицияВСтроке, РезультатФункции, Знак)

	ИмяТега = "";
	
	Пока ПозицияВСтроке <= СтрДлина(ДополнительноеОписаниеНоменклатурыHTML) Цикл
		
		ТекущийСимвол = Сред(ДополнительноеОписаниеНоменклатурыHTML,ПозицияВСтроке,1);
		ПозицияВСтроке = ПозицияВСтроке + 1;		
		
		Если ТекущийСимвол = ">" Или ТекущийСимвол = " " Тогда
			
			Если Найти(ИмяТега, "br") + Найти(ИмяТега, "hr") = 0 Тогда

				НоваяСтрока = РезультатФункции.Добавить();
				НоваяСтрока.ИмяТега = ИмяТега;
				НоваяСтрока.Уровень = ?(Знак = 1, РезультатФункции.Итог("Знак"), РезультатФункции.Итог("Знак")-1);
				НоваяСтрока.Знак = Знак;
				
			КонецЕсли;
			
			Возврат;			
			
		Иначе
			
			ИмяТега = ИмяТега + ТекущийСимвол;
			
		КонецЕсли;
		
	КонецЦикла;	

КонецПроцедуры

 

5. Пример отладки.

После обновления конфигурации при первом запуске вышла ошибка, с комментарием ОбщийМодуль.ДлительныеОперации.Модуль(376): Недопустимое значение параметра. По этому адресу находится код

ТекстОшибки = КраткоеПредставлениеОшибки(Задание.ИнформацияОбОшибке);
ВызватьИсключение(ТекстОшибки);

В отладчике настроил остановку, удалось получить более подробную информацию из переменной Задание.ИнформацияОбОшибке. Оказывается, ошибка происходила в модуле ОбновлениеИнформационнойБазы, код

ПланыОбмена.ЗарегистрироватьИзменения(Узел, Данные);

Тут не подходит безусловная остановка или остановка с условием. Останавливаться по каждой ошибке – тоже не подходит: слишком много ошибок завершения фоновых заданий. В отладчике настроил остановку по ошибке 

Нашел данные, на которых происходит ошибка регистрации и исключил их из обработки.

4. Потерянное регламентное задание.

После обновления конфигурации в журнале регистрации появились записи "{ОбщийМодуль.ОбщегоНазначения.Модуль(2385)}: Регламентное задание недоступно по функциональным опциям или не поддерживает работу в текущем режиме работы программы. Выполнение прервано.". Еще в сообщении есть название регламентного задания, но в диспетчере регламентных заданий такого задания нет. В режиме конфигуратора не удается найти, откуда задание запускается.

По названию задания нашел связанную с ним функциональную опцию. Остановил регламентные задания в консоли кластера. Включил опцию. Задание появилось в диспетчере задач. Отключил выполнение регламентного задания. Все просто. Для осознания этой простоты мне потребовалось всего пару дней. )))

Список функциональных опций для регламентных заданий находится модуль РегламентныеЗаданияПереопределяемый, процедура ПриОпределенииНастроекРегламентныхЗаданий(Настройки)

3. Нестандартное использование замера производительности.

Бывает, что код плохо структурирован, в нем трудно разобраться. )) Например, нам нужно быстро найти, какой макет используется в печатной форме. Запускаем замер производительности, выполняем печать, завершаем замер. Получаем листинг выполненных команд. Выполняем поиск (Ctrl+F) слов "Макет", выбираем нужную строку.

2. Попытка, еще попытка…

Используйте конструкцию Попытка … Исключение … КонецПопытки правильно. ))

Между Исключение … КонецПопытки обязательно должна находиться команда ЗаписьЖурналаРегистрации(); и возможно Сообщить(); ВызватьИсключение; Программа не должна прятать происходящие ошибки, их обязательно выводить в журнал. Кто-то должен ежедневно анализировать и устранять причины ошибок. Казалось бы, это банально, но многие ли из нас начинают день просмотром журнала регистрации ? Кстати, даже некоторые «коробочные» решения не всегда используют ЗаписьЖурналаРегистрации(). Поэтому приходится мучительно долго искать причину очередного "отказа программы".

Далее, не нужно создавать такую ситуацию, когда конструкция выполняется в транзакции, а внутри ее прячется еще одна транзакция, например

Процедура ПриЗаписи(Отказ)

Попытка

ДокументПродажи = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
...
ДокументПродажи.Записать();

Исключение
....
КонецПопытки.

...
КонецПроцедуры;

В этом случае конструкция "Попытка … Исключение … КонецПопытки" бесполезна и вредна. В случае, если во вложенной транзакции произойдет ошибка, внешняя транзакция тоже откатится, но причины никто не увидит. Это фатум.

 

1. Удачный пример блокировки

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

Вариант 1. Сделать блокировку чего-либо на время печати документов кодом типа

Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить();
ЭлементБлокировки.Область = …
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.УстановитьЗначение…
Блокировка.Заблокировать(); 

Не представлялось возможным: ведь тогда всю процедуру печати нужно было выполнять в транзакции.

Вариант 2. Записывать в регистр сведений информацию о том, что регламентное задание должно ожидать некоторое время – тоже отпадает. Как обеспечить корректную работу такого регистра в случае ошибок, сбоев и аварийного завершения программы ?

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

Функция УстановитьБлокировку()
	Попытка
		ФлагБлокировки = ПараметрыСеанса.ТекущийПользователь.ПолучитьОбъект();
		ФлагБлокировки.Заблокировать();
		Возврат ФлагБлокировки;
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

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

Функция ЕстьБлокировка(Пользователь)
Попытка
	Пользователь.ПолучитьОбъект().Заблокировать();
Исключение
	Возврат Истина;
КонецПопытки;
Возврат Ложь;
КонецФункции

Функция проверяет для выбранного пользователя, не установлена ли по нему блокировка. Если пользователей много – вызывайте в цикле. Штатная функция Заблокирован() почему-то не отрабатывает. Возможно, фича моей платформы 8.3.11.

Таким способом, удалось избавиться от взаимоблокировок в работе. Всем успехов !

 

блокировки взаимоблокировки

См. также

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.

23.06.2024    8318    bayselonarrend    20    

156

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.

21.05.2024    21782    dimanich70    81    

146

Механизмы платформы 1С Программист Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    24319    SeiOkami    48    

135

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    15381    YA_418728146    7    

169

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    3745    58    progmaster    8    

4

Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Рассмотрим новую возможность 8.3.24 и как её можно эффективно использовать

27.06.2023    26729    SeiOkami    32    

115
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. login1020 138 23.08.18 16:46 Сейчас в теме
такое решение актуально только для печати же?
А как быть с блокировками и ожиданиями на параллельном проведении Прихода и расхода по одной и той же группе товаров. Есть решение?
3. herfis 513 23.08.18 17:14 Сейчас в теме
Вполне рабочий костыль. Одобрям!
Штатная функция Заблокирован() почему-то не отрабатывает

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

(1) Не обязательно для печати. Для любых случаев, где требуется глобальный "флаг" работы какого-либо процесса. К транзакционным блокировкам это не имеет отношения. Преимущество перед состоянием флага, хранимым в БД, очевидно - в случае сбоев флаг будет сброшен автоматически.
2. vasilev2015 2728 23.08.18 17:08 Сейчас в теме
Здравствуйте !

Это решение позволило не заключать печать в транзакцию.

Если возникают ошибки из-за одновременного прихода и расхода, то можно таким же способом разделить их по времени.

Если нужно обязательно выполнять одновременно - используйте стандартные рекомендации для улучшения параллельной работы:
включить разделение итогов регистров накопления, перейти в режим совместимости 8.3 управляемые блокировки.
login1020; +1 Ответить
4. Goleff74 218 23.08.18 19:17 Сейчас в теме
Эм. А что за действия такие происходят при печати, что это каким-то образом мешает проведению?
ice-net; Plotks2017; zqzq; +3 Ответить
5. vasilev2015 2728 23.08.18 19:28 Сейчас в теме
(4) Там неудачный алгоритм. Документы создаются, проводятся частично, печатаются через модуль объекта. Когда ИТ отдел предлагает все оптимизировать, руководство соглашается. Но чтобы через два-три часа уже все было оптимально :-)
6. Goleff74 218 23.08.18 19:37 Сейчас в теме
(5)
Т.е. во время печати еще и что-то записывается в регистры, которые используются проведением, раз печать в транзакции нежелательно?
ice-net; Plotks2017; +2 Ответить
7. tormozit 7238 24.08.18 07:05 Сейчас в теме
Регламентное задание перед тем как начать перепроведение – проверяет что установленных блокировок нет (для всех пользователей)
Так если оно проверило и начало перепроведение, и тут же пользователь начал печать?
8. vasilev2015 2728 24.08.18 08:42 Сейчас в теме
(7) Здравствуйте, Сергей !
Такая ситуация возможна, но к проблемам не приводит.
При желании можно поставить проверку и в обратную сторону.
9. ladon 24.08.18 09:01 Сейчас в теме
Я так понимаю, всё это можно было бы решить установкой одного флага на всю систему?

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

А так да - неплохой обход.
10. vasilev2015 2728 24.08.18 10:27 Сейчас в теме
(9) Здравствуй, Андрей !
Рад тебя видеть ))). Это практически наша общая статья )))

Да, можно было бы выбрать один объект и установить на него пессимистическую объектную блокировку.
11. ladon 24.08.18 10:31 Сейчас в теме
(10)
Да, можно было бы выбрать один объект и установить на него пессимистическую объектную блокировку.

Привет-привет.
Да, память об этой печати будет жить вечно. :))
12. vasilev2015 2728 25.08.18 09:59 Сейчас в теме
(11)
Да, можно было бы выбрать один объект и установить на него пессимистическую объектную блокировку.


я сообразил: один глобальный флаг подойдет для других целей, а в данном случае важно, что пользователей много. Первый наложил блокировку, второй не думая о состоянии глобального флага наложил блокировку... Проведение начнется, когда все они освободят ресурс. Получается, что все сделано оптимально. Флагов должно быть много. Все флаги в гости будут к нам и запируем на просторе.
13. ladon 25.08.18 13:12 Сейчас в теме
(12) параллельная печать двумя пользователями.. Ну да, вариант. :)
14. PerlAmutor 155 26.08.18 17:38 Сейчас в теме
Я правильно понимаю,что смысл всех этих действий заключается в том, что вы нашли аналог глобального семафора, и в случае, если флаг стоит хотя бы у одного пользователя базы данных, то ничего не делать и просто ждать следующего запуска регламентного задания по расписанию?
15. vasilev2015 2728 27.08.18 09:08 Сейчас в теме
(14) Здравствуйте !

Да, глобальный семафор (в разрезе пользователей), обладающий многими полезными свойствами: простота, устойчивость к аварийным завершениям, малый расход ресурсов.
16. PerlAmutor 155 27.08.18 09:34 Сейчас в теме
(15) Единственная проблема заключается только в том, что свойства пользователя (пароль, логин и т.д.) невозможно изменить на момент печати?
18. vasilev2015 2728 27.08.18 10:33 Сейчас в теме
(16) Интерактивно не удастся изменить реквизиты заблокированного элемента справочника. Но объектная блокировка не запрещает их изменять программно. В моем случае выбран справочник пользователи, но это могла быть искусственная конструкция: Справочник1 с реквизитом пользователь. Решение используется каждый день, пять человек печатают документы, регламентное задание приостанавливается. Все довольны.
17. Evil Beaver 8252 27.08.18 09:51 Сейчас в теме
Так же через объектные блокировки решаются задачи обработки всевозможных очередей. Очень полезный механизм, по сути mutex на уровне платформы.
19. vasilev2015 2728 27.08.18 10:37 Сейчас в теме
(17) в первую очередь для меня привлекательно отсутствие транзакции по сравнению с "обычными" блокировками. С языками программирования кроме 1С я не знаком, сравнивать не могу. ))
20. PerlAmutor 155 27.08.18 12:29 Сейчас в теме
А что если повесить блокировку на константу?

Вот еще один вариант нашел: https://infostart.ru/public/384485/
21. scientia_vinces 27.08.18 14:19 Сейчас в теме
(20) Совсем плохая идея. Если и делать софтовую эмуляцию, то только на основании регистра сведений.
23. vasilev2015 2728 27.08.18 14:40 Сейчас в теме
(21) Согласен, использовать внешний файл - совсем плохой вариант. Регистр сведений - чуть лучше плохого варианта, но тоже плох.
28. СергейК 51 29.08.18 11:51 Сейчас в теме
(21) Почему Константа плохая идея? Или вы не про неё?
Сейчас, вроде, каждая константа находится в отдельной таблице, блокировка не должна никому мешать...
29. herfis 513 29.08.18 12:07 Сейчас в теме
(28) Во-первых, все константы находятся мало того, что в одной таблице, так еще и в одной строке :)
Во-вторых, пессиместическую объектную блокировку на константу наложить нельзя. А транзакционная блокировка плоха не только по вышеуказанной причине, но еще и тем что в транзакцию попадают и все остальные операции с БД в задании.
Любой же семафор на нетранзакционной записи значения в БД плох тем, что он останется взведенным в случае, когда выполнение задания будет прервано аварийно.
Другое дело, что круг применений таких "мьютексов" в 1С довольно ограничен. Гораздо чаще нужна классическая очередь заданий.
32. СергейК 51 29.08.18 21:38 Сейчас в теме
(29)
Не нашел ссылки с 1С сайта, но такое уже читал из разных источников, кажется можно верить:
Способ хранения констант в 1С:Предприятие 8 менялся в зависимости от версии платформы. Так, в платформе до версии 8.2.14 (или платформах выше версии, но с включенным режимом совместимости 8.2.13 и ниже), константы хранятся в одной таблице СУБД, начиная с версии 8.2.14, для каждой константы создается своя таблица СУБД. Данное изменение было сделано для увеличения параллельности работы пользователей.


Во-вторых, пессиместическую объектную блокировку на константу наложить нельзя...

Как это можно проверить, может уже можно?
Почитал документацию, да, нельзя получить константу как объект. Понятно вроде. Спсб.
33. herfis 513 30.08.18 09:12 Сейчас в теме
(32) По-поводу констант ты прав. Заглянул в базу 8.3 с отключенным режимом совместимости - таки по таблице на константу уже. Надо же, а я и не знал. Спасибо за инфу.
22. vasilev2015 2728 27.08.18 14:39 Сейчас в теме
(20) Если на единственную константу, то непонятно как снимать блокировку, когда обработки идут параллельно и оканчиваются в разное время.
24. herfis 513 28.08.18 09:13 Сейчас в теме
(20) Транзакционную блокировку? Это дорого, неудобно и не всегда допустимо.
В варианте по ссылке (с файликами) главный минус - неявное ограничение на один рабочий сервер в кластере.
Сабжевый вариант лишен этих недостатков. Как правильно заметили - это почти полный аналог мьютексов. Механизмы платформы обеспечивают автоматическое снятие блокировки при уничтожении объекта-владельца (завершении процесса). В отличие от классических мьютексов предоставляемых операционками (базирующихся на "монопольных" инструкциях процессора), можно разруливать параллельную работу процессов на разных рабочих серверах.
Если мне не изменяет память, в 7.7 пессиместические блокировки объектов реализовывались как раз на файловых блокировках (блокировались соответствующие биты/байты в спец-файликах). В 8-ке, подозреваю, реализовано примерно также, только на компе менеджера кластера и какой-то сервис менеджера кластера отвечает за дистрибуцию этой информации.
25. asved.ru 37 29.08.18 10:33 Сейчас в теме
Кажется, вернее было бы расследовать причины задержек печати (есть подозрение, что речь о задержке в выводе документа на принтер).

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

руководство соглашается. Но чтобы через два-три часа уже все было оптимально


Вы с руководством подходите друг другу.
26. vasilev2015 2728 29.08.18 11:41 Сейчас в теме
(25) Здравствуйте !

Кажется, вернее было бы расследовать причины задержек печати (есть подозрение, что речь о задержке в выводе документа на принтер).


у нас при так называемой печати происходит частичное проведение, поэтому взаимоблокировки с процедурой проведения из-за разного порядка записей в регистры. Видно в ТЖ.

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


Простой тест: один пользователь проводит документ, тормозит в отладчике на последней строке. Второй пользователь проводит документ - взаимоблокировок нет. Параллельное проведение работает. Правильное решение.

Вы с руководством подходите друг другу.


Они уважают мой талант, я уважаю их нужды. Лишних денег ни у кого нет.
user591389_aska_rabota; Dementor; +2 Ответить
27. СергейК 51 29.08.18 11:48 Сейчас в теме
Правильно понимаю, если только один пользователь захочет из под двух своих сессий 1С печатать, то не получится?
Пока не приходилось делать как бы "множественный" семафор, т.е. не выполнять процедуру пока куча других пользователей делают критические операции. Было наоборот, одна процедура, много пользователей но выполнить её должен кто-то один.
Интересно, спсб.
p.s.
в лоб напрашивается только одна альтернатива: справочник, в который добавляем элемент когда печатаем, удаляем(помечаем) когда закончили. А в регламентном задании запросом проверяем можно ли работать.
Но так кажется будет накладнее.
30. vasilev2015 2728 29.08.18 12:18 Сейчас в теме
(27) Здравствуйте !

Один пользователь, две сессии - эта процедура печати не получится. Альтернативы хуже.
31. WellMaster 104 29.08.18 15:23 Сейчас в теме
Нормальное решение. Пригодится, спасибо.
34. vasilev2015 2728 20.09.18 09:36 Сейчас в теме
Пункт 2 (Попытка, еще попытка) сильно похож на https://its.1c.ru/db/v8std#content:2149184148:hdoc. Но у меня доступнее, короче и правильно расставлены акценты. )))
35. Casey1984 3 14.10.18 09:06 Сейчас в теме
К разделу Удачный пример блокировки. Это сработает, если ТекущийПользователь в процедуре печати совпадает с пользователем переданным в ЕстьБлокировка(), т.е. вы последовательно всех пользователей в регламентном задании проведения проверяете? Или я что-то не понял?
36. Hatson 536 17.08.21 09:21 Сейчас в теме
37. rozer 311 27.05.22 12:55 Сейчас в теме
про объектные блокировки и использование их в качестве "мьютекса": добавить спец. справочник с предопределенными элементами и использовать Заблокировать() в try-except. Бинго!
38. Hatson 536 14.12.22 20:17 Сейчас в теме
"...но многие ли из нас начинают день просмотром журнала регистрации ?" - ох, не дай бог начинать день с журнала регистрации ))
39. Hatson 536 14.12.22 20:25 Сейчас в теме
ФлагБлокировки = ПараметрыСеанса.ТекущийПользователь.ПолучитьОбъект(); 
ФлагБлокировки.Заблокировать(); // не то пальто, 
// произойдет чтение всех данных объекта при вызове "ПолучитьОбъект()", 
// а ведь фиг знает что там внутри. и ".Заблокировать()" работает криво

// Предлагаю так;
ЗаблокироватьДанныеДляРедактирования(ПараметрыСеанса.ТекущийПользователь);


//СП:
ЗаблокироватьДанныеДляРедактирования(<Ключ>, <ВерсияДанных>, <ИдентификаторФормы>)

Заблокировать данные для редактирования в форме клиентского приложения.
Вызывает исключение, если объект уже заблокирован, в том числе и методом Заблокировать.
Оставьте свое сообщение