Имя: Пароль:
1C
1С v8
Выполнение кода одним потоком
,
0 AlexSTAL
 
22.01.19
11:43
Подскажите по архитектуре

Есть справочник, назовём его "Оборудование".
По факту это реальное удалённое оборудование, которое генерирует у себя набор информации.
По необходимости пользователь должен забирать в 1С данные с конкретного оборудования.
Для этого вызывается процедура общего модуля с параметром Оборудование.
Разными способами (http, smb и т.д.) с оборудования данные забираются, анализируются, записываются в виде Документа в 1С.
Занимает это 3-10 секунд.

Задача сделать так, что бы если другой пользователь запустит обновление с таким же оборудованием, то процедура не выполнилась

Смотрел Фоновые задания, там есть Ключ, но он действует только для конкретного пользователя

Думал про управляемые блокировки Регистра сведений, но в этом случае нет возможности же определить, что именно заблокировано и не ждать снятия блокировки и повторного выполнения процедуры обновления
1 seevkik
 
22.01.19
11:45
регистр сведений в который пишется статус текущего(последнего) действия?
2 SUA
 
22.01.19
11:46
Просто запись регистра сведений.
Оброрудование (опционально Пользователь).
Запрос на получение данных - добавить запись если ее нет
Фоновое задание отработало - удалить запись
3 AlexSTAL
 
22.01.19
11:47
а если вылетит 1С, то регистр сведений никто не обновит... или в транзакции?
4 Вафель
 
22.01.19
11:50
можно делать

СправочникОбъект.Заблокировать()
5 AlexSTAL
 
22.01.19
11:57
(4) думал, но не красивый вариант
6 ДенисЧ
 
22.01.19
12:01
(5) Наоборот, это очень красивый вариант
7 AlexSTAL
 
22.01.19
12:04
(7) А как быть с обновлением элемента справочника при РБД ?
8 JeHer
 
22.01.19
12:08
(7) Если Объект.ОбменДанными.Загрузка Тогда...
9 AlexSTAL
 
22.01.19
12:10
(8) Не, наоборот, объект заблокирован и не сможет обновится.
Подумал, нет, там в элемента очень много полей, которые меняются. Блокировать не хочется
10 Garykom
 
гуру
22.01.19
12:15
11 AlexSTAL
 
22.01.19
12:20
(10) Отличная ссылка! Как красиво реализовать в 1С?
12 Garykom
 
гуру
22.01.19
12:21
(11) Вынести наружу из 1С и не страдать херней
13 AneJIbcuH
 
22.01.19
12:24
14 Garykom
 
гуру
22.01.19
12:25
Если же хочется именно в 1С, то заводи справочник "БлокировкиОборудования", создавай там элементы по числу разного оборудования и при начале процессе забора даннх пиши в него "ВремяНачалаБлокировки".

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

И зная среднее время получения данных для каждого оборудования (с неким запасом) и ВремяНачалаБлокировки и текущее время можно понять что нечто повисло или закрылось не сняв семафор.
15 Garykom
 
гуру
22.01.19
12:31
(14)+ Хм еще некие идентификаторы сеанса туда можно чтобы знать кто сча данные получает и/или кто все время виснет
16 AlexSTAL
 
22.01.19
12:40
В общем всё решил сам на основе глобального метода ЗаблокироватьДанныеДляРедактирования с параметром "ключ записи независимого регистра сведений".
Проверил, работает даже в фоновых заданиях
17 rozer76
 
22.01.19
13:16
(0)

>>Смотрел Фоновые задания, там есть Ключ, но он действует только для конкретного пользователя

хорошо смотрел ?

ФоновоеЗадание (BackgroundJob)
Ключ (Key)
Использование:

Только чтение.
Описание:

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

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

Сервер, толстый клиент, внешнее соединение, мобильное приложение(сервер).
18 rozer76
 
22.01.19
13:17
+ (17) быть уникальным среди активных фоновых заданий, имеющих такое же имя метода, как и у данного фонового задания
19 rozer76
 
22.01.19
13:19
+ (18) вот передавай ключ и проверяй

Функция УжеВыполняетсяФоновоеЗаданиеПоИдентификатору(КлючФО) //roz 29.05.2018
    НайденныеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(Новый Структура("Ключ", КлючФО));
    Если НайденныеЗадания.Количество() = 0 Тогда
        Возврат Ложь;
    КонецЕсли;
    Задание = НайденныеЗадания[0];
    Если Задание.Состояние = СостояниеФоновогоЗадания.Активно Тогда
        Возврат Истина;
    КонецЕсли;  
    Возврат Ложь;
КонецФункции
20 AlexSTAL
 
22.01.19
13:21
(17) не только хорошо смотрел, но и пробовал
21 Ёпрст
 
22.01.19
13:23
как в (4) самый простой вариант. Работает всегда.
22 Ёпрст
 
22.01.19
13:24
Блокировать можно любой элемент справочник, любого справочника. Хоть элемент справочника валюты (который не обновляется)
23 Ёпрст
 
22.01.19
13:24
Это просто семафор
24 rozer76
 
22.01.19
13:28
(20)знач они могли быть неактвными, тогда неуникальность допускается
25 AlexSTAL
 
22.01.19
13:28
(21) Вариант в (16) работает ещё лучше
26 AlexSTAL
 
22.01.19
13:30
(24) вы попробуйте...
27 rozer76
 
22.01.19
13:30
(25) он не лучше, просто для уф делали метод а (4) всегда работает
28 rozer76
 
22.01.19
13:32
(26) да чего пробовать ... работает 100% а как ты думаешь если регл задание выполняется в этот же момент может выполняться оно же или с одинаковым ключем?
29 AlexSTAL
 
22.01.19
13:33
(28) У регламентного задания свои ключи
30 rozer76
 
22.01.19
13:38
(29) нет, вот  "Ключ используется при запуске фонового задания на основе регламентного задания"


РегламентноеЗадание (ScheduledJob)
Ключ (Key)
Использование:

Чтение и запись.
Описание:

Тип: Строка.
Прикладной идентификатор. Для регламентных заданий уникальность ключа не требуется. Ключ используется при запуске фонового задания на основе регламентного задания. В этом случае проверяется уникальность ключа для всех активных фоновых заданий, связанных с регламентными заданиями, имеющими одинаковый объект метаданных. Другими словами, уникальность ключа проверяется в пределах объекта метаданного регламентного задания. Если условие не выполняется задание не запускается. Возможность чтения и записи доступны только для администратора.

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

Сервер, толстый клиент, внешнее соединение.
31 AlexSTAL
 
22.01.19
13:52
(30) проверить - 2 минуты, создайте:
Парам = Новый Массив;
Парам.Добавить(ВыбОборудование);
Задание = ФоновыеЗадания.Выполнить("МойОбщийМодуль.ФоновоеВычисление", Парам, "Test1", "Тестовое задание");

В ФоновоеВычисление поместите:

ВремНач = ТекущаяДата();
Пока ТекущаяДата()-ВремНач <= 30 Цикл
КонецЦикла;

откройте 2 сеанса и попробуйте... в рамках 1 сеанса будет сообщение об ошибке повторного запуска, в рамках разных они с одним ключём будут выполняться параллельно. Это даже в универсальной консоли видно будет