|
Как организовать очередь фоновых заданий? | ☑ | ||
---|---|---|---|---|
0
ssalikoff
06.04.22
✎
07:44
|
При наступлении некоего события нужно запустить фоновую обработку на сервере.
Однако, если событие снова произойдёт до окончания работы фоновой обработки, то нельзя запускать её второй экземпляр, а поставить в очередь и запустить только после окончания работы текущего экземпляра обработки. Думал это решить с помощью регламентных заданий, у них, действительно, есть поле Ключ, который не позволит одновременно выполняться двум заданиям. Но мне нужно, чтобы не просто блокировался запуск задания, а гарантировался его запуск, когда это станет возможным. Как это сделать? |
|||
1
xkanix
06.04.22
✎
07:49
|
Посмотреть как сделана очередь заданий во фреше (в любой типовой которая есть во фреше).
|
|||
2
ssalikoff
06.04.22
✎
07:51
|
(1) А можно поточнее указать куда смотреть? Допустим, пусть для примера это будет БП 3.0. Где там очередь заданий?
|
|||
3
xkanix
06.04.22
✎
07:59
|
(2) Подсистема АдминистрированиеСервиса -> ОчередьЗаданий
|
|||
4
xkanix
06.04.22
✎
08:02
|
В исправление к (3) - основное в ТехнологияСервиса -> ОчередьЗаданий (то что раньше написал это UI подсистема, в ней совсем не всё).
|
|||
5
ssalikoff
06.04.22
✎
08:13
|
(4) Посмотрел. Хрень какая-то. В общих модулях ОчередьЗаданий* одни функции-заглушки. Никакого реального кода.
Можно объяснить, в чём суть методики? |
|||
6
rozer76
06.04.22
✎
08:20
|
А проще почему нельзя? РЗ с минимальным интервалом обрабатывает очередь
|
|||
7
ssalikoff
06.04.22
✎
08:24
|
(6) не понял, что вы хотели сказать. Можно ещё раз, для не самых сообразительных?
|
|||
8
Serg_1960
06.04.22
✎
08:30
|
ТелепатБот :) Вам предложили создать регламентное задание, которое будет обслуживать очередь экземпляров фонового задания.
|
|||
9
rozer76
06.04.22
✎
08:31
|
(7) событие - в очередь, РЗ разбирает ее с минимальным интервалом
|
|||
10
xkanix
06.04.22
✎
08:36
|
(5) Да, действительно.
Видимо решили выпилить код от БТС, а на фреше его как-то добавляют (через расширение, например - так, конечно, и обновлять) проще. Ну тогда - прошу прощения. Без "Библиотека технологии сервиса" видимо смотреть реализацию негде. |
|||
11
ssalikoff
06.04.22
✎
08:39
|
(9) Идею понял. Хотя как-то это не очень красиво.
Некрасиво, что приходится что-то писать в базу данных, а потом оттуда постоянно читать. Хотелось бы что-нибудь поизящнее. |
|||
12
lEvGl
гуру
06.04.22
✎
08:48
|
если задание имеет склонность не успевать отрабатывать до следующего запуска, то есть теоретическая вероятность "бесконечного цикла", когда ожидающие задания будут накапливаться, как следствие - сервер в ужасе. это произойдет из за Обязательного запуска следующего по расписанию задания. этого можно избежать, если пропускать те запуски, которые должны были произойти в момент уже работающего предыдущего задания, не запускать их принудительно. ну а чтобы определить работает сейчас какое то задание или нет, хранить признак запущенного задания все равно где то придется. храните в файле, если в базе не хотите :)
|
|||
13
ssalikoff
06.04.22
✎
08:59
|
(12) Хотелось бы хранить это в оперативной памяти сервера. Или как-то оповещать работающее задание, чтобы оно перезапустилось после завершения. Но, по-видимому, в рамках архитектуры 1С это невозможно. Буду делать, как мне посоветовали выше
|
|||
14
Serg_1960
06.04.22
✎
09:16
|
Ох и любите вы всё усложнять :)
Фоновое задание (например, "ОчередьЗаданий"), реализующее очередь из запущенных экземпляров фонового задания, общается с ними, например, через механизм сообщений. При начале работы очередной экземпляр сообщает ОчередьЗаданий чтобы его включили в очередь и ждёт разрешения на продолжение исполнения от ОчередьЗаданий; получив разрешение, продолжает работу и сообщает о своём завершении в ОчередьЗаданий. ОчередьЗаданий обрабатывает сообщения от экземпляров, "двигает" очередь, разрешает работать первому в очереди; автоматически завершает свою работу при исчезновении очереди. Очередной экземпляр, перед началом работы, проверяет наличие ОчередьЗаданий и запускает её при необходимости. Виртуальная очередь может быть реализована в виде хранения в памяти (можно в хранилище) любой структуры (например, массив)... Как то вот так :) |
|||
15
ssalikoff
06.04.22
✎
12:33
|
(14) вот это непонятно: «общается с ними, например, через механизм сообщений». Как можно что-то сообщить фоновому заданию, и как можно организовать бесконечный цикл ожидания внутри фонового задания?
|
|||
16
Serg_1960
07.04.22
✎
09:11
|
(15) Для общения между фоновыми заданиями, например, можно использовать СообщениеПользователю() и ПолучитьСообщенияПользователю(). Только не надо забывать их удалять перед завершением работы фонового задания. Иначе юзверь будет чиать их чат :)
Для реализации простой очереди ожидания завершения работы предыдущего экземпляра, можно использовать ПолучитьФоновыеЗадания() с отбором по ИмяМетода и Состояние. Найти последний запущенный экземпляр и через ОжидатьЗавершение() - поставить на паузу текущий экземпляр. Не совсем в тему, есть ветка с обсуждением нечто подобного - Завершение фонового задания |
|||
17
ProgAL
07.04.22
✎
10:47
|
Фоновые = ФоновыеЗадания.ПолучитьФоновыеЗадания();
Для Каждого Фоновое из Фоновые Цикл Если Найти(Фоновое.Ключ, "имя вашего задания, которое можно посмотреть в консоли заданий") > 0 И Фоновое.Состояние = СостояниеФоновогоЗадания.Активно Тогда Предупреждение("Фоновое задание еще выполняется."); Возврат; КонецЕсли; КонецЦикла; |
|||
18
rudnitskij
07.04.22
✎
16:55
|
(17) на сервере "Предупреждение"? Оригинально
|
|||
19
ProgAL
07.04.22
✎
18:56
|
Это был клиентский код.
|
|||
20
ДедМорроз
07.04.22
✎
22:15
|
А зачем запускать еще раз?
Просто пишем то,что нужно в регистр,а задание перед завершением проверяет,а не нужно ли чего ещн сделать. Если задания нет,то запустить новое. Очередь нужна там,где есть не одно задание,а пул. |
|||
21
Serg_1960
08.04.22
✎
09:22
|
(20) Если не забывать о многопользовательском режиме работы и связанной с этим асинхронности событий, то может возникнуть ситуация, при которой в момент завершения задания произойдёт запись в регистр. Первый процесс завершает работу задания, второй - не вызывает новое так, как старое ещё не завершилось.
|
|||
22
ДедМорроз
09.04.22
✎
15:41
|
А блокировки вамина что?
Задание перед завершением также ставит блокировку на регистр,читает,а не нужно ли что сделать,и если не нужно сообщает,что закончено. После этого,любой желающий перед запистю задания в оегистр также ставит блокировку,и,если записано,что задания нет,то пишет,что он создал новое и запускает его. Тогда два сразу не запустятся. |
|||
23
ssalikoff
09.04.22
✎
22:44
|
(16) А я и не знал, что СообщениеПользователю() работает на сервере. Теперь знаю.
|
|||
24
ДедМорроз
09.04.22
✎
23:00
|
(23) оно и в фоновом задании работает и потом их даже можно получить.
По крайней мере,всю нотификацию о работе фоновых заданий очень успешно через сообщения делать. |
|||
25
ssalikoff
09.04.22
✎
23:43
|
(24) А вот получит ли фоновое задание сообщение через ПолучитьСообщенияПользователю() от другого фонового задания, запущенное в другом сеансе? В справке явно об этом не сказано. Вообще, идеологически, кажется, что доступ к чужим сообщениям не должен предоставляться.
|
|||
26
Serg_1960
09.04.22
✎
23:51
|
(22) Sorry, имхо, Обращение к базе; организация режима ожидания установки/снятия блокировки; чтение/запись... использование регистра, в данном конкретном случае, имхо, не эффективно и не оптимально.
|
|||
27
ДедМорроз
10.04.22
✎
00:18
|
(25)получит прекрасно.
Я даже для передачи команд использовал отдельное фоновое задание,чьи сообщения читали целевые. Там единственная проблемамв том,что без удаления они очень быстро накапливаются,а с удалением - не все их получают. Что касается блокировки,то лучше использовать константу и просто ставить на нее блокировку,когда мы делаем что-то критичное,в частности,запуск задания или его завершение,а писать задания можно и без блркировки,если мы изначально идентификаторы писателям раздали,чтобы их пространства не пересекались. Есть еще вариант с "хвостом". Когда задание выходит на состояние "нечего делать",то оно ставит в регистр это состояние и дату его установки и ждет в течение какого-то времени,проверяч,что новых заданий не появилось,а когда процесс ставит задание и видмт предыдущее в состоянии ожидания,он использует блокировку,чтобы исключить уход задания из жизни в момент постановки новой задачи. |
|||
28
ssalikoff
10.04.22
✎
12:57
|
(27) Спасибо за науку. Возьму на вооружение этот метод. Жаль, что это на уровне платформы не поддерживается, приходится пользоваться подобными «костылями»
|
|||
29
vi0
10.04.22
✎
13:12
|
(0) а для чего эта очередь, и какой длины она допустима?
что за задача решается? |
|||
30
ssalikoff
11.04.22
✎
01:00
|
(29) Когда на склад поступает товар, срабатывает триггер и образовавшиеся свободные остатки начинают распределяться согласно заранее заданным правилам по заказам клиентов, по разным резервам для отделов. Это распределение может работать несколько минут, и если в это время произойдет другое поступление, то схема «ломается», если позволить запустить параллельное задание по распределению. Нужно чтобы распределения работали монопольно, строго последовательно
|
|||
31
vi0
11.04.22
✎
03:19
|
(30) а для чего именно очередь? в триггере хранится какая то уникальная для события информация, или только сам факт что событие произошло?
почему нельзя, чтобы триггер писал куда-то инфу о факте события, а одно рег задание, например, раз в минуту например опрашивало бы наличие и обрабатывало бы его? |
|||
32
ssalikoff
11.04.22
✎
03:40
|
(31) да, в триггере есть специфическая информация, передаваемая в качестве параметра фоновому заданию
|
|||
33
vi0
11.04.22
✎
03:50
|
(32) и пиши ее в регистр сведений, организуй очередь там
почему ты не хочешь бд использовать? а если сервер зависнет и перегружать надо будет? откуда будешь восстаналивать инфу от тригеров? я смотрю в (6) тебе уже советовали подобное |
|||
34
ssalikoff
11.04.22
✎
03:52
|
(33) Потому что писать что-то в базу данных и потом регулярно оттуда считывать — это плохая, некрасивая идея. В (16) мне посоветовали куда более красивое решение, которым я и воспользовался.
|
|||
35
rphosts
11.04.22
✎
03:55
|
(0) сделай регулярно запускаемый (например раз в 3 сек) процесс который будет диспетчеризировать очередь фоновых.
|
|||
36
ssalikoff
11.04.22
✎
03:57
|
(35) Каждые три секунды запускать процесс — кажется мне плохим советом. Выше было предложено красивое решение через ПолучитьСообщенияПользователю() и ОжидатьЗавершение()
|
|||
37
rphosts
11.04.22
✎
04:11
|
(36) >Фоновое задание (например, "ОчередьЗаданий"), реализующее очередь из запущенных экземпляров фонового задания,
непрерывно выполняемое? Оно загрузит на около 100% 1 ядро процессора сервера. Имхо, про красоту вам только кажется: процесс занявший одно ядро и процесс регулярно получающий управление и если нет в нём нужды возвращающий управление серверу. >Выше было предложено красивое решение через ПолучитьСообщенияПользователю() и ОжидатьЗавершение() Это только инструмент, также можно в РС писать, можно в Справочник - у каждого из вариантов есть свои плюсы и минусы. |
|||
38
vi0
11.04.22
✎
04:25
|
(34) "Потому что писать что-то в базу данных и потом регулярно оттуда считывать — это плохая, некрасивая идея"
откуда такие мысли? |
|||
39
vi0
11.04.22
✎
04:27
|
(38) + всё решают цели задачи, требования, имеющиеся ресурсы
считывать раз в минуту одну запись регистра, это такой мизер |
|||
40
vi0
11.04.22
✎
04:35
|
подобным образом через регистр работает движок многопоточки от Евгения Павлюка
https://habr.com/ru/post/255387/ https://github.com/wizi4d/TaskManagerFor1C |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |