|
| 1 | +# firestore-sharded-counter |
| 2 | + |
| 3 | +**DESCRIPTION**: Auto-scalable counters for your app. |
| 4 | + |
| 5 | + |
| 6 | +**FEATURES**: |
| 7 | + |
| 8 | +- Zero configuration, one mod for all your app needs |
| 9 | +- Automatically scales from 0 updates/sec to at least 10k updates/sec |
| 10 | +- Efficient for very low traffic counters |
| 11 | +- Handles gracefully bursts of up to thousands updates/sec |
| 12 | +- Can support thousands of updates/sec per counter and millions of counters in an app |
| 13 | +- Works well offline and provides latency compensation |
| 14 | + - Counter updates are immediately visible locally even though the main counter is eventually updated |
| 15 | + |
| 16 | + |
| 17 | +**DETAILS**: This mod allows you to increment any fields in your documents at arbitrary rate. |
| 18 | + |
| 19 | +Client SDK, instead of incrementing the field directly, increments their own shard in `_counter_shards_` subcollection. A background task is periodically aggregating these shards and eventually rolling them up to the main counters. |
| 20 | + |
| 21 | +There are three cloud functions that orchestrate shard aggregations: |
| 22 | +1. A `worker` function is responsible for monitoring and aggregating a range of shards. There may be 0 or hundreds of workers running concurrently to scale up to large workloads |
| 23 | +2. A `controller` function runs every minute and monitors the health of the workers. It can scale up and down the number of workers as needed and recover a worker on failure. |
| 24 | +3. A `onWrite` function triggers every time a shard is written and runs one-time aggregation. This improves latency for low workloads where no workers is running. To improve efficiency there's only one instance of this function running at any given time (`maxInstances` is set to 1). |
| 25 | + |
1 | 26 | # Installation
|
2 |
| -`firebase mods:install . --project=<my-project-id>` |
| 27 | +``` |
| 28 | +firebase mods:install . --project=<my-project-id> |
| 29 | +
|
| 30 | +Please check the post-install message for the final step to set up your mod. |
| 31 | +``` |
3 | 32 |
|
4 | 33 | # Web SDK
|
5 | 34 | ```
|
|
11 | 40 | </head>
|
12 | 41 | <body>
|
13 | 42 | <script>
|
14 |
| - // Initialize Firebase |
| 43 | + // Initialize Firebase. |
15 | 44 | var config = {};
|
16 | 45 | firebase.initializeApp(config);
|
17 | 46 | var db = firebase.firestore();
|
18 | 47 |
|
19 |
| - // Initialize counter |
| 48 | + // Initialize the sharded counter. |
20 | 49 | var views = new sharded.Counter(db.doc("pages/hello-world"), "stats.views");
|
21 | 50 |
|
22 |
| - // Increment the counter |
23 |
| - views.incrementBy(firebase.firestore.FieldValue.increment(3)); |
| 51 | + // This will increment a field "stats.views" of the "pages/hello-world" document by 3. |
| 52 | + views.incrementBy(3); |
24 | 53 |
|
25 | 54 | // Listen to locally consistent values
|
26 | 55 | views.onSnapshot((snap) => {
|
27 |
| - console.log("Visits: " + snap.data()); |
| 56 | + console.log("Locally consistent view of visits: " + snap.data()); |
28 | 57 | });
|
| 58 | +
|
| 59 | + // Alternatively if you don't mind counter delays, you can listen to the document directly. |
| 60 | + db.doc("pages/hello-world").onSnapshot((snap) => { |
| 61 | + console.log("Eventually consistent view of visits: " + snap.get("stats.views")); |
| 62 | + }) |
29 | 63 | </script>
|
30 | 64 | </body>
|
31 | 65 | </html>
|
|
36 | 70 | cd functions/
|
37 | 71 | npm install
|
38 | 72 | npm run build
|
39 |
| -``` |
| 73 | +``` |
0 commit comments