読者です 読者をやめる 読者になる 読者になる

パルカワ2

PerlとRubyとイチャラブ

手動で実行するバッチ処理を書く。

決まった時間に実行するなどは、基本的に自動化されるが「一度しか実行されないもの」または「何度も実行するが、いつ実行されるか決まっていない」場合は自動化したくてもしようがない。なので、手動で実行する。

一度しか実行しないバッチは、「データベースのカラムを追加、変更したのでデータを追加/修正したい」など。
何度も実行するバッチは、「問題が発生した場合、ユーザーに対する補填(いわゆる詫び石付与)」などが考えられる。

そして、この2つのバッチの対象者は、多い場合と少ない場合がある。

実行のオプションを付けない限り、dryrun

人間なのでついうっかり本番で動かしちゃったとかあるので、それを防止する。
動かそうと思って動かすのと動かすつもりがなくて動くのは全然違う。

スクリプトファイルにベタでコードを書かない

例えばPerlだと.plにコード書くのはあまりしなくて、.pmに分けたりする。
そうすることで、テストのしやすさを向上させて、テストを書く障壁を低くする。

rakeタスクでもテストは書けるけど、moduleにしたほうがサクサク書けるよねというイメージ。
http://robots.thoughtbot.com/test-rake-tasks-like-a-boss

tmux上で実行する

別にtmuxでなくてもよくて、sshしてバッチ動かしたけどコネクションが切れてて途中で止まってましたとか死ねる。マジで
他にはscreen, nohupとかです

途中で止めない

実行してる途中で止めるとめんどいので、完走させてから考えるとよいです。
考えるためには、なんでコケたのか理解する必要があり、以下に書いた「エラーのログをファイルに取る」「変更のログをファイルに取る」をする必要があります。

エラーのログをファイルに取る

エラーが起きたらログを取ります。
printして満足するのではなくて、ちゃんと後から参照出来るようにファイルなりなんなりに落とし込みます。
fluentdに投げてアレコレするでも良いと思います。

変更のログをファイルに取る

エラーが起きずとも変更が起きたログを取ります。
変更のログは、前に書いたカスタマーサポートで活用出来る、行動ログ - パルカワ2と同じような感じで書くと良いとおもいます。

実行完了したら通知する

実行したら通知するようにしておきます。
growlとかそんなめんどいことはしなくて、IRCに通知します。
それでバッチが終わったら、エラーがないかなど確認します。

普通、通知系のメソッドなりがプロジェクトにあると思う。

MyApp::Notify::IRC->finished_batch_script;

みたいな感じでやると決まった文言が投稿されるという風にしておくと、IRCでハイライトしやすいのでオススメです。

あと実行結果をnopasteに貼って、そのURLをIRCに通知するとかしたことあるけど、実行結果がめちゃくちゃ大きくなってnopasteが悲鳴をあげるみたいな事あるので注意が必要です。

実行条件の洗い出し

  • この時間以外で動いてほしくない
  • 2回実行してほしくない

動いてほしくない状態というはわりかしあるので、それを防止する。

毎回トランザクションを張らない

ユーザー一人ひとりのデータを更新する必要があって、
一人ひとりトランザクション張って更新していくのはあまりにだるいので、100人単位とか1000人単位とかで区切る。

一気に全ユーザーを取得しない

ユーザーが50万人にいるサービスで、ユーザー全部を取ってきて、DBICやらActiceRecordのインスタンスを作ると死ぬのは容易に想像できる。
ActiveRecordには、find_in_batchesというのがあって、まあなんかよしなにしてくれるらしいのでそれ使いましょう。

追記

大事です

まとめ

そんな感じで気をつけることがたくさんあってバッチはだるいので極力書きたくない。こういう風にまとめても完璧ではない。なので、仕事しないのが一番いいと思いました。