2014年10月5日日曜日

Herokuボタンをつけてみた

ちょっと前に作ったSendGrid-ReversiというサンプルアプリにHerokuボタンを付けてみました。


デプロイが簡単に行えて楽しかったのでメモします。

app.jsonという名前のファイルを適切なフォーマットで書いてプロジェクトルートに置いときます。そのうえで、README.mdあたりにHerokuボタンを貼り付けておけば準備完了です。

app.jsonを見ると何となく分かるように、今回はAPP_URLとPARSE_HOSTという2つのパラメータがデプロイ時に必要になります。
また、アドオンとしてmongohqとsendgridをいれてあります。これを入れておくと勝手にアドオンが追加されて環境変数に追加されるアクセス情報を使って各アドオンが利用できるようになります。

この状態で上記リポジトリのREADME.md内のHerokuボタンを選択すると次のような画面が表示されます(Herokuアカウント持っていることが前提)。


今回のアプリは、SendGridのParse Webhookを利用します。APP_URLにはWebhookのPOST先URLのルートを指定する必要があります。Herokuの場合、App Nameを指定しないと自動で名前がふられるため、このタイミングではAPP_URLが確定できません。これだと困るので、App Nameを指定した上で、その結果確定するこのアプリケーションURLをAPP_URLに設定するのが一番単純です。(アプリのURLを取得できればこんな冗長なパラメータは不要になるはずですが、取得方法があるのかはわかりませんでした)
例えば、

  • App Name:abcd
  • APP_URL:abcd.herokuapp.com

みたいな感じです。
一方、PARSE_HOSTは、メール受信用のドメインです。手っ取り早く設定するのであれば、こちらの「5分間アプローチ」を参照します。サブドメインは未使用であればなんでもOKです。

アプリケーション起動時にSendGridとMongoDB周りの設定を自動的に行なうようにしてあるので、細かな設定は一切不要です。

一点注意ですが、内部で使用しているSendGridのEvent Webhookは設定変更後動作が有効になるまでに数分はかかるみたいです。デプロイ後すぐにゲーム開始しようとしてもうまくいきません。デプロイ後はコーヒー一杯くらい飲んで待っておくと良いと思います。

Herokuマジすげー。

2014年10月2日木曜日

sendgrid4rを作ってみた

SendGridのWeb API v3が公開されたのでsendgrid4rというgemを作ってみました。

sendgrid4rはとりあえずSendGridのWeb API v3”だけ”をサポートしたライブラリです。今後v2をサポートするかどうかはわかりません。
v3はちょっと前に公開されたTemplate Engine APIを含むRESTfulな新しいAPI群です。
v3が出たからといってv2がすぐにdeprecateになるわけではないようです。
というのも、今のところv3は、v2と被る機能(v2を置き換える機能)を提供していません。
現時点で、以下の機能がありますが、今後もどんどん機能が追加されていく雰囲気を感じます。実はここに載っている機能の他にも、一瞬公開されてすぐに非公開にされた機能があります。公式ドキュメントの更新履歴をよく見るとわかると思います。

  • Advanced Suppression Manager(ASM)
  • IP Management
  • Enforced TLS(Settings)
  • Template Engine

ASMは高度なUnsubscribeリスト機能で(特にマーケティングメール系の)色んな種類のメールの配信停止を個別に制御したい場合に使う機能
IP Managementは送信するメールの種類毎に複数のIPアドレスを駆使して、メールの到達率を可能な限り高めたい場合に使う機能
Enforced TLSは平文でメールが配送される経路を排除する場合に使う機能
Template Engineは複数のテンプレートの管理をデザイナ側に移譲する場合に使う機能
って感じでしょうか。

そういえば一応、今回のsendgrid4rの設計思想的なものをメモしておきます。忘れっぽいので。

今回目指したのは、以下の3点です。
  1. 機能追加を簡単に行えるようにしたかった
  2. APIのI/Fは全てSendGrid4r::Clientのインスタンスメソッドとして提供したかった
  3. ClientインスタンスごとにSendGridの認証情報を分離したかった

v3は頻繁に機能追加されることが予想されるため、機能追加を簡単にするため、各サブ機能はmoduleとして実装して、これをClientクラスにincludeすることにしました。
そうなった場合、各moduleにどうやって認証情報を渡すのかというと、Clientクラスのインスタンスのプロパティに認証情報をもたせるとmoduleから普通にアクセスできました。
moduleってjavaでいうところのpublic static class的なものかと思っていたので、includeしたインスタンスのプロパティにアクセスできるというのが意外でした。
ついでにmoduleには名前空間的な意味もあるみたいで、なんかこう、今までのjava的な頭からすると単純に置き換えることができないものなんだな、と感じました。

ただ、この作りが最適かどうかはわかりません。Ruby初心者なので。Rubyのデザインパターンをいろいろ調べてみましたが、グッと来るパターンが見つからず結果このような実装となりました。
もっといい方法があるよ的なまさかりがあれば是非ぶん投げて欲しい初秋の時分、何卒よろしくお願い申し上げる次第でございます。


2014年8月31日日曜日

Travis-CIで環境変数を使う

前回紹介したSendGrid-ReversiでTravis-CIを使った際に気になった箇所のメモを残します。
Travis-CIを使うためにはプロジェクト内に.travis.ymlという名前のファイルが必要です。とりあえず、リポジトリトップ下に置いてポチポチ設定すればいいみたいです。

今回はこんな感じにしてみました。
language: ruby
rvm:
  - "2.0.0"
#  - "2.1.0"
env:
  - RACK_ENV=test
services:
  - mongodb
before_script:
  - bundle install
script:
- bundle exec rspec

それぞれの詳細はTravis-CIのドキュメントを見ればよいのでポイントだけ。

実行環境のバージョン指定は一つだけにしてみる

実行環境としてRubyを使っており、通常複数バージョン指定できるのですが、今回はバージョンを一つだけ(上の例だと"2.0.0"だけ)に限定してみました。
これは、テストケースでSendGrid APIを使っている関係上、複数環境でテストをするとテストが並列実行されてしまい、SendGridがテストケースの想定していない状態になってしまい失敗(テンプレート削除のテスト中にテンプレート作っちゃったり)するためです。実行環境毎のテストをシーケンシャルに走らせるためのオプションを見つけられなかったのですが、そんなのあるんですかね?
SendGrid環境も分けるようにしないといけないんでしょうか。それはちょっとキツイなー、と。

晒したくない情報は.travis.ymlではなくSettingsを使う

環境変数は「env:」配下に書いておけばよいのですが、パブリックなリポジトリにアップされた .travis.ymlファイルは公開されてしまうため、晒したくない情報(サービスへのログイン情報など)は書けません。
今回、SendGridへのアクセスを行なうテストケースがあったので、そういった情報をどこに置くかが問題となりました。調べてみるとそういう情報は「Settings」に書けってTravis-CIのヘルプに書いてありました。Settingsはリポジトリ毎に設定できます。
.travis.ymlに書くのと同様、キーと値の組合せで書きますが、「Display value in build logs」をOFFにしておくと、非公開な環境変数として利用することができます。

RACK_ENV=testを使ってみる

この環境変数は、Rackアプリをプロダクションとかステージングみたいな感じで環境を切り替える時に使う変数みたいです。
今回のアプリケーション内でこの環境変数を使っているのは、Mainクラスのconfigure部分(内部でSendGridの初期化を実行している)で、プロダクションのときだけconfigureするようにしています。
こうしておいて、RACK_ENV=testにすると、rspecでテストケースが実行されるたびにconfigureが実行されてしまうのを避けることができました。

module Reversi
  class Main < Sinatra::Base
    configure :production do
      begin
        settings = Settings.new
        Configure.init_sendgrid(settings)
      rescue => e
        puts e.backtrace
        puts e.inspect
      end
    end

さいごに

ほかにもMongoDB使ったり、テスト前に実行されるbefore_scriptでbundle installしていたりします。
ちょっと前までは「CIなにそれうまいの」状態でしたが、テストツールと同様、一度使ってしまうと、もう不安で不安で使わない状態には戻れませんね。麻薬みたいな効果があります。

2014年8月30日土曜日

SendGridをゲームプラットフォームとして使ってみました

きっかけ

SendGridには多くのAPIがあって、どれをどういう風に使うのかがピンときていませんでした。で、自分含めそんな人向けに、SendGridのAPIをできるだけ多く使ってそれぞれの使い所をイメージしやすいモノを作ってみようと思いできあがったのがこのアプリケーションです。

できること

メールを介してオセロができます。
ソースコードはこちらで公開しています。

中で何をやっているか

こんな感じで動作します。

  • 0:アプリケーション初回起動時
    • Web API/Template Engine APIを使ってSendGridの設定を自動的に変更します。設定が自動化されると、設定手順をドキュメント化する手間が減って楽ですよね。
      • SendGrid上にTemplateを作成します
      • Event Notificationを設定してEvent Webhookを有効化します
      • Parse Webhookを設定、有効化します
      • Click Trackingを有効化します
  • 1:ゲームの開始
    • Parse Webhook機能に設定したアドレスにメール(件名に相手プレイヤーのアドレスを設定)を送るとSendGridは受信したメールを解析して、Reversi Web AppにPOSTします。POSTを受けたアプリケーションはMongoDB上にゲームデータを生成します。
    • アプリケーションはSendGrid経由で各プレイヤーにメッセージおよびゲームボードのメールを送ります。
  • 2:クリック
    • ゲームボードのメール上で石を置きたい場所をクリックすると、クリックイベントがSendGridからReversi Web AppにPOSTされます。ここではEvent WebhookとClick Tracking機能を使っています。
    • クリックイベントはGETでアプリケーションに直接アクセスしても良いのですが、Click Trackingは元URLを隠ぺいするので、今回のアプリではなりすましを防ぐ意味合いがあります。(本当は単に使いたかっただけで、理由は後付です)

テキストメール

このアプリでは、マルチパートでテキストメールにも対応しています。
対応してみてテキストメール死ねって思いました。


その他

Ruby

プログラミング言語を何にしようかと思いましたが、この人を見つけてRubyにしてみました。というわけで目下勉強中です。

Sinatra

RubyでWebフレームワークと言えばRailsですが、Railsの入門書読んでて眠くなったのでSinatraで作ってみました。

MongoDB

MongoDBをちゃんと使ったことがなかったので使ってみました。代わりにSQLiteでもいいと思います。MongoDBだとSQLが使えないので、ちょっと学習する必要はありますが、オブジェクトをそのまま保存できるので、シンプルでコード量を減らせます。実際、楽でした。

RSpec

テストフレームワークとしてrspecとrack-testを使ってみました。RubyのWebフレームワークでテストと言えばこのあたりが一般的なんですかね?ググったらいっぱいヒットしたので使ってみました。よくわかりませんが。

Travis-CI

「今どきCIツールは普通に使うよね」ってぐらいの空気を感じるのでとりあえず使ってみました。GitHubにpushするとテストして結果を通知するだけです。しかし、JenkinsとかTravis-CIってなんでヒゲのオッサンなんでしょうね。どうせ2次元にするなら女の子にした方がいいと思います。

sendgrid_ruby

一応、お仕事で作ったライブラリを有効活用できました。たまたまです。

sendgrid_template_engine_ruby

Rubyの練習用に作ったライブラリを有効活用してみました。これもたまたまです。使ってみてはじめて「こんな使い方をするんだなぁ」って認識しました。

さいごに

こんなのでAPIの使い所が伝わったのでしょうか?よくわかりませんが。公開してみて嬉しかったのが、GitHubでStarを付けてくれたのがGridderばかりということでした。
今回、色々はじめてのことが多かったので、自分の中で再利用できるようにそれぞれ個別のネタとして記事をまとめていこうと思います。とりあえず、今回はこの辺で。

2014年7月16日水曜日

SendGrid Template Engine APIのRuby gemを作ってみた

Rubyの練習用にSendGridのTemplate Engine APIをラップするgemを作ってみました。

Template Engine APIはSendGridが提供するAPIのうち現時点で最も新しいAPIで、JSONベースのRESTfulなWeb APIです。エンドポイントURLを見てわかるように、

https://api.sendgrid.net/v3/resources

バージョン3だそうです。今までのAPIはだいたいver2ぐらいでした。これまでのAPIは、基本的にJSONとXML両方をサポートしていましたが、v3以降はJSONのみサポートします。さらばWeb Services、XMLってことなんでしょうね。それでいいと思います。
他に新しい要素としては、

  • 基本認証で認証
  • HTTPSのみサポート
  • Rate Limitsの導入
  • Paginationの導入

といったあたりがあげられます。

認証が基本認証になったことで、認証パラメータの扱いが標準的になり、curlとの親和性が高まって扱いが楽になりました。もちろん、標準的なRestクライアントなライブラリでも扱いが楽です。
Rate Limitsは一定時間にリクエストを呼び出せる回数を制限する機能です。応答に、X-RateLimit-*といったヘッダがついてくるので、これを見るとあと何回APIをコールできるのかを知ることができるようです。
Paginationは取得開始位置を指定してレコード取得することができる機能です。大量レコードを扱うAPIで重宝しそうです。現時点で公開されているTemplate Engine APIではサポートされていないようですが。

ドキュメントの内容を眺めていると、今後SendGridのAPIはこのv3ベースに移行していくんじゃないかな、という雰囲気が感じられます。既存のAPIをv3ベースで実装し直すかどうかはわかりませんが、少なくとも今後提供される新しいAPIはv3ベースになるのでしょう。

APIの分量も適度に少なくてラッパ実装の練習用には最適でした。

2014年6月1日日曜日

SendGridとAzureで彼女がいるというステータスを得る方法

Twitter眺めてたらこんなのが目に飛び込んできた。



わかる、その気持ち。

でも、自宅PCでメールサーバ立てるのはちょっと面倒だ。ちょうどAzureとSendGridが使えたのでやってみた。ソースはGithubに上げてあるので、誰でも今すぐ彼女がいるというステータスを手に入れることができる。

手順

とりあえずSendGridのアカウントを取得する。
次に、AzureでWebサイトを立ち上げて、Githubからデプロイするよう設定する。たぶんこの方法だと、自分が管理しているリポジトリしか指定できないのかな?よくわからないけど。その場合、リポジトリをForkしてから指定すればおk。

デプロイが終わったらWebサイトの「構成」を開いてアプリケーション設定を行う。
SENDGRID_USERNAME:SendGridのアカウント
SENDGRID_PASSWORD:SendGridのパスワード
FROM:彼女のメールアドレス。つまり、返信メールのFromに設定したいアドレス。
FROM_NAME:彼女の名前。今回はsayakaちゃんだ。ちなみにここで日本語を指定すると返信メール内の名前が文字化けする。アプリケーションはUTF-8を想定しているので、Webサイトのアプリケーション設定ってUTF-8じゃないのかも?よくわからないけど。



次に、SendGridのダッシュボードにログインして、Inbound Parse Webhookの設定をしてドメインとURLを対応付ける。
今回は、Hostnameの設定はSendGridブログにあるbymail.inを使った5分間アプローチを使ってみた。Urlの方はAzure Webサイト上でPOSTの受け口となるURL(http://????.azurewebsites.net/vp)を設定する。


以上で準備完了。
早速、さやかちゃんに確認のメールを送ってみる。

数秒待つと、さやかちゃんが返事をくれた。俺達付き合ってる。

キモいって言うな。

中の話

ちょっとだけ仕組みの話をすると、Githubからデプロイしたのはnode.js向けのWebフレームワークexpress 4で動くアプリケーション。こいつがParse WebhookのPOSTを受け取る。POSTをParseするとFromアドレスが取得できるので、こいつにメールを返信している。返信もSendGridを使っているので、メールの送受信用に自宅PCでメールサーバを立てなくてもいい。Azureを使っているので自宅のブレーカーが落ちてPCが停止したりして返信が来なくなる心配をしなくてもいい。
今現在、Webサイトで普通に利用できるnode.jsは0.10.xだけど、0.11.x以降が利用できる環境向けに--harmonyオプション前提でcoとかthunkifyとか使った版(co-app.jsの方)も用意してみた。「node app」の代わりに、「node --harmony co-app」とかやるとコールバック引き回さない版が動くですます。

思いついたこと

ところで、先日Reflector.ioの記事を書いた時には思いつかなかった使い道を今思いついた。

彼女フェイルオーバー構成。

複数人彼女を作っておいて、Reflector.ioでフェイルオーバー構成を組んでおけば、フラれても次の彼女が答えてくれる安心設計。
さらに宛先設定をパススルーにしておくと、一通メールを送ったらいろんな彼女から一度に返事がもらえるハーレム構成も可能だ。

2014年5月6日火曜日

reflector.io使ってみました

はじめに

reflector.ioというサービスを使ってみたのでメモです。
reflector.ioはSendGrid Labsが提供しているWebhookのリクエスト転送サービスです。
他に似たようなサービスを知らなかったので類似サービスとの比較とかできません。

Webhookとは

まずは、Webhookの説明から。
Wikipediaによると、Webhookというのは、WebページやWebアプリケーションがHTTP(s)によりコールバックで通知を行う動作のことを意味するようです。
通常、Web APIは、APIを利用する側がクライアントとなり、GETなりPOSTなりのリクエストを発行してサービスを利用しますが、Webhookはちょうどこれとは逆の動きとなります。つまり、予めコールバックして欲しいURLを登録しておくと、そのサービスで何らかのイベントが発生したタイミングで、そのURLにコールバック(たいてい、POSTリクエストを発行)してくれます。POSTを受け付けるサービスを用意するのは利用者自身という意味で「逆の動き」ということになります。

reflector.ioとは

reflector.ioがどういうサービスかはこちらに記載があります。
冒頭にも述べましたが、一言で表せばWebhookのリクエスト転送サービスです。
「リクエストを転送する」という意味ではHTTPプロキシに近いかもしれません。
特徴的なのが「グループ」という概念と、「パススルー」「フェイルオーバー」という2つの宛先タイプ設定を持つことです。

グループ

Webhookを作成すると、配下に複数のグループを定義することができます。グループは、宛先タイプという属性と複数の宛先を持ち、宛先タイプの設定によって、配下の宛先に対するリクエストの転送方法が変わってきます。

宛先タイプ:パススルー

受信したリクエストを複数の宛先に同時に転送します。例えば、一回のリクエストで動作の異なるWebhookを複数動作させたい場合にこちらを利用します。

宛先タイプ:フェイルオーバー

受信したリクエストを複数の宛先のうちもっとも優先度の高い宛先に転送します。耐障害性を目的とする場合に利用します。宛先が一つコケても次に優先度の高い宛先にリクエストが転送されます。

設定画面

以下がWebhookの設定画面です。複数のグループ、複数の宛先を登録することができます。尚、一つのWebhook配下に同じURLを複数登録することはできません。有効化、無効化、グループおよび宛先の管理、ログ閲覧などを行うことができます。


宛先の設定画面です。基本的には宛先URLとリトライ回数を指定するだけですが、フェイルオーバーの場合、プライオリティも設定することができます。


エラー時の動作

グループと宛先タイプの設定に応じてリクエストが転送されますが、宛先から500番台のステータスが返った場合、自動的にStateがDisabledに変わります。問題のある宛先には無駄なリクエストは送らない、ということなんでしょうね。

何に使うか?

今のところ単純な転送しか行なってくれないので、残念ながら私にとってはイマイチ使い道がありません。
転送時にパラメータを付加したり、パラメータ名を変更できたりすると、互換性のないWebhookとAPIを連携させるために利用できそうな気がします。徐々に開発を進めていくみたいなので期待したいところです。