Имя: Пароль:
1C
1С v8
Запись данных "вне транзакции"
0 alexei366
 
26.03.15
11:10
Представим есть у нас допустим web-сервис, в нем 2 метода:
1) Первый запускает мега алгоритм который отрабатывает в среднем скажем за 5 минут.
2) Второй метод должен получать процент выполнения первого.

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

Столкнувшить с подобной задачей я у себя сделал запись в рег сведений через фоновое задание.
А кто что ещё предложит? (запускать фоновое задание для обновления процента выполнения мне не очень нравиться)
1 GROOVY
 
26.03.15
11:15
Временное хранилище не нравится?
2 alexei366
 
26.03.15
11:16
(1) Ты понимаешь что это у нас два разных сеанса?
3 vde69
 
26.03.15
11:16
файл лога, там и по событиям можно разделять
4 alexei366
 
26.03.15
11:17
(3) Что за файл лога? Ты про ЖР?
5 vde69
 
26.03.15
11:17
да
6 alexei366
 
26.03.15
11:19
(5) Да это ещё хуже чем через доп фоновое задание по моему мнению, да и засорять его тоже не хочу.
7 Господин ПЖ
 
26.03.15
11:21
пиши у журнал винды
8 mehfk
 
26.03.15
11:21
ЕМНИП, запись во внешний источник данных происходит вне транзакции. Попробуй сделать финт ушами - подключи собственный регистр сведений в качестве внешнего источника данных.
9 vi0
 
26.03.15
11:22
зачем тебе именно фоновое задание? почему нельзя в самом алгоритме писать в РС?
у тебя 8.3 со снапшотом?
10 mehfk
 
26.03.15
11:23
(8)+ не лучше все-таки собственный регистр сведений так не подключать - будет плохо.
11 alexei366
 
26.03.15
11:27
(9) "Потомучто гладиоус")))
Если мы делаем изменения в транзакции то другой сеанс наши изменения увидет только после её фиксации , то есть 2 метод будет возвращать:

0% 0% 0% 0% 0% 0% 0% 0% 0% 0% ... 0% 0% 100%
12 vi0
 
26.03.15
11:28
(11) ты про 8.3 ответь сначала
13 alexei366
 
26.03.15
11:28
(8) Финт ушами конеш имеет некий смысл, но нужно будет про него помнить, вдруг сервер поменять захотим , сделать копию базы и т.д, всеж слетит нафиг
14 alexei366
 
26.03.15
11:29
(12) Что ты конкретно имеешь ввиду про "снапшот"?
15 vi0
 
26.03.15
11:32
(11) кстати, почему фоновое задание у тебя может получить процент, а веб-сервис нет?
16 alexei366
 
26.03.15
11:35
(15) Фоновым заданием я его записываю/обновляю, оно запускается из первого метода. Видать неверно меня ты понял.
17 vi0
 
26.03.15
11:54
откуда у тебя фоновое задание получает данные? или пишет значения так, от балды, с учетом того что алгоритм 5 минут выполняется?

если у тебя режим изоляции транзации предполагает грязное чтение, то и читай данные из любого объекта 1с в который можно писать самим алгоритмом, но тема эта неустойчивая, т.к. если переведешь на 8.3 со Read Commited Snapshot то грязного чтения там уже не будет

а самое простое, да может быть ЖР использовать, если он у тебя в формате sqlite, правда не по назначению будет использоваться, некрасиво

еще - транзакция 5 минут - это много, хотя у тебя может быть и особый случай допускающий

в общем, пока больше вопросов чем ответов
18 alexei366
 
26.03.15
12:00
(17) Это придуманная задача, мог написать и 10 минут и 20 не суть.

Объяснение: Начался выполняться первый метод, в его контрольных точках (так скажем каждые 5%) запускается фоновое задание чтобы обновить "вне транзакции" запись регистра и вписать туда текущее состояние выполнения в процентах. Соответственно другой сеанс опрашивает регистр и тянет из него процент по выполнению первого метода
19 vi0
 
26.03.15
12:02
(18) у тебя работает все? чем тебе не нравится?
20 alxbzm
 
26.03.15
12:03
(16) Первым методом запускаешь фоновое задание.

Фоновое задание в процессе своей работы периодически вызывает
Сообщить("Готово Х%")

Во втором методе через менеджер фоновых заданий находишь нужное, которое в данный момент выполняется, вызываешь для него ПолучитьСообщенияПользователю(Истина), в полученном массиве ищешь последнее сообщение - в нем и есть текущий процент выполнения этого задания.
21 ДенисЧ
 
26.03.15
12:04
я извращался со сторонней sql-базой... В которую писал процесс выполнения...
22 ДенисЧ
 
26.03.15
12:05
(20) "находишь нужное, которое в данный момент выполняется"
а если их пять, которые выполняют алгоритм над разными данными? )
23 alxbzm
 
26.03.15
12:05
(22) "НайтиПоУникальномуИдентификатору()"
24 alxbzm
 
26.03.15
12:06
+(23) хотя да - идентификатор надо еще определить... надо подумать ))))
25 alexei366
 
26.03.15
12:10
(20) Да это я видел в типовом функционале как 1С делает, но мне чот не очень это нравиться что приходиться через сообщения работать.
26 alexei366
 
26.03.15
12:11
(20) Ну и если мы представим что у нас не запускается фоновон задание, а все происходит в рамках web-соединения, тогда непокатит наверно
27 alexei366
 
26.03.15
12:13
(19) Мне не нравиться что на каждое обновление требуется запускать фоновое задание, а это типа время ресурсы (читал что если используется кластер с несколькими серверами то назначение для выполнения фонового задание на каком-либо из них может занять чутли не пару секунд)
28 vde69
 
26.03.15
12:14
предлагаю красивое решение, цените :)

заводим справочник со 100 предопределенными элементами

в первом потоке запросом выбираем N элементов с признаком "ДляИзменения"

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

100 элементов = 100%
29 alexei366
 
26.03.15
12:14
(22) Да этот вопрос решаем через какойнить ключ.
30 vi0
 
26.03.15
12:26
(28) даже в качестве шутки не прокатит
там будет ожидание 20 сек
31 vi0
 
26.03.15
13:05
(25) скажи, где именно в типовом видел такое?
32 alexei366
 
26.03.15
13:05
(28) А если я при этом хочу и инфу другую кроме 100%, не не очень
33 vde69
 
26.03.15
13:27
(30) не будет... вот пример где это реально работает http://infostart.ru/public/18951/
34 fisher
 
26.03.15
13:33
(0) Я бы просто не в базу писал, а в файлик.
35 alexei366
 
26.03.15
15:19
(34) не файлик не вариаент
36 vi0
 
26.03.15
15:50
(33) и где там?
37 vde69
 
26.03.15
16:02
(36) там по блокировкам определяется ход и игрок...
38 vi0
 
26.03.15
16:03
(37) но там нет того, что ты описал в (28)
39 vde69
 
26.03.15
16:05
(38) там абсолютно то-же, только справочники другие..., я так например делал аську...
40 vi0
 
26.03.15
16:08
(39) не, ты используешь метод Заблокировать
а в (28) ты про запрос говоришь
41 vde69
 
26.03.15
16:23
(40)ты совершенно прав, я не использую метод "заблокировать"... в этом вся фишка...
42 vi0
 
26.03.15
16:27
(41) чет я тебя не пойму
скажи в каком модуле в какой строке ты используешь этот метод
43 ssh2006
 
26.03.15
16:50
(41) автоматические блокировки и запрос с ДЛЯ ИЗМЕНЕНИЯ?

Должно ведь быть ожидание при попытке прочитать таким запросом
44 Гёдза
 
26.03.15
16:50
А зачем блокировать, не проще ли реквизит изменять?
А то вдруг блокировка повиснет?
45 vde69
 
26.03.15
16:50
(42) точно нету там... видно я чего-то переделал....

сейчас так

Функция ПроверитьАктивностьИгрока(Игрок) Экспорт
    Результат = Ложь;
    Объект =Игрок.ПолучитьОбъект();
    попытка
        Объект.Заблокировать();
    Исключение
        Результат = Истина;
    КонецПопытки;
    
    Возврат Результат;
КонецФункции
46 Гёдза
 
26.03.15
16:51
(44) Хотя нет, туплю
47 Гёдза
 
26.03.15
16:52
С блокировками не стоит забывать по эскалацию блокировок.
А она может возникнуть в самый неподходящий момент
48 ssh2006
 
26.03.15
16:58
(45) понятно, объектная блокировка
49 FN
 
26.03.15
17:00
(0) любое внешнее хранилище данных.
Файл, sql, значение в реестре винды, переменная окружения ОС и тд тп.
50 Dmitrii
 
гуру
26.03.15
17:09
В БСП в общем модуле ДлительныеОперации

// Регистрирует в сообщениях информацию о ходе выполнения фонового задания.
//   В дальнейшем эту информацию можно считать с клиента при помощи функции ПрочитатьПрогресс.
//
// Параметры:
//  Процент - Число  - Необязательный. Процент выполнения.
//  Текст   - Строка - Необязательный. Информация о текущей операции.
//  ДополнительныеПараметры - Произвольный - Необязательный. Любая дополнительная информация,
//      которую необходимо передать на клиент. Значение должно быть простым (сериализуемым в XML строку).
//
Процедура СообщитьПрогресс(Знач Процент = Неопределено, Знач Текст = Неопределено, Знач ДополнительныеПараметры = Неопределено) Экспорт
   ПередаваемоеЗначение = Новый Структура;
   Если Процент <> Неопределено Тогда
     ПередаваемоеЗначение.Вставить("Процент", Процент);
   КонецЕсли;
   Если Текст <> Неопределено Тогда
     ПередаваемоеЗначение.Вставить("Текст", Текст);
   КонецЕсли;
   Если ДополнительныеПараметры <> Неопределено Тогда
     ПередаваемоеЗначение.Вставить("ДополнительныеПараметры", ДополнительныеПараметры);
   КонецЕсли;
   ПередаваемыйТекст = ОбщегоНазначения.ЗначениеВСтрокуXML(ПередаваемоеЗначение);
   Текст = "{" + ИмяПодсистемы() + "}" + ПередаваемыйТекст;
   ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Текст);
   ПолучитьСообщенияПользователю(Истина); // Удаление предыдущих сообщений.
КонецПроцедуры

// Находит фоновое задание и считывает из его сообщений информацию о ходе выполнения.
//
// Возвращаемое значение:
//   Структура - Информация о ходе выполнения фонового задания.
//       Ключи и значения структуры соответствуют именам и значениям параметров процедуры СообщитьПрогресс().
//
Функция ПрочитатьПрогресс(Знач ИдентификаторЗадания) Экспорт
   Перем Результат;
   Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
   Если Задание = Неопределено Тогда
     Возврат Результат;
   КонецЕсли;
   МассивСообщений = Задание.ПолучитьСообщенияПользователю(Истина);
   Если МассивСообщений = Неопределено Тогда
     Возврат Результат;
   КонецЕсли;
   Количество = МассивСообщений.Количество();
   Для Номер = 1 По Количество Цикл
     ОбратныйИндекс = Количество - Номер;
     Сообщение = МассивСообщений[ОбратныйИндекс];
     Если Лев(Сообщение.Текст, 1) = "{" Тогда
       Позиция = Найти(Сообщение.Текст, "}");
       Если Позиция > 2 Тогда
         ИдентификаторМеханизма = Сред(Сообщение.Текст, 2, Позиция - 2);
         Если ИдентификаторМеханизма = ИмяПодсистемы() Тогда
           ПолученныйТекст = Сред(Сообщение.Текст, Позиция + 1);
           Результат = ОбщегоНазначения.ЗначениеИзСтрокиXML(ПолученныйТекст);
           Прервать;
         КонецЕсли;
       КонецЕсли;
     КонецЕсли;
   КонецЦикла;
   Возврат Результат;
КонецФункции
51 alexei366
 
26.03.15
17:30
(50) Это уже было сказанно, что типовыми методами делают через сообщить пользователю. Но такой подход мне кажеться какимто кривым, но с другой стороны с текущими возможностями наверно один из лучших
52 vhl
 
26.03.15
17:37
(51) Чем он кривой? Довольно удобно, пока не будет пуш-уведомлений, другие методы с записями в базу или файл - еще хуже.
53 alexei366
 
26.03.15
17:57
(52) А теперь представь что выполняется метод, а его результат хотят мониторить несколько пользователей, первый сообщения заберет и все)
54 fisher
 
26.03.15
18:00
А почему файлик не подходит, я не совсем понял?
55 Dmitrii
 
гуру
26.03.15
18:08
(53) > первый сообщения заберет и все)

Доработай, чтобы не забирал или чтобы забрав последнее сообщение из массива снова сообщал.

ИМХО, любые варианты с записью куда-либо (в журнал, файл, регистр или другу таблицу БД) - гораздо более кривой способ
56 alexei366
 
26.03.15
18:16
(54) Ну опять же представим маловероятную ситуацию:
Имеем сеть кластеров 1С, база одна, на каждом кластере выполнена публикация.
Первый пользователь запустил мега процедуру на web-сервисе, второй хочет наблюдать за процессом, и как ты уже догадался обращаться они будут "по условиям задачи" к разным кластерам, то есть компы будут разные а общего сетевого каталога у нас нет.

Просто хочу универсального стабильного решения.
57 alexei366
 
26.03.15
18:17
(55) ага и как я по твоему в сеансе смогу сообщить от имени фонового задания?
58 Господин ПЖ
 
26.03.15
18:22
(56) пиши в базу скульную рядом

зы а vde69 про блокировки элементов справочника - не работает?
59 vde69
 
26.03.15
18:31
(56) правильным с точки зрения 1с будет использование хранилища данных или ЖР, кстати именно такой вопрос у них в тестах есть :)
60 alexei366
 
26.03.15
18:44
(59) Что ты имеешь ввиду под хранилищем данных?
61 alexei366
 
26.03.15
18:45
(58) "пиши в базу скульную рядом " ты имеешь ввиду на прямую к SQL подрубаться? Если так то это уже обсуждалось
62 К_Дач
 
26.03.15
20:25
Может не совсем быстро будет, но как вариант:

Заводим константу "почта для проверки процента".

В ключевых точках функции, завернутой в транзакцию (через 5%), шлем на почту сообщения. Другой сеанс регулярно проверяет почту и выводит результат.

Из недостатков - требуется наличие поднятого почтового сервера в сети, либо может быть не очень быстро, если почта просто на интернетовском ресурсе
63 vi0
 
26.03.15
20:33
(62) или через смс)
64 zulu_mix
 
26.03.15
20:39
а параметры сеанса тоже в транзакции работают?
65 alexei366
 
26.03.15
20:46
(64) Сначало задайся вопросом как получить параметр сеанса из другого сеанса
66 alexei366
 
26.03.15
20:47
(62) Эт точно несовсем)
67 Dmitrii
 
гуру
26.03.15
20:49
(57) Согласен. Про "сообщить повторно" я загнул.
Однако никто не заставляет удалять все сообщения.
Можно удалять их перед завершением работы фонового задания.

Впрочем я не настаиваю. Нравиться вам писать/читать через какие-то промежуточные таблицы/константы/файлы - ради бога.
68 zulu_mix
 
26.03.15
20:50
(65) а с чего ты взял что у тебя новый сеанс будет? дернул сервис - он фоновое запустил если в параметре сеанса пусто. иначе возвращает значение параметра. как только отработало фоновое - возвращает хмл. после приема хмл шлешь туда тикет и очищаешь параметр.
69 alexei366
 
26.03.15
21:10
(67) Ну да можно и не удалять впринципе. Вариант не плохой (да и в типовых так сделанно), но не нравиться мне через сообщения
70 alexei366
 
26.03.15
21:11
(68) Ты все продумал.
Есть два сеанса (просто сеансы или фоновые без разницы, это все сеансы), первый чтото делает, второй хочет узнать скоко он сделал, и как в этой ситуации применить параметры сеанса?
71 alexei366
 
26.03.15
21:12
(68) "Ты все продумал" был вопрос*
72 zulu_mix
 
26.03.15
21:14
(71) а ты проверял что у тебя новый сеанс запускается в этом случае?
73 alexei366
 
26.03.15
21:17
(72) Я тя плохо понимаю:
Есть сервер с кластером SQL базой и IIS с публикацией.
Есть два клиенстких компа.
Один делает запрос к web-сервису на первый метод, который чото делает долго.
Со второго клиентского компа мы обращаемся к другому методу web-сервиса который должен нам вернуть процент выполнения первого.
То есть имеем два сеанса (уж поверь).
Надеюсь щас объяснил доходчиво
74 zulu_mix
 
26.03.15
21:19
я думал ты с одного компа теребонькаешь сервис чтоб определить когда он завершится
75 alexei366
 
26.03.15
21:20
(74) Да даже если с одного компа, сеанса то всеравно 2, я пример с двумя привел чтоб те понятней стало что я имею ввиду
76 zulu_mix
 
26.03.15
21:21
еще раз переспрошу - ты уверен что будет 2 сеанса?
77 alexei366
 
26.03.15
21:44
(76) Даж не знаю как тебе ещё объяснить.
Да уверен
78 vde69
 
26.03.15
22:14
(77) а я вот не уверен, все зависит от прослойки...

например я делал web сервер который работал в одном сеансе 1с при множестве внешних сеансах...

но если автор задает такой вопрос - то скорее всего это типовой механизм и сеансы разные...
79 alexei366
 
26.03.15
23:33
(78) Что значит внешние сеансы?
80 vde69
 
26.03.15
23:48
(79) сеансы к веб серверу...
81 alexei366
 
27.03.15
00:19
(80) Ок ты себе программный код представляешь чтоб в твоих "внеш сеансах" на "один сеанс" была возможность обмена параметрами не считая таблицы базы данных?

И вообще объясни чем "внешние" сеансы отличаются от обычных
82 fisher
 
27.03.15
11:02
(56) Согласен. Если закладываться на кластер - файлики не вариант. Внешняя БД или разделяемые файлы - это усложнение инфраструктуры. Родная БД - проблема с записью вне транзакции. Фоновое задание решает, но не оптимально. ЖР - тоже не оптимально. Чисто сервисными записями его засорять не хотелось бы. ЖР удобно использовать для ведения лога действий пользователя. Сообщения пользователя  в фоновом задании - удаляются при вычитке. Т.е. нет стабильности получения данных прогресса из параллельных сеансов.
Мда... Дилемма.
Лично я всё-таки озаботился бы отдельным сервисом для подобных задач. Это не единственная задача, где удобно оперировать какими-то служебными данными не через родную БД.
Поднял бы внешнюю БД и прописал её в источниках данных. Или там папочку разделяемую завел для кластера. Или и то и другое для разных классов задач.
83 vhl
 
27.03.15
11:31
(53) ПолучитьСообщенияПользователю() - так сложно сделать чтоли? И никто ничего не заберет. Нормально у нас так работает - любой может получить сообщения этого фонового задания. Без всяких внешних sql-таблиц, журналов, писем и смс.
84 vhl
 
27.03.15
11:33
(82) >Сообщения пользователя  в фоновом задании - удаляются при вычитке
Блин, вы бы хоть документацию почитали, прежде чем советовать...
85 tridog
 
27.03.15
11:47
(0) Из того, что есть в платформе - вариант с фоновым заданием наименее мерзкий. И нормально работающий.
86 fisher
 
27.03.15
12:34
(84) Посыпаю голову пеплом. Но если не удалять - тоже не очень хорошо выходит. Их может накопиться достаточно много, а вычитывать каждый раз придется все.
87 alexei366
 
28.03.15
00:37
Можно конеш совместить 2 варианта: Фоновое задание "Сообщает", а сеанс который забирает сообщения удаляет а результат последнего в регистр сведений, если в след раз обращается к фоновому а там сообщений нет то берет из регистра
Кaк может человек ожидaть, что его мольбaм о снисхождении ответит тот, кто превыше, когдa сaм он откaзывaет в милосердии тем, кто ниже его? Петр Трубецкой