三十路SEの学び記録とかなんとか

子育て中三十路SE♂の業務外での学びとかガジェットネタとか

予約サイトから空き情報を定期的に取得しslackに通知する

再開してからだいぶ間が開いてしまいました。     

今回の内容は、railsのジョブをheroku上で稼働させて、とある予約サイトから情報を取得してその内容をslackに通知するというものです。     

slackは仕事のチームで使っているとかではなく、個人でRSSリーダーやこういった通知のために利用しています。仕事でも使いたい。。    

f:id:us_key:20180809175027p:plain

目次

動作環境

  • Ruby 2.3.0p0
  • Rails 5.0.7
  • slack-notifier 2.3.2

railsでタスクを作る

ひとまずrails newRailsアプリケーションを生成した後、ジョブ実行するためのrakeファイルを作成します。

$ rails new schedulerSample

$ rails g task scheduler

slack通知する

slack-notifier

railsからslackにメッセージを送るためのgemslack-notifierというのがあるため、gemfileに追加してbundle installしておきます。

# Gemfile
gem 'slack-notifier'

slackの設定

以下にアクセスしてslackにAPPを作成します。 Slack API: Applications | Slack

開いた画面で「Create New App」を押します。 f:id:us_key:20180809122009p:plain

アプリケーションの名前を適当に決めて入力し、ワークスペースを選択して「Create App」を押します。 f:id:us_key:20180809122103p:plain

「Incoming Webhooks」を押します。 f:id:us_key:20180809122106p:plain

「Activate Incoming Webhooks」を「On」にします。 f:id:us_key:20180809122111p:plain

すると下の方に説明やら何やらが出てくるので、「Add New Webhook to Workspace」を押します。 f:id:us_key:20180809122114p:plain

確認画面が出てきます。投稿先をChannelやDirect Message先の中から選択し、「許可する」を押します。 f:id:us_key:20180809122119p:plain

リダイレクトされた画面の下の方に説明と合わせてWebhook用のURLが表示されます。これを後で使います。 f:id:us_key:20180809123505p:plain

rakeタスクの実装

今回空き情報を取得する予約サイトは、とあるパスに配置されているjsonを取得してその内容を表示しているというものです。
なのでそのjsonを取得し、rails上でslackに通知する内容に編集します。

先ほど作ったrakeタスクを編集します。

# /lib/tasks/scheduler.rake
namespace :scheduler do
end

生成された状態はこんな感じ。namespaceというのはタスクをまとめる単位ってところです。
この中にタスクを書いてあげます。

# /lib/tasks/scheduler.rake
namespace :scheduler do
  task :test do
    require 'net/http'
    require 'uri'
    require 'json'

    notifyMsg = ""

    notifier = Slack::Notifier.new("https://hooks.slack.com/services/hogehoge") #hogehogeの部分は生成されたWebhook URLに合わせて変えてください

    uri = URI.parse('https://hogehoge.json') #取得するjsonのURLを指定

    msg = ""

    json = Net::HTTP.get(uri)
    result = JSON.parse(json)

    #jsonの取得結果を編集してmsgに詰める…

    notifier.ping(msg)
  end
end

ここまでできたらローカルで動作確認してみます。

$ rake scheduler:test

想定通りにslackに通知が飛べばOK。

heroku schedulerからタスクを起動する

herokuへのデプロイ

ローカルでherokuコマンドが使用できるようになっている前提で。。
作成したrailsアプリをgit管理したうえで、heroku createでheroku上にアプリを作成します。

$ git init
$ git add .
$ git commit -m "first commit"

$ heroku create schedulersample

そして、herokuのリポジトリにpushしてアプリをデプロイします。

$ git push heroku master

と、ここでエラーが発生。

remote:  !
remote:  !     Failed to install gems via Bundler.
remote:  !     Detected sqlite3 gem which is not supported on Heroku:
remote:  !     https://devcenter.heroku.com/articles/sqlite3
remote:  !

herokuでサポートされていないsqlite3がgemfileに含まれていたからでした。
今回はデータベースを使わないので、gemfileの該当部分をコメントアウトします。
(herokuでデータベースを使う場合は、productionでは別のデータベースのgemを指定します)

bundle updateしたうえで再度herokuにデプロイします。

$ bundle update
$ git add .
$ git commit -m "gemfile revised"
$ git push heroku master

さて、デプロイはできましたがこれだけではまだ定期実行してくれません。 herokuでスケジューラの設定をします。

heroku schedulerの設定

herokuに作成したアプリケーションにaddonを追加します。

$ heroku addons:add scheduler:standard

$ heroku addons:open scheduler

開いた画面で「Add new job」を押します。
f:id:us_key:20180809173025p:plain

実行するタスクの内容(ローカルで実行したのと同じコマンド)、FREQUENCY(Daily/Hourly/every 10 minutesから選択)、次回の実行時間を指定し、「save」を押します。 f:id:us_key:20180809173409p:plain

ジョブの稼働時間が課金対象になりますが、簡単な処理であれば複数稼働していても無料範囲(クレジット登録ありで月1000時間)を超えることはないと思います。
今回のような内容であれば1回の稼働での処理は数秒で終わるので、1時間おきに稼働させたとして1日あたり数分、1か月で数時間ってところかなと。
(もちろん処理内容によるのでログを確認するなどしてください。)

まとめ

ということで、heroku schedulerを使うと簡単にrailsでジョブスケジューラが組めるよという内容でした。
もちろん複雑なスケジュールを組むには別の方法を採る必要があるかもしれませんが、個人で実装するような簡単な内容ならこれで十分かなと感じます。
クローリングなんかにも使えそうですね。

参考

qiita.com

qiita.com