Diary

@ssig33

Heroku でのスケジュールタスクの実行(Rails の場合)

Heroku ではいわゆる cron 的なことをしたい人のために Heroku Schedulerというものが用意されています。

ですがこれはかなり問題の多いプロダクトで、シリアスな業務で用いるにはいろいろと厳しいです。まず設定 UI が非常に貧弱で、設定ミスをしても気付きづらいです。またセッション管理の点にも問題があり、自分がいじってるつもりと別アプリの設定をいじってしまうという事故はわりとよく起きます。

そして最大の問題ですが、公式のドキュメント

Scheduler job execution is expected but not guaranteed. Scheduler is known to occasionally (but rarely) miss the execution of scheduled jobs.

とある通り実行されるかどうかは無保証です。実行漏れは「rarely」だと書かれていますが、実感としてレアかどうかと言われると、ガチャのレアぐらいのレアさだなと思います。ユビレジの場合酷いときはまいにちなにか抜けてリカバリーを開発者が手動でやるなんてことをやってる時期がありました。

そこでドキュメントには

If scheduled jobs are a critical component of your application, it is recommended to run a custom clock process instead for more reliability, control, and visibility.

とありますのでこの行き方でやっていく必要があります。ようするに計時専門の Dyno を立ててそこで自前で cron 的なことをしろってわけ。 Rails の場合 resque-schedulerはよい選択肢です。設定がコードになってリポジトリに入れられるのも非常によい(デプロイターゲットに応じてこのあたりの設定をいじりたいとかなってくると欠点として認識されることもあるかもしれませんが)。

ところで Heroku の Dyno は最大でも 24 時間しか連続起動してくれません。また CLI から restart かけただとかデプロイしたとかで頻繁に再起動されます(ユビレジでは一日数回〜数十回のデプロイが行なわれます、最近ではわりとどこの会社もこんなかんじですよね?)。そうなるとその再起動のタイミングで resque-scheduler がなにかすべきだった!!!みたいなときにデプロイが走ったりすると実行漏れが起きます。体感ですけど heroku scheduler のときの半分ぐらいの頻度でこれらが原因となって実行漏れが起きました。

resque-scheduler はこういうことを想定して作られており

You may want to have resque-scheduler running on multiple machines for redundancy. Electing a master and failover is built in and default.

とあります。 Heroku でこれを活用したいときはわりと話は単純で

heroku scale scheduler=2

とかするだけです。ところが

Precautions are taken to prevent jobs from potentially being queued twice during failover even when the clocks of the scheduler machines are slightly out of sync (or load affects scheduled job firing time).

ともあり、 resque-scheduler を複数プロセス実行している場合に重複実行されるケースがあるようです。今のところユビレジでは重複実行されて致命的な事態となりうるジョブがあまりないためこの問題への対処は手をつけていません。ただしユビレジからのメールが二通届いてしまうなどという事態が稀に生じていることは確認されており、頻度次第ですが今後対処を行なう必要があるとは思います。

対処法としてはアプリ側でもう実行済みかどうか確認してハネるみたいなのが必要でしょう。実はユビレジでは一部のジョブでそれが導入されています。というのも Heroku Scheduler 時代に「1 時間に 1 回のタスクがたまに抜けるなら 5 分に 1 回実行して、アプリ側で重複実行だったら弾けばいいんじゃない?」みたいなのが導入されたからです(なおこれは多重実行されて困る系のタスクではなく、重いので実行されまくると困るというタイプのタスクでした)。

Heroku 公式のドキュメントにも説明あるし、いろいろとツールも揃っているのですが、なかなかこういう話を日本語で見聞したことがないので書いておきました。

25 Dec 2017 Mon 17:03

このサイト HTTPS 対応 + HTTPS 強制にした のだが、いろいろやりかた考えた結果 Cloudflare に金払うのが一番楽ということでそのようになったのだが、完全に Cloudflare に依存する人生という感じで危ないですね。

04 Dec 2017 Mon 16:04

優秀なプレイヤーを管理職にするなとかよく言うけど すくなくとも俺はプレイヤーとして自分よりダメな奴に管理されたくないんだよな。いいコーチはかならずしもいいプレイヤー出身じゃないとかよく言うけど、それは横綱クラスじゃないという話であって幕下の奴がいい親方になるのか?優秀なプレイヤーを十分集めてそのなかから管理職をやりたがっててかつその能力のありそうな奴を管理職にするべきなんじゃないのか。

02 Dec 2017 Sat 14:59

Nahoruru

28 Nov 2017 Tue 22:28

かに

22 Nov 2017 Wed 18:00

CDN 最高

22 Nov 2017 Wed 18:00

と思ったらうまくいくようになった、、、

18 Nov 2017 Sat 16:38

CloudFlare の purge が API 経由でうまくいかなくて困ってる

18 Nov 2017 Sat 16:38

ねむい

17 Nov 2017 Fri 16:18

修正すべきことは多分 1 行とか なんだけど、

  • 問題を理解すること
  • 影響範囲を明らかにすること
  • 分かった影響範囲に対してテストコードや人力 QA の手順を確立させること

みたいなところで膨大なコストがかかる作業をしていて、なんでかまあそれの仕切り役の一人みたいになっている(なぜかといえば職務がそういうことのリーダーシップをとることというようになったからです)。

ここでまあ問題はなにかというと「問題を理解する」のに莫大な手間がかかってしまう原因がなにかといえば、理由はまあいろいろあるんですが、その一つが俺が昔書いたコードがアレというものだからです。

我々は常に過去の自分の影と戦闘することになるのだが、今や我々のチーム力は過去と比べものにならないくらい大きいので、僕以外の人が一番厳しい部分をやってくれている。これはいつ殺害されてもおかしくない状況なので緊張感がある。

16 Nov 2017 Thu 18:36

コーヒー豆の量規定の 2 倍にしたら全然うまくなくて、規定量の正しさを感じる

16 Nov 2017 Thu 17:43

かに

16 Nov 2017 Thu 16:54

Web アプリの非同期処理に goroutine 使う の多分だめだと思うんだけどわりとみんなやってるしもうあんま気にせずやっていくことにしてくという気持ちになってきてる。

失敗してもいい非同期処理ならまあこれでもいいのだろう、、、

16 Nov 2017 Thu 16:50

頭痛い、、、

16 Nov 2017 Thu 16:47

dev.to には勝ってた

このサイトは速い

もう 1 か 2 スコア上げて阿部寛もぶち抜きたい

16 Nov 2017 Thu 02:32

日本の店舗でクレカ普及しないのってリボ払いが普及しないせい で結果としてクレカ会社が儲からないから手数料に転嫁されるせい、というのはみんなよく言ってる。

じゃあリボ払いが普及しなかったのがいいことだったのか?というとそれはどうなんだろう。貧しくて資産がなくても資金繰りさえ回ってればまあ生活はできるわけで。毎月ごとにクレカの支払い方法と借金の借り換えで苦労するアメリカ人みたいなの、大変なんだろうけど、そこでクレカという金融システムがなければ彼らが生活を維持できる時間は格段に短くなる。

市民社会の成立にはそういう金融システムというのは不可欠な要素だと言えるのではないか。では現代日本でクレカとリボ払いという要素が受け入れられなかった結果何が起きたかといえば、ロードサイドに立ち並ぶ質屋であり、そして今雨後の筍のようにボコボコと出てきている怪しげは「フィンテック」アプリであろう。これらが最悪なのが「金融サービスである」という理解をされないまま人々に利用されている点であり、特に「フィンテック」界隈に顕著だが意図的に騙しにかかっていることだ。

「これは借金である」という認識をみんながちゃんと持って、クレカのリボ払いに苦労してる社会の方が今と比べればなんぼかマシだったんではないかと思う。

08 Nov 2017 Wed 16:22

glide 捨てて dep に引越した

30 Oct 2017 Mon 16:30

k8s に転居した(このサイトは Heroku だが)

23 Oct 2017 Mon 23:19

全部クライアントサイド JavaScript で実装されててメモは Google Drive に保存される Markdown メモツール作った。

https://memopad.ssig33.com/

以前から自分専用に使ってたメモツールがあったのだが、これにつかってた MySQL が落ちて、その MySQL の復帰のしかたはメモツールにしか書いてなかったみたいな頓知みたいな事態が起きてキレて作った。

バックエンドを自前のサーバーからクライアントサイド向けの Google の API Library に置き換えるだけなのでわりとシュッと出来てよかった。 React のおかげで本当にこういうのはめちゃくちゃ簡単になった。

HTML と JS は S3+Cloudfront でデプロイしている。これでやってる。

サイトの説明にも書いてるけど、あらゆる機能がクライアントで動くように実装されているのでセキュアかつ動作を検証可能です。

23 Oct 2017 Mon 15:45

salesforce の導入 で厳しい事態みたいな話よく聞くんですけど、まあ原因は二つだろうと思っている。

まず開発環境が厳しいという話。 salesforce と apex をガリガリやってましたみたいな転職希望者と話す機会が多いのだが(というのも働いている会社で salesforce と apex が分かる人を探しているからである)、彼らの希望は一貫している。 salesforce に関わらないこと、をとにかく希望している。

これはまあどうにもならないんだけど金(だけ)で解決する話でもある。金さえあれば apex 書くって人いるでしょ。

もう一つはこれが本質的に超高難易度の SI であるということ。 CRM の導入、メンテというのはそれ即ち経営の最高判断であるはずで、 SIer 出身者であればみんなそんなことは知っている(俺は SIer 出身者ではなくクソ映像業界出身者だ)。しかし、 SI の知識のない人達が、メールは G Suite 使いますみたいな感じであまあまでやって失敗している事例を本当によく見る。

CRM に関する知識と業界の知識と企業特有の業務知識に精通した上で、既存の業務をどのように salesforce 流の業務にコンバートしていくのか。それによって発生する余剰の人員の再配置をどう手当するのか。これらの問題に対処できるのは決断力に優れた経営者だけなのだが、実際には大した権限を与えられていなエンジニアが少ないリソースで作業をして、訳のわからないことになっていく。

19 Oct 2017 Thu 16:21

Slack で大きい絵文字を簡単に作る という遊びがあります。

スクリーンショット 2017-10-10 14.34.53.png

こんなん。画像を 4x4 で 16 枚で分割して

:yos-1-1::yos-2-1::yos-3-1::yos-4-1:
:yos-1-2::yos-2-2::yos-3-2::yos-4-2:
:yos-1-3::yos-2-3::yos-3-3::yos-4-3:
:yos-1-4::yos-2-4::yos-3-4::yos-4-4:

みたいな感じで貼るわけです。

スクリーンショット 2017-10-10 14.34.16.png

とか

スクリーンショット 2017-10-10 14.34.45.png

中身としては 16 枚の絵文字なので適当に差し替えて遊んだりできます。

Kobito.7WlpYO.png

とか。

これを手で作るのはだるいので簡単に作る方法です。

画像の用意についてはこれを読んでください。

そのようにして画像が用意されると、これをアップロードしないといけないのですがこれを手でやるとだるいです。そこで emojipacks という悪魔のツールを使います。

emojipacks は以下のような yaml があれば一括で絵文字を登録してくれるという便利ツールです。

---
title: yame
emojis:
- name: yame-1-1
  src: https://s.ssig33.com/s/7da3f11bcf7a4062b12057a4a884f02b
- name: yame-2-1
  src: https://s.ssig33.com/s/391026804f5943bb8feaad01b1660c84
- name: yame-3-1
  src: https://s.ssig33.com/s/77a642d788a84a3fbc8c9ba4c4d35710
- name: yame-4-1
  src: https://s.ssig33.com/s/7202e75135624c67a09b32edb4e1084b
- name: yame-1-2
  src: https://s.ssig33.com/s/0516e5e9861248b4a348fbfa7dfbdd09
- name: yame-2-2
  src: https://s.ssig33.com/s/ea88903d5567426dbaf49138480f7d6b

こういう絵文字のデータは http でアクセスできるところに存在している必要があります。これを手でやるのはだるいので、適当に画像をアップロードする場所をなんか用意したうえで以下のようなスクリプトを書きましょう。

require 'yaml'
hash = {"title" => 'yame', "emojis" => []}

Dir.glob("sob*").sort_by{|x| x.scan(/d+/).first.to_i}.each_with_index do |s,i|
  x = i % 4 + 1
  y = i / 4 + 1

  src  = upload(s) # この upload メソッドはなんか各自の事情で実装したらいい
  hash["emojis"] << {"name" => "yame-#{x}-#{y}", "src" => src}
end
puts YAML.dump(hash)

あとは emojipacks で登録するだけ。

これを全部一括でうまいところやるようにしてガンガン巨大絵文字を登録できるようにしてもいいとは思うんですけど、まだそこまで自動化してません。

10 Oct 2017 Tue 14:42

Google Home は IFTTT と連携できるので それでオッと思う人は完全に買いだと思います。

Google Home => IFTTT => Webhook => IRKit みたいな感じで家電制御系は勝利していきますし、 Webhook あればまああとはただの Web アプリの世界なのでそこでなんでもできます。 API.AI もまあ楽しいんですが普通に何かする分にはたぶん IFTTT のほうがはるかに楽です。

08 Oct 2017 Sun 11:30

Twitter の凍結について思うこととしては 、これ本当に文化差が問題なんだろうなっていう。自分のまわりで Twitter の凍結でよくあるパターンが「あなたのアカウントは一時凍結されました、異議がある場合は正当性をアピールするメールを送ってください」みたいなあのメールが Twitter からきたときに「どうすればいいですか?教えてください」って返事してそのまま永久凍結になるってやつ。

これ何が起きてるかといえば、 Twitter 社のアメリカ人からしてみれば「正当性をアピールしろって言ってるのに質問で返してきやがったな、ナメてんのかこの野郎」っていう印象になってると思うんですよ。

たぶんここでの正解は「私は Twitter を n 年利用しており、 Twitter での情報発信でコミュニティと Twitter そのものへの貢献をしてきた。問題のある発言と捉えられたものがあるとしてもそれは友人との内輪のやり取りであるはずだ」みたいなのを送ることだろうと思うんですよ。

でもまあ日本人の多くが「正当性のアピール」だの「異議」だのを送れって言われてこうはならないだろうし、結果として即永久凍結ということになる。

02 Oct 2017 Mon 00:01

Go で並列数をうまいところ制御しながら並列に動くクローラー というもののサンプル。

並列に HTTP アクセスしてきてパースして title 要素を表示するというものです。 title 要素をパースしてくるのに使っているパッケージはこちらです。

今回は HTML のダウンロード => パース => 画面への出力処理 までを一塊として並列処理の単位にしています。

ですが、ここをさらに gorutine と channel で制御してダウンロードは 5 並列でやってパースは 20 並列でやって出力は 1 並列でやる、みたいなふうにもできるでしょう。今回は channel を単なるセマフォのように使っていますが、その場合は gorutine 間のやり取りに channel を使う方がシンプルに書けるでしょう(そしてそれがより Go らしいやり方でしょう)。

またダウンロード制御するにあたってホスト名ごとに並列数制御するみたいのもそんなに難しくない(とはいえ実務の上ではこのホスト名とこのホスト名は実は同じインフラに乗ってるので並列数カウントする上で一緒のものとして数えないといけない、とかあったりするのでどうやるにせよ難しさはつきまとうのだが)。

こういうことをやるのに古代人たちはいろいろと苦労したものですが、現代人は結構簡単に並列数を稼ぎつつマルチコアの限界まで遣ってHTML をパースしつつうんたらかんたらやるみたいなクローラーを書けるようになっています。

古代のコード引き継ぐべきかどうかはこういう点についても顧慮してもいいのではないかと思う。

ただ Go はあくまでマルチコアの限界まで使い切るみたいなことは簡単ですが、スケールアウトするという話になってくると途端にどうにもならないのでまあその場合は erlang なんですかね。ただまあクローラーだったら実行ホスト事にクロール対象割り当てればいいだけなので Go でもよさそう。

30 Sep 2017 Sat 16:06

クラスで一番の美人は金正恩の性奴隷になった という記事の眉唾っぷりについて

ポルノ映画を製作したとして罪に問われた歌手ら11人の処刑には、市民1万人が集まった。ヒヨンもその1人だった。「連行される歌手たちは、縛りあげられ、頭にはフード、口に猿ぐつわをはめられた状態で慈悲を乞うことも叫びを上げることも許されない」

最終的に歌手たちは、対空砲の砲弾が尽きるまで撃たれた。ヒヨンはこれを200フィート(約60m)の距離で見ており、その後で気持ち悪くなってしまった。

とあるがそもそもこのニュースそのものがかなり信憑性が低い。射殺された歌手の人数がニュースによって違うし、射殺された女のなかに金正恩の元カノがいたという話があったが、それはデマだという話もあった。

処刑についても裁判から即決で処刑されただとか、公開処刑だったとかで、全く話が定まらない。

また、幹部が対空砲で射殺されたときの様子とされる衛星写真を見ても、郊外の射場で行なわれており 600m の距離に市民 1 万人が集結するとはとても思えない。

なお北朝鮮での対空砲での幹部の処刑は ZPU-4 が使用されているらしい。

ZPU-4

北朝鮮の市民教育における軍事教育の水準がどの程度なのかはよく知らないが、これを見てすぐに「対空砲」だと分かるものなのか?

恐らく AV を密造していた人間が処刑されたという事件自体は実在しているのだろう。しかし、おそらくこの匿名の女性がいうような公開処刑ではなかっただろうし、この女性が目撃したというのは嘘だろう。

このような無意味な嘘をつく理由はいくらでもあるということを我々は Twitter を見ることで知っている。

21 Sep 2017 Thu 16:12

GraphQL について思うこと

という問題がまずある。ヘビーな API コールは想定せずに、 API の型情報を規定して各レイヤーに共有する仕組みとして使うならいいんだろうけど、しかしそれオーバースペックじゃねーかな。

まあなんかいろいろ事情はあるとは思いますが。 URL っていうシステムを捨てるメリットがあるかどうかは、、、

12 Sep 2017 Tue 18:31

秋葉原いくと全然代わり映えのしないパーツショップみたいのが沢山あって まじで意味わからん。いやなんか店ごとに色つけてるよとかあんのかもしれないけど、普通にゲームするために部品買う分にはどこで買ってもかわらないでしょ。

こういうふうに非効率な小規模な販売店が大量に存在するコストというのがどこに現わているかというとそれこそが「ASK 税」なのだった。

本質的には ASK は取引先をある程度の規模の販売店のみに絞り、オペレーションコストを最適化することによって利益を最大化させるはずだ。しかし、なんのかんので秋葉原という街を PC 街として維持するコストは今後も払い続けるつもりではあるようだ。

そのコストをエンドユーザーが負担する理由などなにも無いということに気付いた今、皆が海外通販を利用するようになってしまった。 GPU はともかく CPU は保証もクソもないしね。

ASK としても問題は認識しているだろうし、そもそもスリッパも一部大規模店にのみ重点的に卸すというような行動をとっていた。今後は海外通販との比較の上で価格決定を行なわざるを得ないだろうし、一部大規模販売店への傾斜というのは必然的に強まるだろう。

PC パーツの街としての秋葉原は完全に終了していくものと思われるし、それを寂しいと感じる人ももはやほとんどいないのだろう。

07 Sep 2017 Thu 15:00

redux-api-middleware についてのものすごく表面的な理解

この週末自作 Web アプリに redux と redux-api-middleware を入れるということをやっていた、特に redux-api-middleware はよく理解してなかったので。これまで俺がどうしていたかというと、通信にかんすることは他のコンポーネントにぜったいに影響を与えさせないみたいなことを維持させて axios でアレするのと redux を使うのを併用するみたいな地獄みたいなことしてた、 redux-api-middleware 使うとコードの見た目キモくて嫌いなんだ、、、でもそうも言っておられん社会情勢なので、、、

背景

redux-api-middleware という名前について

redux ではフローの中で副作用を扱うことを禁止している。この為 API アクセスとかは出来ないので、それをなんかこう上手いところやってくれる middleware という仕組みを用意している。

公式ではロギングを例になんかまあいろいろ説明を書いてくれている。ちなみに読んでない。なんでロギングを例にするんだ、あきらかにみんな興味あるのは HTTP アクセスでしょ、こういう微妙に利用者に嫌がらせっぽいことしてくるのが気に食わない、、、

API アクセスという副作用を伴う作業をうまいところやってくれるライブラリが redux-api-middleware

どう使うのか

action creator 側に以下のように書く

import { CALL_API } from 'redux-api-middleware'

export default {
  load: ()=> {
    return {
      [CALL_API]: {
        endpoint: '/api',
        method: 'GET',
        types: ['REQUEST', 'SUCCESS', 'FAILURE'],
        credentials: 'same-origin',
      }
    }
  }
}

このようにしたあと、ふつうに load を dispatch する。 CALL_API とかそういうのはもうそういうもんと思っておく!!!

credentials: 'same-origin' をつけないと Cookie を使ってくれない。

types というのは reducer が受け取る action type 。リクエスト開始されると一番目の名前でアクションが、完了すると二番目の名前でアクションが、失敗すうと三番目の名前でアクションが発生する。

なのでリクエスト成功して state 更新したいときは reducer には

const reducer = (state = initialState, action)=>{
  switch(action.type){
    case 'REQUEST': 
      return {
        loading: true
      }
    case 'SUCCESS':
      return {
        data: action.payload
      }
    case 'FAILURE':
      return { fail: true }
    default:
      return state;
  }
}

これでコンポーネント側では this.props.loading が true ならローディングインジケーターを出して this.props.fail が true ならエラーメッセージを出して、あと this.props.data になにか入っとけばそれでなにか表示する みたいにすればいい。

感想

内部とか、 redux の middleware の根本的な仕組みとか一切理解しなくてもわりと表層的な理解でガシガシ書けるのでいい気はする。する、、、、

04 Sep 2017 Mon 18:26

OSS 版 Fastladder で LDR と全く同じインターフェイスでフィード読む というようなことをやっていきたい人がいると思います。

1. さくら VPS 契約する

1,706円/月 のメモリ 2GB プランがいいと思います。ストレージは SSD じゃなくて HDD にしときましょう。

2. 環境のセットアップ

面倒がすくないと思うので、標準 OS の CentOS 7 でサーバーを起動してください。このへんよくわからん人はさくらのマニュアルみて。

3. Docker のインストール

root ユーザーか sudo 実行できるユーザーで以下を実行してください。 SSH とか分かんない人はあきらめるか調べろ!!!

# curl -fsSL get.docker.com -o get-docker.sh
# sh get-docker.sh
# service docker start

これで Docker インストールされます。

4. git のインストールと構成設定をダウンロードしてくる

# yum install git -y
# git clone https://github.com/ssig33/compose-fastladder

5. データベースのセットアップ

# cd compose-fastladder
# docker-compose run fastladder ./bin/rake db:create db:migrate

6. fastladder の起動

# docker-compose up -d

これでできあがり。これでちょっと待ってると http://さくらVPSのIPアドレス:8080 であなたの Fastladder にアクセスできます。

これがなにやってるのかよく分からない人に向けたメッセージ

これで何が起きているのか分かるようになると普通にそれだけで飯食っていけるのでやっていってみたらどうでしょうか。

01 Sep 2017 Fri 15:42

Next