Имя: Пароль:
1C
1С v8
Фоновые задания. Превышение времени предоставления блокировки
,
0 Tateossian
 
24.09.14
16:21
Уважаемые форумчане! Столкнулся со следующей проблемой. В некой функции строю дерево партий (из партионного учета) со всеми цепочками преобразований (через отчеты производства за смену, комплектации) - некий локальный расчет себестоимости. Переделал разузлование на фоновых заданиях, которые запускаются при уровне выше второго. Но во время работы фоновых заданий есть таблица, которая хранит в себе данные "цепочек" - с документом оприходования и документом списания и количеством. Данные в ней должны быть синхронизированы: сначала я читаю данные в этой таблице, потом записываю. Эта таблица сделана на непериодическом РС. И постоянно фоновые задания падают на методе Прочитать(). Как правильно разруливать блокировку? Там таблица из трех записей, вот же ж. И все равно падает.
1 Tateossian
 
24.09.14
16:23
Сделал вот такую штуку с блокировкой. может, не правильно?

Процедура НакопитьДвижение(ТаблицаНакопленных, Регистратор, ДокументПартии, Номенклатура, Количество)
        
    Блокировка = Новый БлокировкаДанных;
    ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.АА_НакоплениеДвиженийНДСЭкспорт");
    ЭлементБлокировки.УстановитьЗначение("ДокументДвижения", Регистратор);
    ЭлементБлокировки.УстановитьЗначение("ДокументОприходования", ДокументПартии);
    ЭлементБлокировки.УстановитьЗначение("Номенклатура", Номенклатура);
                
    МенеджерЗаписи = РегистрыСведений.АА_НакоплениеДвиженийНДСЭкспорт.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.ДокументДвижения = Регистратор;
    МенеджерЗаписи.ДокументОприходования = ДокументПартии;
    МенеджерЗаписи.Номенклатура = Номенклатура;
    МенеджерЗаписи.Прочитать();
    Блокировка.Заблокировать();
    Если Не МенеджерЗаписи.Выбран() Тогда
        МенеджерЗаписи.ДокументДвижения = Регистратор;
        МенеджерЗаписи.ДокументОприходования = ДокументПартии;
        МенеджерЗаписи.Номенклатура = Номенклатура;
        МенеджерЗаписи.Количество = Количество;
    Иначе
        МенеджерЗаписи.Количество = МенеджерЗаписи.Количество + Количество;
    КонецЕсли;
    МенеджерЗаписи.Записать();
    
    Блокировка = Неопределено;
    
КонецПроцедуры
2 Tateossian
 
24.09.14
16:31
(1) Это обрезанная функция, не обращайте внимания на параметр "ТаблицаНакопленных".

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

Процедура ППП() // написал для форматирования

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

...

НакопитьДвижение(ТабНакопленных, ДокПартии, стрОстаток.Регистратор, стрОстаток.Затрата, лСписываем);



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

То есть, я сначала читаю остаток в этом регистре, потом его дописываю. Излишняя блокировка получается.
3 Tateossian
 
24.09.14
17:36
Убрал процедуру НакопитьДвижение() и засунул все сюда (2)

Процедура ППП() // написал для форматирования


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

...

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

Все равно падает...
4 Зойч
 
24.09.14
17:47
режим блокировок какой?
5 Tateossian
 
24.09.14
17:48
(4) Управляемый, конечно.
6 bolobol
 
24.09.14
17:51
Если управления не получается, видимо - НЕуправляемый и НЕконтролируемый...
7 Зойч
 
24.09.14
18:06
интересно с другой стороны кто блокирует
8 Зойч
 
24.09.14
18:08
9 Tateossian
 
25.09.14
16:28
Апну ветку.

Господа! Я не уточнил, что это все делается в обработке проведения. Если эту функцию вывести отдельно, то все работает без проблем. Вопрос: почему в обработке проведения фоновые задания блокируются?

У документа режим управления блокировкой выставил в управляемый.
10 bolobol
 
25.09.14
16:52
Твою стипендию! С этого и начинать нужно было!
Сам себе заблокировал в транзакции проведения, а другим сеансом накладываешь тоже самое.
11 acanta
 
25.09.14
16:52
А где то в настройках сеанса можно увеличить это время предоставления блокировки?
12 Fragster
 
гуру
25.09.14
17:46
(11) можно даже программно
13 Fragster
 
гуру
25.09.14
17:48
Глобальный контекст (Global context)
УстановитьВремяОжиданияБлокировкиДанных (SetLockWaitTime)
Синтаксис:

УстановитьВремяОжиданияБлокировкиДанных(<Таймаут>)
Параметры:

<Таймаут> (необязательный)

Тип: Число.
Время ожидания блокировки данных (в секундах).
Значение по умолчанию: 20
Описание:

Устанавливает время ожидания блокировки данных (в секундах).

Доступность:

Сервер, толстый клиент, внешнее соединение.
14 Tateossian
 
25.09.14
18:23
(10) В том-то и загвоздка, что фоновым заданиям вообще пофиг на проводимую реализацию в родительском сеансе. Если убрать этот регистр, то фоновые задания отрабатываются нормально. Это регистр нужен для синхронизации данных, отрабатываемых разными фоновыми заданиями. Я тестировал без него - никаких проблем с блокировками. Выходит, вся проблема в данном регистре, но в родительском сеансе к нему нет обращений. ЧЯДНТ?
15 Fragster
 
гуру
25.09.14
18:39
документ подичиненый регистратору? удаление движений авто? в регистр пишешь в "родительском" сеансе?
16 Tateossian
 
25.09.14
18:41
(15) В смысле регистр? Не, неподчиненный. В родительском этот регистр вообще не используется. Кстати, заметил, что результаты, выполненные в одном потоке и асинхронно различаются. Не сильно, но разница есть. Походу, ошибка в логике где-то :(
17 Fragster
 
гуру
25.09.14
18:43
надеюсь, ты в обработке проведения не дожидаешься конца выполнения фоновых, а только их стартуешь, а уже они разруливают формирование движений и слитие результатов?
18 Fragster
 
гуру
25.09.14
18:46
концепт такой:

обработка проведения -> старт фонового задания 1

фоновое задание 1 - делим данные на независимые порции, стартуем фоновые задания 2...К на каждую порцию или не более чем Х штук в цикле пока порции не закончатся. ждем окончания

Фоновые задания 2...К пишут в независимый регистр результаты своей работы

фоновое задание 1 - собирает результаты, очищает регистр-буфер, записывает набор движений исходного документа.
19 Tateossian
 
25.09.14
18:51
(18) ААААА, понял. У меня нет этого "прокси" - фонового задания 1. Кстати, можно подключить обработчик ожидания (имхается мне) и там стартануть все это дело. Но вот вопрос: а если будет эксепшн, как этот вопрос разрулить? (Движения тогда не запишутся)
20 Fragster
 
гуру
25.09.14
18:52
МенеджерФоновыхЗаданий (BackgroundJobsManager)
ОжидатьЗавершения (WaitForCompletion)
Синтаксис:

ОжидатьЗавершения(<ФоновыеЗадания>, <Таймаут>)
Параметры:

<ФоновыеЗадания> (обязательный)

Тип: Массив.
Массив фоновых заданий, завершение которых нужно ожидать.
<Таймаут> (необязательный)

Тип: Число.
Таймаут в секундах ожидания завершения заданий. Если таймаут не задан, ожидание будет длиться до завершения всех заданий, или до первого аварийного завершения задания.
Описание:

Ожидает завершения всех фоновых заданий из списка. Если хотя бы одно задание завершено аварийно, ожидание прерывается и выдается ошибка выполнения задания. Если наступил таймаут, выдается ошибка ожидания задания. Ожидать завершения заданий может только администратор или пользователь, запустивший задания на выполнение.

Доступность:

Сервер, толстый клиент, внешнее соединение.
21 Fragster
 
гуру
25.09.14
18:53
вот тут тоже без проксизадания, но мало ли:

http://infostart.ru/public/173394/
22 Tateossian
 
25.09.14
18:59
(20) Я как раз эту процедуру юзаю в обработке проведения. Если она выполнится, тогда отрабатываю данные, если "отваливается" провожу без фоновых заданий. Так вот после добавления этого регистра, обеспечивающего синхронизацию - она всегда отваливается. Даже одно фоновое задание нельзя запустить. Почему так?
23 Fragster
 
гуру
25.09.14
19:10
(22) забей на обработку проведения, делай все вне транзакции
24 Fragster
 
гуру
25.09.14
19:10
иначе будет косяк
25 Fragster
 
гуру
25.09.14
19:11
ну ты видимо юзаешь какие-то заблокированные ресурсы из незакрытой транзакции записи-проведения документа, и при этом сам себе дедлок делаешь
26 Tateossian
 
25.09.14
19:25
(25) Ок, я понял. А как проверить, что фоновое задание отработало нормально? Видится мне мне, что что-то вроде Пока Не проведенПравильно Цикл завернуть в попытку, а при исключении проведенПравильно = ложь и так до бесконечности:) Или ограничиться несколькими попытками и вывести в ЖР.
27 Fragster
 
гуру
25.09.14
19:41
в обработке проведения пиши в регистр ключ задания номер 1, в конце фонового задания пиши в регистр успех или косяк, далее - обрабатывай, либо в самом задании (при необходимости отменяй проведение, например), либо в обработке ожидания.

также передзаписью документа можно этот регистр проверять и блокировать.

И в списке документов раскрашивать сереньким, допустим.
28 Fragster
 
гуру
25.09.14
19:42
(27)+ только в случае косяка - надо не совсем отменять, а восстанавливать предыдущее состояние, что немного сложнее