TypeScript & React & Firebase で何かつくってみる6 Functions 3
そろそろ思いつきだけで進めるのも限界がきたかな. ちょうどGWになるし じっくり考えたほうがいいかも.
Functions トランザクション
シャッフルの他に トランプでよくあるアクションと言えば「一枚引く」だ.
要するに カードをある「場」から別の「場」へ移動する処理だ. 「引く」に限らず「交換する」「捨てる」なども本質的に同じと考えていいだろう.
普通に考えれば, データベース中のある場所からデータを削除し別の場所に挿入する, アトミックな処理にする必要があるだろう.
1 回のトランザクションまたはバッチ書き込みでは、最大 500 のドキュメントに書き込みを行うことができます。
とあるが, サンプルコードは1つのドキュメントしか読み書きしてない.
2つ以上のドキュメントをアトミックに扱う場合はどう書けばいいのか.
すぐにはわからなかったため, ひとまず deck ドキュメントの下に hand という配列を用意する.
hand とはいわゆる手札だ.
本来 deck は「一揃えのカード」の意味で, その下に手札あるのおかしいし, そういうつもりで作ったのではないのだが, まぁ一旦これで.
Functions に以下の関数を追加する.
type Deck = {
cards: Card[]
hand: Card[]
}
export const draw = functions.https.onRequest((request, response) => {
const deckRef = fireStore.collection('fields').doc('deck');
fireStore.runTransaction(transaction => {
return transaction.get(deckRef).then((snapshot => {
const deck = snapshot.data() as Deck;
// デックにカードがあれば その先頭を deck.hand に追加して deck.cards からは削除する.
if (deck.cards.length > 0) {
deck.hand.push(deck.cards[0]);
deck.cards.shift();
transaction.update(deckRef, deck);
}
}))
}).then(snapshot => {
response.send('success');
}).catch(err => {
response.status(404).send('not found');
});
});
別段むずかしいことはない. クライアント側にもこの関数を叩くボタンを用意するが, 新しいことはないので省略.
わずかにカードゲームらしさが出てきたが・・・先は長い.
Functions 遅い
なんかレスポンス悪いな, と思って調べると, いくつかつまづきポイントがあるようだ.
cloud functionsに一定期間のアクセスがない場合は、自動的にインスタンスがスリープモードに入る。そのために、しばらくぶりにアクセスがあると、インスタンスが起動するまでに数秒間の時間がかかる。
まぁ仕様ならやむを得ない.
パフォーマンス(処理速度)をあげるには、単純にメモリの割り当て量 (CPU の割り当て量) を増やせばよいです。ただし、比例して料金も増加しますので、・・・
当面お金をかけるつもりはないので, なるべくリソースは増やしたくない.
ここで 3つの改善案が紹介されている.
1. 関数のロード時間を改善
2. リージョンを東京にする
3. Firestore になるべくアクセスしない
現段階で打てる手は 2 くらいか.
リージョンが日本じゃないのは気になっていたところだ.
export const shuffle = functions.region('asia-northeast1').https.onRequest(...
呼び出し前に関数1こ挟むだけ. 超簡単. ただし直すとクライアント側のリクエストURLも変わるので注意だ.
結構速くなった.
今まで ざっと Cold Start 5秒 通常時1秒 だったのが, Cold Start 2秒 通常 200ミリ秒 まで改善.
・・・200ミリ秒か. 微妙なラインだ.
カードゲームに銃の撃ち合いほどのリアルタイム性は必要ないと思うが, 使い所は要検討か.
この記事が気に入ったらサポートをしてみませんか?