uWSGI でファイルが更新された時にリロードする

最初は inotifyx 使って自力で書こうとしてたんだけど,ブロックしてうまくいかなかったりして,thread でも立てなきゃいけないのかなと思って uwsgidecorators を読んでたら,そもそも uwsgidecorators (というかそもそも uwsgi-core) にファイル更新検知機能がついてた。

メインとなる wsgi ファイルが main.wsgi というファイル名だったとして,監視するモジュール((別モジュールだてにしなくてもいい (main.wsgi に入れ込む) のかもしれないけど追ってない追記: やってみたら別モジュールに独立させなくてもうまくいった。小さい捨て WSGI スクリプトであればリロードのロジックを入れ込むのが楽。(もちろん,WSGI アプリケーションとして独立させるなら入れ込まないほうがいいけど) )) watcher.py は:

# watcher.py
import uwsgi
from uwsgidecorators import filemon

@filemon('main.wsgi')
def reloaded(num):
    uwsgi.reload()

対応する uWSGI のパラメータは,たとえば:

; uwsgi.ini
[uwsgi]
master = true
plugins = python,http
http = :8000
wsgi-file = main.wsgi
import = watcher

ファイルがいっぱいあったらどうすんねーんと思うかもしれないけど,@filemon デコレータは,ディレクトリの監視もできます。

ちなみに内的には inotify 機構を使っているので無駄はないはず。IN_ALL_EVENTS レベルの監視をしてるんで,touch とかしてもちゃんとリロードされます。



あと今回の話と関係ないけど,たとえば 1 分間リクエストがなかった場合にワーカーを自動的に kill するには

idle = 60

のようにしておけばよい。uWSGI 使うようなシチュエーションでそんなにメモリをケチるシーンはないかもしんないけど。

追記: idle (や lazy) と @filemon の相性はよくないかもしんない。ワーカーがいない状態で編集してリクエスト投げたら編集前の内容だったことがあった。気のせいかもしれないけど。


もういっこわりと便利なオプションは harakiri

harakiri = 60

のようにしておくと,処理に 60 秒以上かかるワーカーは強制的に落とされます。