Digdagを用いてRubyOnRails環境でバッチ実装

# Digdagについて
[Getting started](https://qiita.com/amagasu/items/92ad70c33f73ab613d08)
[Architecture](https://qiita.com/amagasu/items/572075dcc8b3c8640072)
[Concepts](https://qiita.com/amagasu/items/c850db3b564a7d6dc99c)
[Workflow definition](https://qiita.com/amagasu/items/2a8b84ac8fb4da2d9968)
[Scheduling workflow](https://qiita.com/amagasu/items/9f47a34884ba06d93264)
[Operators](https://qiita.com/amagasu/items/1f9b26a71c86fc9d4607)
[Language API -Ruby](https://qiita.com/amagasu/items/b11527d92d259bd3ab48)
[Digdagで環境毎に設定値を変える（RubyOnRails）](https://qiita.com/HavenSpring/items/bb1c7fbae9175c1f9479)
[Digdagを用いてRubyOnRails環境でバッチ実装](https://qiita.com/HavenSpring/items/b3c3e26ef868f8d5eaf4)

# 準備
Ruby on Rails チュートリアルのサンプルアプリケーションダウンロード
https://github.com/yasslab/sample_app

Ruby on Rails チュートリアルのサンプルアプリケーションを実行して、ユーザーとPostを登録。
ぼくはtestユーザーを作って４つの投稿を登録しました。
![スクリーンショット 2020-07-20 19.01.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108475/2b8af674-0f51-de83-2727-e9969b81429e.png)

今回は、ユーザー名をパラメーターにして該当するユーザーの投稿数を出力する簡単なバッチを作ります。
バッチの実装・起動は二つの方法でやってみます。


Railsでバッチ処理を書く際によく使われている以下の二つの方法をやってみます。
①rails runner：スクリプトとしてバッチを書く
■メリット
Rubyのスクリプトなので自由度が高い
■デメリット
Railsの環境を毎回読み込むので若干遅い
バッチの置き場所が決まってない

②rake task：ビルドタスクとしてバッチを書く
■メリット
namespaceメソッドを使ってグループ化ができる
taskの置く場所がきまっていて迷わない
■デメリット
処理の行数が長くなるとつらい
引数の渡し方に癖がある
一時的に使用するバッチの置き場所に困る

## 概要
Digdag: スケジュール、Alert、メインタスクだけ登録

![batch-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108475/cc940879-d38f-3a68-ee32-c17b68cd523b.png)

# rails runnerで実行
パラメーター取得は[OptionParser](https://docs.ruby-lang.org/ja/latest/class/OptionParser.html)を使いました。


## バッチ処理スクリプトを追加
```/lib/scripts/``` の配下にバッチ処理スクリプトを追加

```rb:lib/scripts/post_batch.rb
require 'optparse'

module Scripts
  class PostBatch
    def initialize
      @option = {}
      OptionParser.new do |opt|
        opt.on('-n VALUE', 'user name') { |v| @option[:name] = v}
        opt.parse!(ARGV)
      end
    end

    def count
      user = User.find_by(name: @option[:name])
      puts "ID: #{user.id} 名前： #{user.name}"
      puts "投稿数： #{Micropost.where(user_id: user.id).count}"
    end
  end
end
```

lib配下のrubyファイルを自動ロードする

```rb:config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
```

## workflowsの配下にrails_runner.digを追加して以下の内容を追加

```rb:rails_runner.dig
+task:
  sh>: bundle exe rails runner Scripts::PostBatch.new.count -n 'test'
```

## 実行
testユーザーのID,名前、投稿数が出力されています。

```rb:実行結果
$ digdag run rails_runner.dig --rerun
2020-07-20 19:38:39 +0900 [INFO] (0017@[0:default]+rails_runner+task): sh>: bundle exec rails runner Scripts::PostBatch.count 'test'
ID: 5 名前： test
投稿数： 4
```

# rakeで実行
## rakeタスク生成

```rb:
$ rails g task task_post
Running via Spring preloader in process 4255
      create  lib/tasks/tast_post.rake
```

```/lib/tasks/task_post.rake``` ファイルが生成されるので開いて以下のソースを追加


```rb:lib/tasks/task_post.rake
namespace :task_post do
  desc "ユーザー投稿数を取得"
  task :count, ['name'] => :environment do |task, args|
    user = User.find_by(name: args.name)
    puts "ID: #{user.id} 名前： #{args.name}"
    puts "投稿数： #{Micropost.where(user_id: user.id).count}"
  end
end
```

## Workflow追加

```rb:rake.dig
+task:
  sh>: bundle exec rake task_post:count[test4]
```

## 実行
testユーザーのID,名前、投稿数が出力されています。

```rb:実行結果
$ digdag run rake.dig --rerun
2020-07-20 20:04:16 +0900 [INFO] (0017@[0:default]+rake+task): sh>: bundle exec rake task_post:count[test]
ID: 5 名前： test
投稿数： 4