Skip to content

Instantly share code, notes, and snippets.

@hikiit
Last active June 27, 2019 16:09
Show Gist options
  • Save hikiit/2f31f537064155daa37c23e9e5238066 to your computer and use it in GitHub Desktop.
Save hikiit/2f31f537064155daa37c23e9e5238066 to your computer and use it in GitHub Desktop.
class _CounterPageState extends State<CounterPage> {
final _random = Random();
final _db = Firestore.instance;
// Shardsをすべて削除し、counter1に記載されたShards数で初期化
void _initFirestore() async {
// Shardsサブコレクションがすでに存在しているかチェック
QuerySnapshot shardsSnapshot = await _db
.collection('counters')
.document('counter1')
.collection('shards')
.getDocuments();
if (shardsSnapshot.documents[0].exists) {
// クライアントからのdelete()は非推奨
for (DocumentSnapshot document in shardsSnapshot.documents) {
document.reference.delete();
}
}
// 作成するShards数を取得
var numShardsSnapshot =
await _db.collection('counters').document('counter1').get();
var numShards = numShardsSnapshot['num_shards'];
// batchで一括初期化
var batch = _db.batch();
final counter1 = _db.collection('counters').document('counter1');
for (int i = 0; i < numShards; i++) {
batch.setData(
counter1.collection('shards').document(i.toString()), {'count': 0});
}
batch.commit();
}
// 分散カウンタ
// counter1のサブコレクションであるShardをランダムに1つ選択し、カウントアップ
void _incrementShard() async {
// Shardsの数を取得する
var numShardsSnapshot =
await _db.collection('counters').document('counter1').get();
var numShards = numShardsSnapshot['num_shards'];
// トランザクションでカウントアップ
_db.runTransaction((Transaction tx) async {
final sharedId = _random.nextInt(numShards);
final DocumentReference postRef =
_db.document('/counters/counter1/shards/' + sharedId.toString());
DocumentSnapshot postSnapshot = await tx.get(postRef);
if (postSnapshot.exists) {
await tx.update(
postRef, <String, int>{'count': postSnapshot.data['count'] + 1});
}
});
}
// Shardsサブコレクションに変更があったらShardsサブコレクションを合計値を再計算
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(20.0),
child: StreamBuilder<QuerySnapshot>(
stream: _db
.collection('counters')
.document('counter1')
.collection('shards')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new Text('Loading...');
default:
var count = 0;
for (DocumentSnapshot document in snapshot.data.documents) {
count += document['count'];
}
return Center(child: new Text(count.toString()));
}
},
),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: RaisedButton(
child: Text('初期化'),
color: Colors.lightBlue,
onPressed: () {
_initFirestore();
},
),
),
],
),
floatingActionButton: FloatingActionButton(
// 1タップで100回インクリメントする
onPressed: () {
for (int i = 0; i < 100; i++) {
_incrementShard();
}
},
child: Icon(Icons.thumb_up),
backgroundColor: Colors.pink,
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment