light log

学んだこととか

Heroku上のTwitter botを修正した

昨日作ったツイッターに自動投稿するbotだけど、動きがおかしかったので修正した。

(それにしても最近やる気が出ないことが多い。。いわゆる五月病だろうか)

問題

想定では、Heroku Schedulerを使って毎朝8時に一度だけ投稿するようにしたつもりだったが、8時以外にも何度か投稿されていた。

原因

想定していた8時ちょうどにも投稿はされていて、Schedulerの設定はうまくいっている様子。

問題は余分な投稿の原因。

heroku logsでログを確認すると、何度もstateがstarting -> up -> crashedと移り変わっていて、毎回startingのタイミングで投稿されているように見える。

要は、Procfileにツイートを投稿するスクリプトの起動コマンドが書いてあって、stateがstartingになるたびにそのコマンドが実行されている。

実はこれは昨日から気持ち悪いと思っていて、最初はProcfileに実行可能なタスクの一覧を定義して、その中から定期実行したいタスクを選んでSchedulerで指定するイメージでいたら、Schedulerでも直接スクリプトの起動コマンド(Procfileに定義したのと同じもの)を指定することになって、「じゃあProcfileは不要なのでは?」となっていた。

今日調べたら、Procfileで指定しているのはProcess Typesというもので、これらは常時動いているデーモン的なもののようだ。このプロセスタイプごとに割り当てるdynoの数を制御できる。

Process Types and the Procfile | Heroku Dev Center

The Process Model | Heroku Dev Center

で、じゃあ今回のような、毎朝一回ツイートを投稿するだけで、他の時間は何も実行している必要がないアプリ場合、Procfileはどうしたらいいんだろうと思ったけど、たぶんそういう場合のやり方は無いのだろう。そもそもWebアプリのプラットフォームだし。

対策

だとしたらダミーでもなんでもいいからWebアプリを作るしかない。

昨日も示した以下のページでも、sinatraを使ってリクエストがあったら文字列を表示するだけのインデックスルートを用意している。昨日は意味なさそうだし不要そうと思って無視したけど、そういうことだったのか。

Herokuを使って1日1回名言をツイートするTwitter Botの作り方 - アインシュタインの電話番号

ということで、上のページに倣ってsinatraをGemfileに追加して、なんか適当にこういうやつを作る。

require 'sinatra'

get '/' do
  'hello world'
end

で、Procfileはこのプログラムを起動するコマンドに変える。

web: bundle exec ruby app.rb -p $PORT

Schedulerで指定しているコマンドは変更しない。

これでコミットしてgit push heroku masterする。

……動かない。

heroku psすると、何もプロセスが起動していない様子。昨日のProcfileではプロセスの名前をbotとしていて、botに1 dyno割り当てる形になっていたので、それが変わったのが原因かと思って、

$ heroku ps:scale web=1

としてwebに1割り当ててみたら無事動いた。

まとめ

ダミーを使って無理矢理実現しているのは多少気持ち悪いけど、まぁ仕方ないかなという気はする。

下手にハマったせいでherokuの基本的なイメージがだいぶつかめた気がする。そうそう、この機会にドットインストールのheroku講座も見てみた。ある程度調べたあとだったからあんまり学びはなかったけど。最初に見とけばよかった。

Heroku入門 (全12回) - プログラミングならドットインストール

あとは五月病さえなんとかなれば完璧。