Firebaseでチャットアプリのサンプルを作った

TL;DR

チャット機能があるアプリをAWSで作ろうとしたが意外と難しそうだったのでFirebaseを試してみた

モチベーション

AWS導入事例では ALBの下にEC2やコンテナを並べてRedisのpub/subで…みたいなことをしていて結構大掛かりになりそうでした。 これは大規模な例ですが、AWSでチャット機能を実装しようとするとどうしてもSocket.io・WebSocket等を使うことになります。

今作りたいアプリではチャットはメインの機能ではないしフルスクラッチで開発するのは工数的にも厳しいので、 出来合いのものを埋め込むかPaaSを利用してもうすこし簡単に作りたい。 少し調べたところLayerというものを見つけましたが、 まだ完全にビジネスに耐えれるものでは無さそうでしたので諦めて、FirebaseのRealtimeDBを使ってみることにしました。

やったこと

チャットを実装するチュートリアルが公開されていたのでそれをやってみます。

https://codelabs.developers.google.com/codelabs/firebase-web/index.html#0

このチュートリアルでは以下の内容を網羅できるので今回のアプリにはぴったりでした。

  • Firebaseのプロジェクト作成
  • Googleアカウント認証機能
  • Firebase Realtime DBでメッセージの送受信
  • 画像の送受信
  • notificationの実装
  • デプロイ

所感

ちょっと機能がたりてない感がありますが、思ってた以上に簡単にチャット機能を実装でました。
本当はサーバーサイドでメッセージを受信したらイベントドリブンでプッシュ通知を相手側に送るみたいなことをやりたかったのですが、 Firebaseだけでは完結できませんでした。やるとしたらサーバー立ててRealtimeDBの全トピックをListenしてmessageがあったらプッシュ通知API叩くみたいなことをやらないといけない気がします。
pushイベントをhookできればLambdaでサーバレスできそうなので少し残念。 料金は高いですが初期のフェーズはFirebase Realtime Databaseを使用してスケールしてきたらチャット基盤を構築するということにしておくとそれほど問題にはならなさそうです。
圧倒的な速度でチャット機能を実現できるのでとりあえず迷ったらこれで作ってみるのが良さそうです。

Amazon Cognitoの認証フローを調べた

Amazon Cognitoを使う機会があったので調べたことをまとめました。

Amazon Cognitoとは

Amazon Cognitoはユーザの認証やデータ同期を提供するサービスです。

以下の3つの機能があります。

  • Cognito User Pool
    • AWSが提供する認証システム
  • Cognito Federated Identities
    • 任意の認証システムをつかったサインアップ機能の提供
  • Cognito Sync
    • ユーザデータ同期

今回はFederated Identitiesについて調べました。

Cognito Federated Identities

Cognito フェデレーテッドアイデンティティでは次の様なことができます。

  • ユーザの一意のIDを生成
  • Cognito User Poolや外部の認証システム(Facebook, Twitter等)と連携しユーザを認証
  • 権限が制限された一時的なAWS認証情報をクライアントに提供
  • 未認証ユーザにもIDを発行し一時的な認証を提供することができる

仕組み

Facebookを認証システムとして利用する場合、 iOSAndroidSDKのメソッド名等の細かい部分は異なるが大まかなフローは以下の通りです

https://github.com/takatori/blog/raw/master/entries/20170405/img/Cognito.png

  1. AWS SDKFacebookとの認証を行う
  2. FacebookがOAuthトークンをSDKに返す
  3. 取得したOAuthトークンをパラメータとしてCognitoのGetIdを呼び出す
  4. Cognitoは受け取ったトークンからidを生成もしくは既にある存在するidを取得して返す
  5. SDKが受け取ったidを指定してクレデンシャル情報取得APIを呼び出し
  6. Cognitoが一時的なクレデンシャル情報を返す

他にも認証フローがありますが、上記の方法が最も一般的なやり方のようです。

まとめ

Cognitoは機能がたくさんあり、ドキュメント分量が多いので一見複雑なことをしているように見えますが、 整理してまとめてみると意外とシンプルなフローで認証が行われていることがわかりました。 ドキュメントに書いて有ることを自分でかきなおしてみるのも結構勉強になりますね。

参考

2016年振り返り

大晦日なので2016年を振り返りたいと思います。

仕事

2016年で一番大きいかったのはやはり社会人になって東京に移動したことです。 以下仕事内容を時系列に従って振り返ってみます。

4月に入社すると二週間研修が行われ、その後すぐに案件に配属されました。 そこで、メインのエンジニアとしてServerlessの新規Webサイトの設計・開発を行うことになりました。 レビューを頂きながらですがサーバーサイドを一人で開発し、戸惑いながらもなんとか9月にリリースすることができました。 9月からは再び新規案件を任されここでもServerlessで開発を行うことになりました。 また、並行してインターン生の指導と内定者のメンターに任命されました。 10月からはJava・Play Frameworkの案件も始まり現在は2つの案件を同時に進めています。 11月にはTechLeadに任命されました。TechLeadとしてはまだ何もできていませんが、来年度は社内の若手で行う勉強会を企画しようと思っています。 12月に二つ目のServerless案件の第一弾をリリースしました。

新卒ですが様々なことを経験できて非常に勉強になった一年でした。趣味でWebサービスを開発するだけでは身につかなかった知識をたくさん身につけることができたと思います。 一方で実力不足を痛感した年でもありました。特にインフラ周りの知識が足り低なさすぎてとても一人で案件をまわせる段階ではないです。 来年はプロのエンジニアとして案件の技術的判断をひとりですべてできるように努力していかなければならないと反省しました。

つかった技術

読んだ本

Github

f:id:takatorix:20161231210529p:plain

4月から毎日コミットを心がけていましたが、途中途切れている箇所がいくつもある上に、内容のないdotfileの更新だけという日が多々ありました。 また、自分のリポジトリに対するコントリビュートしかなくOSSに全く貢献できていないです。

ブログ

hatenaブログ -> hexoで生成したブログをgithub pageで公開 -> hatenaブログと遷移したこともあり、ブログの内容より見た目やサービスにこだわりすぎて投稿数を増やすことができませんでした。来年はまず内容を充実することを目指します。

失敗したこと

失敗したことは数え切れないぐらいあるのですが、思いついたものを適当にあげます。

  • 朝起きる時間が遅い

    • 朝はやく起きれた日は一日緊張感を持って作業ができますが、遅くなってしまった日は全く集中できていなかったことが多かったです
    • 特に休日は昼間で寝過ごすと何も作業ができないので気をつけていきたいです
  • 部屋選び

    • 生活しやすい街の駅から徒歩5分圏内で綺麗で安いと割といい感じの物件を選んだはずだったのですが、いかんせん狭すぎました。
    • ロフトを含めると普通の広さぐらいなのですが、ロフトは使いづらすぎました。
    • 机を置けないと家で作業しづらすぎる...
  • Mac Book Air

    • 仕事でMBPを支給されるのに購入してしまった
    • 殆ど使っていないのでもったいないことをした
    • 時間があればArchをインストールして遊びたい

来年の目標

  • ブログを毎月書く
  • 勉強会で1回以上発表する
  • OSSに1回以上コントリビュートする
  • 毎日commit
  • 国内旅行3回

まとめ

東京に来てから様々な勉強会でいろんなエンジニアと関わって自分の技術力が足りていないことを痛感しました。 来年は最低でもここに上げた目標を達成し、まともなエンジニアになりたいです。

crateをcrates.ioに公開してみる

これはRust その2 Advent Calendar 2016 - Qiita11日目の記事です。

このエントリではcrateをcrates.ioに公開する方法を紹介します。

crates.ioとは

Cargo用のセントラルパッケージリポジトリです。

https://crates.io/

Cargoはこちらから依存するcrateを取得します。 また、作成したcrateの公開もCargoから実行可能です。

crates.ioでは一度公開されたcrateが非公開化・削除されないようcrateのバージョン管理を行っています。 発行できるバージョン数に制限はありませんが、 一度発行したバージョンを上書き・削除することはできないので公開する際には注意が必要です。

それでは、crates.ioにcrateを公開する方法を紹介していきます。

crates.ioのアカウントを作成する

crateを公開するためにはcrates.ioにGithubアカウントでログインし、 APIトークン取得する必要があります。

cargo.ioのページからGithubアカウントでログインします f:id:takatorix:20161210213626p:plain

Account Settingsページに移動し、APIトークンを取得します f:id:takatorix:20161210213622p:plain

f:id:takatorix:20161210213633p:plain

取得したAPIトークンをCargoに登録するために、以下のコマンドを実行します。

$ cargo login <APIトークン>

このコマンドはローカルの~/.cargo/configにトークンを保存しています。

Cargo.tomlに情報を追加する

cargo new で生成されたCargo.tomlファイルには以下の情報が記載されます。

[package]
name = "rawst"
version = "0.1.0"
authors = ["takatori <takatorix@gmail.com>"]

上記の情報のみでもcrateを公開することが可能ですが、 より検索に引っかかりやすいようメタデータを追加していきます。

[package]
name = "rawst"
version = "0.1.0"
authors = ["takatori <takatorix@gmail.com>"]

license = "MIT"
description = "The interactive tool for AWS CLI written in Rust"
repository = "https://github.com/takatori/rawst"
readme = "README.md"
keywords = ["rawst", "aws"]

この他に、homeページやdocumentページを指定することもできます。

また、バージョン管理システムでignoreされているファイルは自動的にパッケージから除外されますが、 excludeで除外するファイル・ディレクトリを明示的に指定することもできます。

[package]
# ...
exclude = [
    "public/assets/*",
    "videos/*",
]

逆に、includeでpackageに含めるものを指定することもできます。

crateの名前は先着順に割り当てられるため、すでに使用されているものは使えないので気をつけてください。

パッケージング

次にcrate.ioにアップロードできるフォーマットにcrateをパッケージングします。

$ cargo package

このコマンドを実行するとtarget/packageディレクトリに.crateファイルが生成されます。

.crateファイルは現在のとろこ、最大10MBまでしかアップロードできないのでサイズの大きな画像ファイルなどはexclude指定すると良いでしょう。

また、コミットされていないファイルがある場合以下のようなエラーが出ます。

error: 1 dirty files found in the working directory:

すべてのファイルをcommitまたはstashするか--allow-dirtyフラグを付けることでパッケージングできるようになります。

公開する

それではcrateをcrates.ioにアップロードします。

$ cargo publish

この段階で依存crateのバージョンをワイルドカードで指定している場合、以下のようなエラーが発生します。

error: api errors: wildcard (`*`) dependency constraints are not allowed on crates.io. 

ワイルドカードは許可されていないので、明示的にバージョンを指定する必要があります。

publishが成功すると以下のようにcrates.io-indexリポジトリにindexが登録されていることが確認できます。

https://github.com/rust-lang/crates.io-index/blob/master/ra/ws/rawst#L1

発行したバージョンを取り下げる

誤ってバージョンを発行してしまった場合yankコマンドで取り下げることができます。

$ cargo yank --vers 1.0.1

このコマンドはcrates.ioに公開されたデータを削除するのではなく、 指定したバージョンを新たに使用できないようにします。 すでにこのバージョンを指定しているプログラムからは引き続き使用することができます。

一度発行してしまったバージョンはどうあがいても変更できませんので、 誤ってクレデンシャル等の情報を含めて発行してしまった場合、クレデンシャルの方を即座に変更する必要があります。

まとめ

cargoを使ってcrateをcrates.ioに公開する方法を紹介しました。 簡単にパッケージを公開できるのでどんどん開発していきましょう!

参考

Rustの勉強をはじめました

最近よく聞くようになったプログラミング言語Rustの勉強をはじめました。

Rustとは

なぜRust?

  • システムプログラミングを勉強したかったので
  • 関数型っぽくもかけそう

勉強題材

最近、いろんな言語をちょっとだけ触ってやめる、みたいなことを繰り返しているけど今回はガチ

Go言語初心者向けハンズオンに参加してきました

Go言語初心者向けハンズオンに参加してきたので内容と感想を書きます。

概要

tenntennさんが主催でteratailさんが会場・サポートを提供してくださいました。

connpass.com

対象は主にA Tour of Goを終えたようなGoに少し触ったことのある人で、 Go言語自体の解説ではなくGoを使ってプロダクトを作るということがメインでした。

やったこと

tenntennさんが作られているハンズオンをひたすらやっていく形式でした。

github.com

コマンドラインツールをステップを踏んで少しづつ作っていくのですが、 実際にプロダクトを作っていくときもこのステップを真似ればできそうだなという感じで非常に参考になりました。

自分のようなA Tour of Goをやったはいいものの次にどうやってプロダクトを作っていいのか悩んでる人は絶対に このハンズオンをやったほうがいいと思います。

感想

Go言語のすごい方たちに教えていただきながらGoを勉強できるという非常にありがたい経験ができました。

Goについてはgo routine等について全く触っていないので良さをほとんど理解できていない気もしますが、 コードを読むとだいたい何をやっているのかわかるので気軽にかけて楽しい印象を受けました。

個人的にGoを使ってみてつらいなと感じたたのは、ifが値を返さないところとerr処理がコードの至る所に現れる点で、 ScalaだとOption型ですっきりかけそうだけどな〜と感じたところが結構ありました。

ということをdeeeetさんに聞いてみたところ、以下のエントリを紹介していただきました。ありがとうございます。

jxck.hatenablog.com

ハンズオンに参加してみてGo言語を使って何かを作るハードルがぐっと下がったような気がします。 超すごいエンジニアの方にめちゃくちゃ初歩的なことを聞くなんて申し訳無さがありましたが、 親切に教えていただいてとても勉強になりました。ありがとうございました!