51139


バックグラウンドのバッチ処理を rails (のサブセット: ActiveRecord などのみ使う) で記述しています。結果、
`Application#load_tasks` により `bundle exec rake`
コマンドでバッチをコマンドで実行できる状態になっていたとします。

この時に、バッチのメインループを、失敗しようが成功しようが、ある一定のインターバルを挟んだ上で、ひたすらループしたいと考えています。これは、どう実現するのがベストでしょうか?

似たようなことを実現する上で、有名なツールとして `whenever` がありますが、これは cron
による定期実行をサポートするツールであって、「秒単位でインターバルを指定しながらひたすらループしたい」という今回やりたいことは満たせないと思っています。

また、同じ系統のツールたちに、 もろもろの job queue (active_job でサポートされるような) がありますが、 redis
を前提としているものが大半であったりして、わりと、オーバーキルな気がしています。

運用でどうにかするという観点では、現在では以下のように tmux session と shell script を組み合わせています。

[code]

    tmux new-session -s セッション名 -d 'while true; do 実行したいコマンド; sleep インターバル; done'
    
[/code]

ただ、この方法は、なんというかあまり rail
にのっかっていないというか、ちょっと気をつかわないと上手く動かなかったりするので、これをよろしくやってくれるライブラリなどがあれば知りたいな、と思っています。


CC BY-SA 4.0
2018-05-08T14:36:56.830
43874
2019-02-08T03:03:16.517
754
question
ruby-on-rails ruby
rails (ruby) で forever 的なことがやりたい際のベストプラクティス


> バッチのメインループを、(中略)ひたすらループしたいと考えています。

この部分がよくわからなかったので見当違いの回答だったらすみません。

単純に無限ループするrake taskを作ってはだめでしょうか?

run_forever.rake

[code]

    namespace :my_task do
      desc "run forever"
      task 'run_forever' do
        loop do
          Rake::Task["main"].invoke
          sleep 10
        end
      end
    end
    
[/code]

実行

[code]

    $ bundle exec rake my_task:run_forever &
    
[/code]

> 失敗しようが成功しようが

というのは例外を吐くかどうか、ということでしょうか?  
それならmain rake taskで例外をキャッチしてしまえば良いと思います。


CC BY-SA 4.0
2018-07-13T15:46:22.123
45588
2018-07-13T15:46:22.123
28630
43874
answer


タスクをデーモン化する場合、プロセスの起動・停止やクラッシュ時に再起動してくれるプロセス管理ツールを使うことになると思うんですが、Rubyなら[eye](https://github.com/kostya/eye)、Pythonなら[Supervisor](http://supervisord.org/)あたりでしょうか。後者はクセ強めですが多機能です。

cronとデーモン化はどちらも設定が必要なのと、一長一短あるので、用途に応じて使い分けてはいかがでしょうか。

  * cron: 定時実行したい時。古いバッチプロセスが残っていようがお構いなしに新たなプロセスを発火するので、バッチの処理量や完了時間があらかじめ予測できない場合は古いプロセスが積み上がってサーバのリソースが枯渇するリスクあり。
  * デーモン化: プロセスを常時起動したい時。無限ループを使えばステップ・バイ・ステップで実行できるので古いプロセスの積み上がり考慮する必要が無い。ただし常時起動であるが故に自前のコードや依存ライブラリにメモリリークが発生しているとサーバのリソースを緩やかに枯渇させる。そしてメモリリークのデバッグは難しい :)


CC BY-SA 4.0
2018-07-31T15:40:07.763
47140
2018-07-31T15:40:07.763
32
43874
answer


  * 対象のバッチ処理を Sidekiq のジョブとして定義したのちに、 sidekiq-scheduler で定期実行
  * sidekiq 自体は foreman export で、対象サーバーのサービスとして登録

に最終的に落ち着きました。


CC BY-SA 4.0
2018-12-12T06:15:42.310
51139
2019-02-08T03:03:16.517
2019-02-08T03:03:16.517
754
754
43874
answer