Функция LOCK через базу данных
-
Всем привет!
Хочу реализовать функцию Lock для многопоточного бота (пока один поток работает со строкой, второй берет следующую). Все было бы просто, если бы использовались ресурсы с параметром одновременных использований = 1. Но у меня используется база данных BAS-а без загрузки в систему ресурсов (потому что много операций с БД, которые гораздо проще делать напрямую с БД, а не через список в ресурсах).
- Я создал отдельную колонку lock в БД
- Я присваиваю lock=process, когда один из потоков начал работать с этой строкой в БД.
- Скрипт работает со строкой 2-5 минут.
- Я присваиваю lock=done, когда поток закончил работу со строкой.
- Другие потоки не берут строки с lock=process.
Проблема в том, что скрипт за эти 2-5 минут работы может сфейлиться во множестве мест (примерно с вероятностью 20%, таков сайт). И у строки остается lock=process (по сути зависает), и строка больше не участвует в работе.
Вопрос: как при фейле потока снимать lock=process со строки? Ну или может не при фейле, но максимально быстро после него. Не могу придумать, буду рад любым подсказкам.
-
@doupiu вроде очевидно весь код в игнор ошибок, при любом исходе сначала разлочить строку, а потом уже выкинуть ошибку если надо
-
@UserTrue звучит неплохо, должно работать, правда придется с десяток if WAS_ERROR навернуть) Спасибо, буду делать
-
@doupiu said in Функция LOCK через базу данных:
@UserTrue звучит неплохо, должно работать, правда придется с десяток if WAS_ERROR навернуть) Спасибо, буду делать
Зачем? Просто все действия из функции Main переместите в созданную функцию, а её вызов оберните в игнор ошибок
-
@Fox а если у меня там уже есть внутри блоки с игнором ошибок? Что произойдет, если поток поймает ошибку в таком действии? Он выйдет из одного игнора ошибок или из всех сразу? Грубо говоря: в игноре ошибок работает вложенность?
-
@Fox а также: если в скрипте настроены куча выходов из него вида if что-то - fail, то я так понимаю игнор ошибок тут не поможет и перед каждым fail нужно снимать lock отдельно. Это я к тому, что решение "обернуть все в один игнор" не 100% рабочее тут)
-
Все как Фокс сказал, оберните в игнор, и снимайте Лок при ошибках, ну и на каждом жёстком выходе тоже надо перед выходом снимать.
И еще - в лок достаточно писать 1 или 0
-
@doupiu said in Функция LOCK через базу данных:
@Fox а если у меня там уже есть внутри блоки с игнором ошибок? Что произойдет, если поток поймает ошибку в таком действии? Он выйдет из одного игнора ошибок или из всех сразу? Грубо говоря: в игноре ошибок работает вложенность?
При ошибки вложенного игнора ошибок сработает самый вложенный, так как в нём произойдёт ошибка, а во внешних ошибки не будет, так как она уже в блоке игнора. Вам проще и быстрее было попробовать самому проверить в BAS
@doupiu said in Функция LOCK через базу данных:
@Fox а также: если в скрипте настроены куча выходов из него вида if что-то - fail, то я так понимаю игнор ошибок тут не поможет и перед каждым fail нужно снимать lock отдельно. Это я к тому, что решение "обернуть все в один игнор" не 100% рабочее тут)
Во первых, в вашем первом сообщении нет упоминаний ни про if, ни про fail, я предложил решение под данные, что вы предоставили. Но даже в этом случае можно выйти из положения, например в текст действия fail поместить кодовое слово (например
%fail%
), а после игнора ошибок в Main поставить условие, если в тексте ошибки присутствует слово%fail%
, то завершить поток с ошибкой не снимая блокировки элемента базы данных
-
@Fox вложенность игнор в игноре работает, да, проверил. Снятие lock настроил после общего блока игнора ошибок + перед каждым fail внутри скрипта. За ночь 300 записей из БД перешли в статус done без зависания в статусе process на ошибках, так что все ок.
Спасибо за советы. Я упомянул в топике узкие места решения "обернуть все в один игнор" не для "поругаться", а лишь для того, чтобы потом люди при поиске смогли найти решение для себя)
-
@doupiu поправка: сброс lock перед каждым Fail не нужен. Кубик "Fail", оказывается, также игнорируется, если обернут в игнор ошибок.