Skip to content

Commit 1137aa0

Browse files
andrewincbshaffer
authored andcommitted
Firestore distributed counters samples (GoogleCloudPlatform#975)
1 parent 859fd32 commit 1137aa0

File tree

6 files changed

+242
-0
lines changed

6 files changed

+242
-0
lines changed

firestore/composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
"src/end_at_field_query_cursor.php",
2525
"src/get_all.php",
2626
"src/get_all_docs.php",
27+
"src/get_distributed_counter_value.php",
2728
"src/get_document.php",
2829
"src/get_multiple_docs.php",
2930
"src/initialize.php",
31+
"src/initialize_distributed_counter.php",
3032
"src/initialize_project_id.php",
3133
"src/invalid_range_order_by_query.php",
3234
"src/invalid_range_query.php",
@@ -49,6 +51,7 @@
4951
"src/start_at_field_query_cursor.php",
5052
"src/start_at_snapshot_query_cursor.php",
5153
"src/subcollection_ref.php",
54+
"src/update_distributed_counter.php",
5255
"src/update_doc.php",
5356
"src/update_doc_array.php",
5457
"src/update_nested_fields.php",

firestore/firestore.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,57 @@
939939
})
940940
);
941941

942+
//Create distributed counter
943+
$application->add((new Command('initialize-distributed-counter'))
944+
->setDefinition($inputDefinition)
945+
->setDescription('Creates a subcollection from the specified multiple shards.')
946+
->setHelp(<<
947+
The %command.name% command creates a distributed counter as a sub collection in Google Cloud Firestore, consisting of several empty shards.
948+
949+
php %command.full_name%
950+
951+
EOF
952+
)
953+
->setCode(function ($input, $output) {
954+
$projectId = $input->getArgument('project');
955+
initialize_distributed_counter($projectId);
956+
})
957+
);
958+
959+
//Increment (distributed counter)
960+
$application->add((new Command('update-distributed-counter'))
961+
->setDefinition($inputDefinition)
962+
->setDescription('Increments a randomly picked shard of a distributed counter.')
963+
->setHelp(<<
964+
The %command.name% command increments the randomly selected shard of a distributed counter using the Google Cloud Firestore API.
965+
966+
php %command.full_name%
967+
968+
EOF
969+
)
970+
->setCode(function ($input, $output) {
971+
$projectId = $input->getArgument('project');
972+
update_distributed_counter($projectId);
973+
})
974+
);
975+
976+
//get value (distributed counter)
977+
$application->add((new Command('get-distributed-counter-value'))
978+
->setDefinition($inputDefinition)
979+
->setDescription('Returns the total count across all the shards of a distributed counter.')
980+
->setHelp(<<
981+
The %command.name% command returns the total count across all the shards of a distributed counter, using the Google Cloud Firestore API.
982+
983+
php %command.full_name%
984+
985+
EOF
986+
)
987+
->setCode(function ($input, $output) {
988+
$projectId = $input->getArgument('project');
989+
get_distributed_counter_value($projectId);
990+
})
991+
);
992+
942993
// for testing
943994
if (getenv('PHPUNIT_TESTS') === '1') {
944995
return $application;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
2+
/**
3+
* Copyright 2019 Google LLC.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
/**
19+
* For instructions on how to run the full sample:
20+
*
21+
* @see https://github.com/GoogleCloudPlatform/php-docs-samples/tree/master/firestore/README.md
22+
*/
23+
24+
namespace Google\Cloud\Samples\Firestore;
25+
26+
use Google\Cloud\Firestore\FirestoreClient;
27+
28+
/**
29+
* Returns a total count across all shards of distributed counter.
30+
* ```
31+
* get_distributed_counter_value('your-project-id');
32+
* ```
33+
*/
34+
function get_distributed_counter_value($projectId)
35+
{
36+
// Create the Cloud Firestore client
37+
$db = new FirestoreClient([
38+
'projectId' => $projectId,
39+
]);
40+
$ref = $db->collection('Shards_collection')->document('Distributed_counters');
41+
# [START fs_get_distributed_counter_value]
42+
$result = 0;
43+
$docCollection = $ref->collection('SHARDS')->documents();
44+
foreach ($docCollection as $doc) {
45+
$result += $doc->data()['Cnt'];
46+
}
47+
# [END fs_get_distributed_counter_value]
48+
printf('The current value of the distributed counter: %d' . PHP_EOL, $result);
49+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
2+
/**
3+
* Copyright 2019 Google Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
/**
19+
* For instructions on how to run the full sample:
20+
*
21+
* @see https://github.com/GoogleCloudPlatform/php-docs-samples/tree/master/firestore/README.md
22+
*/
23+
24+
namespace Google\Cloud\Samples\Firestore;
25+
26+
use Google\Cloud\Firestore\FirestoreClient;
27+
28+
/**
29+
* Creates the specified multiple shards as a subcollection.
30+
* ```
31+
* initialize_distributed_counter('your-project-id');
32+
* ```
33+
*/
34+
function initialize_distributed_counter($projectId)
35+
{
36+
// Create the Cloud Firestore client
37+
$db = new FirestoreClient([
38+
'projectId' => $projectId,
39+
]);
40+
$ref = $db->collection('Shards_collection')->document('Distributed_counters');
41+
# [START fs_initialize_distributed_counter]
42+
$numShards = 10;
43+
$colRef = $ref->collection('SHARDS');
44+
for ($i = 0; $i < $numShards; $i++) {
45+
$doc = $colRef->document($i);
46+
$doc->set(['Cnt' => 0]);
47+
}
48+
# [END fs_initialize_distributed_counter]
49+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
2+
/**
3+
* Copyright 2019 Google LLC.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
/**
19+
* For instructions on how to run the full sample:
20+
*
21+
* @see https://github.com/GoogleCloudPlatform/php-docs-samples/tree/master/firestore/README.md
22+
*/
23+
24+
namespace Google\Cloud\Samples\Firestore;
25+
26+
use Google\Cloud\Firestore\FieldValue;
27+
use Google\Cloud\Firestore\FirestoreClient;
28+
29+
/**
30+
* Increments a randomly picked shard of distributed counter.
31+
* ```
32+
* update_distributed_counter('your-project-id');
33+
* ```
34+
*/
35+
function update_distributed_counter($projectId)
36+
{
37+
// Create the Cloud Firestore client
38+
$db = new FirestoreClient([
39+
'projectId' => $projectId,
40+
]);
41+
$ref = $db->collection('Shards_collection')->document('Distributed_counters');
42+
# [START fs_update_distributed_counter]
43+
$colRef = $ref->collection('SHARDS');
44+
$numShards = 0;
45+
$docCollection = $colRef->documents();
46+
foreach ($docCollection as $doc) {
47+
$numShards++;
48+
}
49+
$shardIdx = random_int(0, $numShards-1);
50+
$doc = $colRef->document($shardIdx);
51+
$doc->update([
52+
['path' => 'Cnt', 'value' => FieldValue::increment(1)]
53+
]);
54+
# [END fs_update_distributed_counter]
55+
}

firestore/test/firestoreTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace Google\Cloud\Samples\Firestore\Tests;
1919

20+
use Google\Cloud\Firestore\FirestoreClient;
2021
use Google\Cloud\TestUtils\TestTrait;
2122
use Google\Cloud\TestUtils\ExecuteCommandTrait;
2223
use PHPUnit\Framework\TestCase;
@@ -507,4 +508,38 @@ private function runFirestoreCommand($commandName)
507508
'project' => self::$firestoreProjectId
508509
]);
509510
}
511+
512+
public function testDistributedCounter()
513+
{
514+
$this->runFirestoreCommand('initialize-distributed-counter');
515+
$outputZero = $this->runFirestoreCommand('get-distributed-counter-value');
516+
$this->assertContains('0', $outputZero);
517+
518+
//check count of shards
519+
$db = new FirestoreClient([
520+
'projectId' => self::$firestoreProjectId,
521+
]);
522+
$ref = $db->collection('Shards_collection')->document('Distributed_counters');
523+
$collect = $ref->collection('SHARDS');
524+
$docCollection = $collect->documents();
525+
526+
$docIdList = [];
527+
foreach ($docCollection as $docSnap) {
528+
$docIdList[] = $docSnap->id();
529+
}
530+
$this->assertEquals(10, count($docIdList));
531+
532+
//call thrice and check the value
533+
$this->runFirestoreCommand('update-distributed-counter');
534+
$this->runFirestoreCommand('update-distributed-counter');
535+
$this->runFirestoreCommand('update-distributed-counter');
536+
537+
$output = $this->runFirestoreCommand('get-distributed-counter-value');
538+
$this->assertContains('3', $output);
539+
540+
//remove temporary data
541+
foreach ($docIdList as $docId) {
542+
$collect->document($docId)->delete();
543+
}
544+
}
510545
}

0 commit comments

Comments
 (0)