Skip to content

Commit d34bd4f

Browse files
committed
Zero 0.18
1 parent a46158c commit d34bd4f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+857
-1389
lines changed
File renamed without changes.
File renamed without changes.
File renamed without changes.

contents/docs/custom-mutators.mdx

Lines changed: 495 additions & 0 deletions
Large diffs are not rendered by default.

contents/docs/debug/inspector.mdx

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
title: Inspector API
3+
---
4+
5+
The Zero instance provides an API to gather information about the client's current state, such as:
6+
7+
* All active queries
8+
* Query TTL
9+
* Active clients
10+
* Client database contents
11+
12+
This can help figuring out why you hit loading states, how many queries are active at a time, if you have any resource leaks due to failing to clean up queries or if expected data is missing on the client.
13+
14+
## Creating an Inspector
15+
16+
Each `Zero` instance has an `inspect` method that will return the inspector.
17+
18+
```ts
19+
const z = new Zero({
20+
/*your zero options*/
21+
});
22+
const inspector = await z.inspect();
23+
```
24+
25+
Once you have an inspector you can inspect the current client and client group.
26+
27+
<Note heading="Clients and Client Groups">
28+
The client group represents a web browser profile. A client represents an
29+
instance of `Zero` within that profile. If a user has Chrome open with 5
30+
different tabs, each with one `Zero` instance, there will be 1 client
31+
group and 5 clients.
32+
</Note>
33+
34+
For example to see active queries for the current client:
35+
36+
```ts
37+
console.table(await inspector.client.queries());
38+
```
39+
40+
To inspect other clients within the group:
41+
42+
```ts
43+
const allClients = await inspector.clients();
44+
```
45+
46+
## Dumping Data
47+
48+
In addition to information about queries, you can see the contents of the client side database.
49+
50+
```ts
51+
const inspector = await zero.inspect();
52+
const client = inspector.client;
53+
54+
// All raw k/v data currently synced to client
55+
console.log('client map:');
56+
console.log(await client.map());
57+
58+
// kv table extracted into tables
59+
// This is same info that is in z.query[tableName].run()
60+
for (const tableName of Object.keys(schema.tables)) {
61+
console.log(`table ${tableName}:`);
62+
console.table(await client.rows(tableName));
63+
}
64+
```
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
title: Debugging Permissions
3+
---
4+
5+
Given that permissions are defined in their own file and internally applied to queries, it might be hard to figure out if or why a permission check is failing.
6+
7+
## Read Permissions
8+
9+
The `transform-query` utility is provided to transform a query by applying permissions to it. As of today you'll need to provide the hash of the query you want to transform. You can find this in server logs, websocket network inspector, or in the CVR database. In a future release, you'll be able to write ZQL directly.
10+
11+
```ts
12+
npx transform-query --hash=2i81bazy03a00 --schema=./shared/schema.ts
13+
```
14+
15+
The output will be the ZQL query with permissions applied as well as the AST of that query.
16+
17+
<Note type="note">
18+
The printed AST is slightly different than the source ZQL string as it
19+
leverages internal APIs to prevent syncing rows that are used strictly for
20+
permission checks.
21+
</Note>
22+
23+
## Write Permissions
24+
25+
Look for a `WARN` level log in the output from `zero-cache` like this:
26+
27+
```
28+
Permission check failed for {"op":"update","tableName":"message",...}, action update, phase preMutation, authData: {...}, rowPolicies: [...], cellPolicies: []
29+
```
30+
31+
Zero prints the row, auth data, and permission policies that was applied to any failed writes.
32+
33+
<Note>
34+
The ZQL query is printed in AST format. See [Query ASTs](./query-asts) to convert it to a more readable format.
35+
</Note>

contents/docs/debug/query-asts.mdx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
title: Query ASTs
3+
---
4+
5+
An AST (Abstract Syntax Tree) is a representation of a query that is used internally by Zero. It is not meant to be human readable, but it sometimes shows up in logs and other places.
6+
7+
If you need to read one of these, save the AST to a json file. Then run the following command:
8+
9+
```bash
10+
cat ast.json | npx ast-to-zql
11+
```
12+
13+
The returned ZQL query will be using server names, rather than client names, to identify columns and tables.
14+
If you provide the schema file as an option you will get mapped back to client names:
15+
16+
```bash
17+
cat ast.json | npx ast-to-zql --schema schema.ts
18+
```
19+
20+
This comes into play if, in your schema.ts, you use the `from` feature to have different names on the client than your backend DB.
21+
22+
<Note type="note">
23+
The `ast-to-zql` process is a de-compilation of sorts. Given that, the ZQL
24+
string you get back will not be identical to the one you wrote in your
25+
application. Regardless, the queries will be semantically equivalent.
26+
</Note>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
title: Replication
3+
---
4+
5+
## Resetting
6+
7+
During development we all do strange things (unsafely changing schemas, removing files, etc.). If the replica ever gets wedged (stops replicating, acts strange) you can wipe it and start over.
8+
9+
- If you copied your setup from `hello-zero` or `hello-zero-solid`, you can also run `npm run dev:clean`
10+
- Otherwise you can run `rm /tmp/my-zero-replica.db*` (see your `.env` file for the replica file location) to clear the contents of the replica.
11+
12+
It is always safe to wipe the replica. Wiping will have no impact on your upstream database. Downstream zero-clients will get re-synced when they connect.
13+
14+
## Inspecting
15+
16+
For data to be synced to the client it must first be replicated to `zero-cache`. You can check the contents of `zero-cache` via:
17+
18+
```bash
19+
$ npx zero-sqlite3 /tmp/my-zero-replica.db
20+
```
21+
22+
This will drop you into a `sqlite3` shell with which you can use to explore the contents of the replica.
23+
24+
```sql
25+
sqlite> .tables
26+
_zero.changeLog emoji viewState
27+
_zero.replicationConfig issue zero.permissions
28+
_zero.replicationState issueLabel zero.schemaVersions
29+
_zero.runtimeEvents label zero_0.clients
30+
_zero.versionHistory user
31+
comment userPref
32+
sqlite> .mode qbox
33+
sqlite> SELECT * FROM label;
34+
┌─────────────────────────┬──────────────────────────┬────────────┐
35+
│ id │ name │ _0_version │
36+
├─────────────────────────┼──────────────────────────┼────────────┤
37+
'ic_g-DZTYDApZR_v7Cdcy''bug''4ehreg'
38+
...
39+
```
40+
41+
## Miscellaneous
42+
43+
If you see `FATAL: sorry, too many clients already` in logs, it’s because you have two zero-cache instances running against dev. One is probably in a background tab somewhere. In production, `zero-cache` can run horizontally scaled but on dev it doesn’t run in the config that allows that.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
title: Slow Queries (zero-cache)
3+
---
4+
5+
In the `zero-cache` logs, you may see statements indicating a query is slow:
6+
7+
```shell
8+
{
9+
"level": "DEBUG",
10+
"worker": "syncer",
11+
"component": "view-syncer",
12+
"hydrationTimeMs": 1339,
13+
"message": "Total rows considered: 146"
14+
},
15+
```
16+
17+
or:
18+
19+
```shell
20+
hash=3rhuw19xt9vry transformationHash=1nv7ot74gxfl7
21+
Slow query materialization 325.46865100000286
22+
```
23+
24+
Here are some tips to help debug such slow queries.
25+
26+
## Check Storage
27+
28+
`zero-cache` is effectively a database. It requires fast (low latency and high bandwidth) disk access to perform well. If you're running on network attached storage with high latency, or on AWS with low IOPS, then this is the most likely culprit.
29+
30+
The default deployment of Zero currently uses Fargate which scales IOPS with vCPU. Increasing the vCPU will increase storage throughput and likely resolve the issue.
31+
32+
Fly.io provides physically attached SSDs, even for their smallest VMs. Deploying zero-cache there (or any other provider that offers physically attached SSDs) is another option.
33+
34+
## Locality
35+
36+
If you see log lines like:
37+
38+
```shell
39+
flushed cvr ... (124ms)
40+
```
41+
42+
this indicates that `zero-cache` is likely deployed too far away from your [CVR database](../deployment#architecture). If you did not configure a CVR database URL then this will be your product's Postgres DB. A slow CVR flush can slow down Zero, since it must complete the flush before sending query result(s) to clients.
43+
44+
Try moving `zero-cache` to be deployed as close as possible to the CVR database.
45+
46+
## Query Plan
47+
48+
If neither (1) nor (2) is a problem, then the query itself is the most likely culprit. The `@rocicorp/zero` package ships with a query analyzer to help debug this.
49+
50+
The analyzer should be run in the directory that contains the `.env` file for `zero-cache` as it will use the `.env` file to find your replica.
51+
52+
Example:
53+
54+
```shell
55+
npx analyze-query \
56+
--schema=./shared/schema.ts \
57+
--query='issue.related("comments")'
58+
```
59+
60+
This will output the query plan and time to execute each phase of that plan.
61+
62+
If you're unsure which query is slow, or you do not know what it looks like after permissions have been applied, you can obtain the query from the hash that is output in the server logs (e.g., `hash=3rhuw19xt9vry`):
63+
64+
```shell
65+
npx transform-query --hash=2i81bazy03a00 --schema=./shared/schema.ts
66+
```
67+
68+
This will find the query with that hash in the CVR DB and output the ZQL for that query, with all read permissions applied. You can then feed this output into `analyze-query`.
File renamed without changes.

0 commit comments

Comments
 (0)