iPhoneで Grafanaの グラフを 参照できる アプリ Grafanizer 作ってます。 詳しくは こちらへ

GoogleAppEngineとFirestoreの機能を利用してGolangとかVue.jsで動く2chみたいな掲示板を作ってGitLabCIで自動デプロイさせて一人DevOptsしてみた

Dec 21, 2017  
#appengine #firestore #vue.js #golang #gitlab #adventcalendar

これは Firebase Advent Calendar 2017 用に作成したポストです。

手を上げたときは「 AppStoreでアプリが売れたらFirebaseからIFTTT経由でiPhoneへ通知させる 」を予定していましたが、直前にコードの修正を行ってたら時間切れで間に合いませんでした。そちらのほうがFirebase色が強いと思いますので、興味がありましたら合わせて御覧ください。

Firebase以外のネタの方が多くてすいません。Firebaseのネタだけ読みたい人は こちらの「躓いたところ」 をどうぞ。

はじめに

今年勉強した内容についての総決算的な意味合いで、今流行りのキラキラキーワードをふんだんに盛り込んだタイトル通りのサービスを作ってみた。
(意図せず12/24のクリスマスにこの記事を公開することとなりましたが、個人的にクリスマスの夜はキラキラと全く関係ありません)

キーワードは今時でキラッキラなんだけど、作ったのは2chみたいな昔ながらの掲示板ってところがちょっとしたアッピールポイント。

icon

(ドメインどころかサブドメインを切ってないくらいには適当な扱い)

機能

機能的な特徴をあげると、以下の感じ。

  1. チャット風なリアルタイム表示
  2. プライベートな掲示板も作成可能(URLを知ってる人のみアクセス)
  3. 全文検索
  4. 掲示板で発言しているユーザーの一覧表示
  5. 24H限りのミュート
  6. 1,000件になると書き込みできない(2chリスペクト)

この手の掲示板で全文検索があるところは珍しいんじゃないかと思うし、掲示板で発言しているユーザーの一覧表示っていうのもなかなかおもしろいと思ってる。

あと、24H限定のミュート。Facebookも何日間かのミュートを実装するみたいだし、永久にってまでは要らないけどちょっとの間ミュートってのは確実に需要がありそう。

ミュートさせるためだけってことでもないけど、今時のサービスっぽく一応ログインしないと発言できないようにしている。捨て垢でも利用できるからどこまで効果あるかわからないけど、流石に匿名っていうのはね。でも、それでちょっと敷居が高くなってしまうのは否めない。

構成

  • Firebase
    • Authentication
    • Firestore
  • GAE
    • Go Standard Environment
    • Search For GAE
  • GCP
    • Cloud Storage
  • GitLab
    • CI

認証周りと発言内容の保存はFirebaseの機能を利用し、HTML配信周りと全文検索用データ作成にGAE上のGolangで作成、JSON形式へ変換した過去ログ(1000件以上になるとdat落ち)はCloudStorageに保管という感じにしてみた。

GitLabはCI機能だけを使ってる。ソースの公開やIssues,PullReqの受付はGitHubで行いながらも、GitLabでミラーしてCIを回してる。なんでGitLabのCIかっていうと使い慣れてるからってだけなんだけど、プライベートリポジトリも持てるし開発も熱いしで結構好きなプロダクトですね。

ユーザー側のインタフェースは全てVue.jsで構築。また、全文検索のインデックス作成や過去ログ変換はGolangで構築してて、GAEのCron機能をつかってバッチ処理にして逃げてる。バッチ処理についてはCloudFunctionにしたかったんだけど、Golangに慣れてしまうとJSでの開発はなかなか億劫になっちゃいますよね。

名前の由来

角打ちとか立ち呑みっていいですよね。一人でふらっと適当な店へ入って、隣のおっちゃんと絶対記憶には残らない適当な話をして、数杯呑んで適当なタイミングで帰る。

今のSNS全盛時代にもあの適当さが欲しい。フォローやブロックとかもう面倒。いまそこにいるメンバーみんなで楽しめたら、それでいいじゃん。

という場所が今のインターネットにも必要じゃないですかね?

コードについて

技術系ブログらしくコードについても少し触れておきたところなのだが、FirestoreとGAEの機能が素晴らしくて難しかったところが全然ない状態。

一番作り込んだのはGitLabCIでの自動デプロイ周りじゃないか? って位に、構築は簡単でした。

あ、あとVue.jsの存在も忘れられない。Vue.jsの一方向なデータフローはFirestoreと非常に相性が良かった。 データの変更は自動的にうけとれるので、そのままVue.jsのdataにセットするだけ。 最初にその動きをイメージしたデータ構造にする必要はあるけど、かなり楽でした。

READMEすら無いけど GitHubのリポジトリはこちら

躓いたところ

キラッキラなサービスを簡単に構築できたわけだけど、実は躓いたところもある。それも2箇所。 でも、どちらもFirestoreがβ版ってことが原因だと思うので、近い将来的には解消されるはず。

GAEからFirestoreへの接続はSocket通信

これはGolangからFirestoreへ接続する際にエラーが発生して躓いた。ローカル環境では問題なく動くのだけど、GAEに載せるとタイムアウトでエラーになる。

一応エラーメッセージは表示されているものの、具体的ではなく一過性のエラーという内容。ググっても一過性のエラーだからエラーを拾って再実行すれば良いっていう記事ばっかりなんだけど、再接続させても全然解決せず。

で、最終的にはクレジットカードの登録なしではSocket通信が出来ないという結末だった。gRPC経由ってのは見てたけど、Socket通信でおまけに課金対象だっていうところまではなかなか到達できずに手間取った。

Firestoreを有効にするとSearchがうまく動かない

これもなかなか手間取ったんだけど、Firestoreと一緒に作られるGAE環境ではSearchがうまく動かなかった。 かと言って、最初にGAEの環境をつくっておくとFirestoreは利用できない。

多分Namespace周りとかの問題だとは思うのだが、結局いい方法が見つからなかったので、FirebaseとGAEでプロジェクトを切り離して対応した。

将来的には問題なく利用できるとは思うが、分けることで良い点もありそう。

GAE側で課金対象にするとFirebaseも自動的に課金対象にアップグレードされる。で、GAE側ではほとんど課金対象にならないのだが、Firestoreを使った開発中はテストも含めてデータを投入するケースが多くなるので課金について少し心配。

実際、Firestoreのデータをチェックして必要なデータが無い場合は自動的にそのデータを作るというコードを作ったのだが、バグってて無限ループになってしまってたことが(笑。 まあすぐ気付いて止めたし、課金対象になってなかったからどこかで動作がストップするとは思うけど結構焦った。

まとめ

  • 古き良き時代のインターネッツが懐かしいね!
  • キラキラキーワードなサービスで古き良きインターネッツを取り戻したいね!
  • Firebase, GAE, Golang, Vue.js, GitLabって最高!
  • Firestoreはやくβ版とれて!
  • 最近のSNSってかなり面倒だよね!

一年の締めくくりとして個人的にはなかなかおもしろいサービスを作ることができた。

まだまだ新しいことを吸収しながらもジジイになるまで趣味のプログラム作りを続けていきたい。