Имя: Пароль:
1C
1C 7.7
v7: "ОтменитьПроведение()" и транзакция...
0 Zhuravlik
 
27.10.11
16:48
Здравствуйте. В моей базе большой документооборот, кто-то все время что-то перепроводит, в общем транзакции - обычное явление.
Если в обработке мне нужно создать документ, я пользуюсь такой конструкцией:

Процедура ВОбходТранзакций(Док, Действие)
 Попытка
   Если Действие = "Записать" Тогда
     Док.Записать();
   ИначеЕсли Действие = "Провести" Тогда
     Док.Провести();
   КонецЕсли;
 Исключение
//здесь процедурка с таймаутом...
   ВОбходТранзакций(Док, Действие)
 КонецПопытки;
КонецПроцедуры

//...
Док = СоздатьОбъект("Документ.Реализация");
//...
ВОбходТранзакций(Док, "Провести");
//...




Если в качестве действия задавать Провести, Записать, Новый, ПометкаУдаления - Все прекрасно работает, если во время выполнения началась транзакция, процедура рекурсивно после таймаута вызывается, и дело движется.

И только один пункт ломает весь кайф - это если надо отменить проведение документа. Если во время отмены проведения началась транзакция, то ОписаниеОшибки() выдает "ДокументЗаблокирован", причем его нельзя открыть. Как будто он открыт другим пользователем. И чтобы продолжить с этим доком работать надо перезапустить 1С. Иначе он будет заблокирован.
Вопрос: Можно ли как-то это обойти? Кроме установки ожидания захвата таблиц в 999, тут есть выносная база, из которой 2-3 раза в день загружаются данные с транзакцией, хаотично. Выгрузка длится 10-15 мин.
В общем, не вариант.
1 Zhuravlik
 
27.10.11
16:50
+ Блокировка(0) тоже не помогает.
2 filh
 
27.10.11
16:54
ну как вариант, записывай и если удачно, то отменяй проведение.
3 andrewks
 
27.10.11
16:58
"Если во время отмены проведения началась транзакция"

это как? оно и так в транзакции выполняется
4 Zhuravlik
 
27.10.11
17:06
(3) Знал, что кто-нибудь мимо этого высказывания не пройдет) Я сам толком не понимаю, но получается что отмена проведения не вызывает транзакции. Если бы вызывала, то моя процедурка тут работала, верно?
(2) Нет, хочу 100% вариант. Если бы Записать() возвращала флаг, что документ записан, как в провести() тогда можно было бы... Можно нагородить функцию, типа

Функция Записать(док)
Попытка
док.Записать();
Возврат 1;
Исключение
записать(док);
конецПопытки;
КонецФункции


Но не хочется городить, если только это единственно возможный вариант...
5 filh
 
27.10.11
17:12
зачем так сложно

Процедура ВОбходТранзакций(Док, Действие)
 Попытка
   Если Действие = "Отменить" Тогда
     ВОбходТранзакций(Док, "Записать")
     Док.ОтменитьПроведение();
   КонецЕсли;
 Исключение
//здесь процедурка с таймаутом...

   ВОбходТранзакций(Док, Действие)
 КонецПопытки;
КонецПроцедуры
6 andrewks
 
27.10.11
17:13
делаю примерно так

   
   КолвоПоп=3;
   Для СчПоп=1 По КолвоПоп Цикл
       Попытка
           //тут делаем свои грязные дела
           Прервать;
       Исключение
           // неудача
           Если СчПоп<КолвоПоп Тогда
               Предупреждение("Не удалось создать документ, попытка будет повторена через 5 сек.",5);
           ИначеЕсли СчПоп=КолвоПоп Тогда
               Сообщить("Не удалось создать документ","!");
           КонецЕсли;
       КонецПопытки
   КонецЦикла;
7 Zhuravlik
 
27.10.11
17:15
(5) через секунду сам до этого дошел)
(6) Да у меня примерно то же самое, просто у вас КолвоПоп, а у меня рекурсия на процедуру. Но если док попадает на транзакцию, то дальнейшая рекурсия просто вываливает ошибку, что документ заблокирован, и капут(
8 filh
 
27.10.11
17:16
даже если потом транзакция отпускается?
9 Zhuravlik
 
27.10.11
17:17
(8) вот именно...
10 andrewks
 
27.10.11
17:17
(7) 2. нифига подобного. у тебя нагромождение попыток получается, а у меня одна.
+ немаловажный фактор - правильный sleep
11 filh
 
27.10.11
17:19
(10) а как попытка влияет на транзакцию?
12 Zhuravlik
 
27.10.11
17:20
(10) Но док-то все-равно заблокирован. Я могу оборвать рекурсию, просто поставлю

Если Док.Блокировка() = 1 Тогда
 Возврат;
КонецЕсли;


Но мне по сути не это надо, а чтобы док распровелся. А он не распроведется, пока я базу не перезапущу.
13 Zhuravlik
 
27.10.11
17:20
(11) Никак. Она просто передает управление на исключение, а там таймаут и рекурсия.
14 andrewks
 
27.10.11
17:21
(11) теоретически никак. кстати, совсем упустил одну тоже немаловажную деталь - время ожидания захвата у меня установлено в ноль. а вот это уже точно влияет
15 КонецЦикла
 
27.10.11
17:21
Нужно ускорять проведение документов и избегать коллапса (как вариант использовать ВК от romix)
Мне в свое время удалось почти уйти от блокировок (при этом кол-во пользователей удвоилось и документостроки выросли)
16 Zhuravlik
 
27.10.11
17:23
(11) Это влияеть на время выполнения может быть, но у меня в данном случае цель - это отменить проведение дока. А только на времени ожидания (высоком?) я не хочу выезжать, тут это не катит. Надо как-то отловить момент конца транзакции..
17 andrewks
 
27.10.11
17:25
(16) попробуй всё-таки время ожидания захвата поставить в ноль у того юзера, под которым обормотка крутится, + делай правильную паузу между попытками, через sleep, или как у меня, через Предупреждение
18 filh
 
27.10.11
17:26
(17) лучше Предупреждение.
19 andrewks
 
27.10.11
17:26
(18) а чем sleep хуже?
20 КонецЦикла
 
27.10.11
17:28
(16) >>Надо как-то отловить момент конца транзакции..

Если не хочешь понимать (15) есть еще вариант проведения всех документов от имени одного пользователя
21 filh
 
27.10.11
17:29
(19) можно нажать и продолжить
:)
22 Zhuravlik
 
27.10.11
17:30
(17) я так пробовал, у меня время ожидания в ноль. Это значит, что действие не будет ожидать конца транзакции, вот и все. Проблема остается. Паузу я делаю так:

       _с = 0;
       СекЖдать = 5;
       Пока СекЖдать>0 Цикл
           ТекущееВремя(ч,м,с);            
           Состояние(" ТаймАут - "+СекЖдать);
           Если с<>_с Тогда
               СекЖдать=СекЖдать-1;
               _с=с;
           КонецЕсли;
       КонецЦикла;
23 filh
 
27.10.11
17:31
уууу, у тебя загрузка проца же будет идти...
24 andrewks
 
27.10.11
17:33
(21) если загрузка роботом - кому оно надо? :)
25 andrewks
 
27.10.11
17:34
(22) вот поэтому и вылетает
26 filh
 
27.10.11
17:36
(24) бывают же моменты, когда ручками запускаем и смотрим :)
Оба метода хороши.
27 Zhuravlik
 
28.10.11
09:38
(25) Только что протестил в копии. Не из-за этого. Поставил такую обработку ожидания -
Процедура Пауза(мс=1000) //пауза в милисекундах
   Если ФС.СуществуетФайл(КаталогПользователя()+"sleep.js")=0 Тогда
       Текст=СоздатьОбъект("Текст");
       Текст.ДобавитьСтроку("WScript.Sleep (250);");
       Текст.Записать(КаталогПользователя()+"sleep.js");
   КонецЕсли;
   WshShell=СоздатьОбъект("WScript.Shell");
   Тек=_GetPerformanceCounter()+мс;
   Пока Тек>_GetPerformanceCounter() Цикл
       WshShell.Run("cscript "+КаталогПользователя()+"sleep.js", 0,-1);
   КонецЦикла;
КонецПроцедуры

(взято с инфостарта http://infostart.ru/public/18698/)

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

Объект заблокирован.
28 andrewks
 
28.10.11
09:41
(27) ну а время ожидания захвата в ноль поставил, или нет?
29 Zhuravlik
 
28.10.11
10:07
(28) Да. Оно и так стоит в 0 у меня постоянно.
30 Zhuravlik
 
28.10.11
10:21
(21) не роботом. бухи загружают каждый день документы из одной базы в другую, - это то, что я пишу. Плюс есть еще выносная база заявок, оттуда тоже с транзакцией 2-3 раза в день выгружаются в доки.