Вежливый таймаут
Все, кто работают с руби, рано или поздно попадают на какую-нибудь статью, рассказывающую почему никогда и ни при каких обстоятельствах нельзя использовать Timeout::timeout
. А я хочу поделиться другим подходом к таймаутам.
Когда нам потребовалось выполнять некоторые действия в цикле, но не дольше определенного времени, у нас появился маленький, но очень полезный гемчик. Суть его проста — небольшой объект, у которого можно спросить “а не пора ли нам сворачиваться?”. Такой вот мягкий, добрый, рекомендательный таймаут-консультант, если сравнивать его с уничтожающим всё Timeout::timeout
из стандартной библиотеки ruby.
На днях мне опять потребовалась такая “вежливая” логика при работе в цикле и, вспомнив про наш гем, я решил использовать его и заодно поделиться им в заметке. Перед написанием я проверил — а всё ли там нормально в репе, чтоб не стыдно было показать друзьям? А там… А там используется Time.now для измерения интервалов времени! Но мы ведь уже тёртые калачи, наученные горьким опытом виртуализации, контейнеризации и прочими современными вещами и сразу видим проблему. Ведь так?
А проблема вот в чём: обычные функции, которые возвращают “время” подвержены как скачкам вперёд, так и назад. Скачки вперёд, я думаю, не будут вызывать удивление — остановили (suspend) виртуалку, потом включили — тут и скачёк. А вот скачки назад, хоть и имеют ту же природу (ntp сервер откатил нас назад на 19 секунд), но оказывают гораздо более разрушительное воздействие. Оказывается, есть даже Международная служба вращения Земли, не говоря уже о волшебной добавляемой вручную Дополнительной секунде…
В общем в процессе написания заметки пришлось сделать пару комитов, найти статью чтоб прикрепить её, и вообще пройти интересный путь по просторам википедии. Кстати, следующее собрание по поводу необходимости “дополнительной секунды” запланировано на 2023 год.