概要
RQ のジョブにはタイムアウトが設定されておりデフォルトでは 180 秒のようです
このタイムアウトは単純にワーカーが実行しているジョブが 180 秒経過しても終了しない場合には強制的にジョブを終了させる設定になります
環境
- macOS 11.7.10
- Python 3.11.6
- rq 1.16.1
挙動を確認するためのスクリプト
ジョブは 190 秒待つようにします
初回はエンキュー時にタイムアウトなしでエンキューして本当にタイムアウトが発生するか確認します
-
vim lib/utils.py
import time
class Message:
def say(self, **kwargs):
print("Start say")
print(kwargs)
time.sleep(190)
print("End say")
-
vim app.py
from datetime import timedelta
from redis import Redis
from rq import Queue
from rq_scheduler import Scheduler
from lib.util import Message
queue = Queue("default", connection=Redis(host="192.168.1.2"))
scheduler = Scheduler(queue=queue, connection=queue.connection)
scheduler.enqueue_in(timedelta(seconds=5), Message().say, msg="hello")
# scheduler.enqueue_in(timedelta(seconds=5), Message().say, msg="hello", timeout=3000)
実行
- pipenv run rq worker
- pipenv run rqscheduler
-
pipenv run app.py
ログ
実際に実行するとジョブの終了時に表示されるメッセージが表示されずに 180 経過してジョブが矯正終了していることがわかります
なお JobTimeoutException で終了したジョブはリトライなどはされませんでした
08:39:14 default: say(msg='hello') (c97f39f8-c197-43ac-828f-245d78ef78f0)
Start say
{'msg': 'hello'}
08:42:14 [Job c97f39f8-c197-43ac-828f-245d78ef78f0]: exception raised while executing (say)
Traceback (most recent call last):
File "/Users/user/.local/share/virtualenvs/python-try-aR_k1rUJ/lib/python3.11/site-packages/rq/worker.py", line 1431, in perform_job
rv = job.perform()
^^^^^^^^^^^^^
File "/Users/user/.local/share/virtualenvs/python-try-aR_k1rUJ/lib/python3.11/site-packages/rq/job.py", line 1280, in perform
self._result = self._execute()
^^^^^^^^^^^^^^^
File "/Users/user/.local/share/virtualenvs/python-try-aR_k1rUJ/lib/python3.11/site-packages/rq/job.py", line 1317, in _execute
result = self.func(*self.args, **self.kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/user/data/repo/python-try/lib/util.py", line 8, in say
time.sleep(190)
File "/Users/user/.local/share/virtualenvs/python-try-aR_k1rUJ/lib/python3.11/site-packages/rq/timeouts.py", line 63, in handle_death_penalty
raise self._exception('Task exceeded maximum timeout value ({0} seconds)'.format(self._timeout))
rq.timeouts.JobTimeoutException: Task exceeded maximum timeout value (180 seconds)
timeout=3000 にして再度試す
コメントにしていた部分を変更して再度エンキューしてみます
今度はジョブのタイムアウトを 3000 秒にしてエンキューします
すると先ほどタイムアウトしたジョブがタイムアウトせずにちゃんと最後まで実行されることが確認できました
08:52:14 default: say(msg='hello') (91aab157-25a5-44b9-898b-4da6dcb3baff)
Start say
{'msg': 'hello'}
End say
08:55:24 default: Job OK (91aab157-25a5-44b9-898b-4da6dcb3baff)
08:55:24 Result is kept for 500 seconds
最後に
ジョブの実行時間が長くなりそうな場合にはエンキュー時に timeout を設定してあげましょう
0 件のコメント:
コメントを投稿