こんにちは、シタテルの鶴巻です。 devops&インフラ担当です。
最近、firebase/firebase-admin-goの実装で気になったところがあり、プルリクエストから経緯を知ることができました。
GitHub上のソースコードで気になった箇所の経緯を追うことは今後もあると思うので、整理がてら方法を紹介します。
要約
- firebase/firebase-admin-goの実装で気になったところがあった
git blame
コマンドで、ソースコードが最後に編集されたhashを特定- 対象のソースコードが追加されたプルリクエストで経緯が分かった
firebase-admin-sdk-goの実装で気になった箇所
firebase-admin-sdk-goは、名前の通りFirebaseサービスをGolangから扱うためのSDKです。
Firebase Authenticationを試してみた際に、弊社で使用しているRubyのSDKがなかったため、GolangのSDKの実装を少し読んでみました。
そこで、Googleのサーバから公開鍵を取得するメソッドの中で排他制御が行われていることに着目しました。
私はここで排他制御を実施している理由がわからなかったので、経緯を調べることにしました。
該当ソースコードは以下です。
https://github.com/firebase/firebase-admin-go/blob/master/auth/token_verifier.go#L66-L76
func (k *httpKeySource) Keys(ctx context.Context) ([]*publicKey, error) {
k.Mutex.Lock()
defer k.Mutex.Unlock()
if len(k.CachedKeys) == 0 || k.hasExpired() {
err := k.refreshKeys(ctx)
if err != nil && len(k.CachedKeys) == 0 {
return nil, err
}
}
return k.CachedKeys, nil
}
プルリクエストを見つける手順
1. git blame
コマンドで、対象のソースコードが最後に編集されたcommitのHash値を特定
- 対象のソースコードが最後に変更されたcommiのHash値は
f3174984
ということが特定できます$ git blame auth/token_verifier.go | grep -e "k.Mutex.Lock()" -e "defer k.Mutex.Unlock()" f3174984 auth/crypto.go (Hiranya Jayathilaka 2017-05-18 13:45:30 -0700 67) k.Mutex.Lock() f3174984 auth/crypto.go (Hiranya Jayathilaka 2017-05-18 13:45:30 -0700 68) defer k.Mutex.Unlock()
2. GitHubの対象レポのプルリクエストをHash値で検索
- プルリクエストが見つかりましたー!🎉🎉🎉
https://github.com/firebase/firebase-admin-go/pull/3
実装の理由は?
- プルリクエストのコメントにありました
- 複数のスレッドが共有している公開鍵のキャッシュを同時に更新するのを防ぐためにmutexを導入したみたいです。
Introduced a mutex to prevent multiple threads from updating the shared cache concurrently.
- ソースコードを追うと、公開鍵取得のメソッドは httpKeySource構造体に定義されており、さらにhttpKeySourceはClient構造体に定義されています。SDKを使う際に最初にClientの初期化を行いますが、初期化した同一のClientで公開鍵取得メソッドがconcurrencyに実行されても安全なように実装されているのかなと考察しました。
firebase-admin-sdk-goはgit-flow
firebase-admin-sdk-goはgit-flowで開発されているようです。
そのため、masterのソースコードのcommitのHash値がプルリクエストがマージされた時のHash値と同じで、プルリクエストが見つけやすかったです。
おまけ(nodejsの実装)
Node.jsのSDKの同じ箇所の実装についても少し覗いてみました。
Node.jsを書いたことはありませんが、見る限り排他制御はしていないように見えます。
Node.jsはシングルスレッド推奨だから排他制御しなくていいのか・・・など思い、言語の特性の違いが垣間見えて面白いですね。
- firebase-admin-node
- 公開鍵取得 https://github.com/firebase/firebase-admin-node/blob/master/src/auth/token-verifier.ts#L260
まとめ
- オープンソース文化いいですね。今回の例だとfirebaseの中の人が書いたソースコードや、そのプルリクを見ることができています(もしかしたら中の人じゃないかもしれませんが)。エンジニアとしては当たり前な文化ですが、ブラックボックス化されている業界が多いなか改めて良い文化だと思いました。
- シタテルはRailsを使用しているので、RubyのSDKがあればFirebase Auth導入してみたかったのですが残念です。