Skip to content

Commit e1d47f0

Browse files
Oxyjunpedrosousa
andauthored
[DO] Runtime API rename, cleaning up Storage API chapter (#18288)
* Initialising PR for separating Storage API from SQL API. * Explicitly stating "Durable Object Storage API" for consistency. * Removing `ctx.storage.sql` from the definitions of the SQL methods. * Moving point in time recovery section to SQL Storage chapter. * Introducing SqlStorage and Sql properly. * Adding an explanation that KV operations are synchronous for SQLite backed DO. * Adding clarification on asynchronous KV operations. * Adding backticks to all methods in headings. * Fixing broken links part 1 * Fixing broken links part 2. * Apply suggestions from code review Co-authored-by: Pedro Sousa <[email protected]> * Update src/content/docs/durable-objects/api/sql-storage.mdx Co-authored-by: Pedro Sousa <[email protected]> * Fixes from PCX review. --------- Co-authored-by: Pedro Sousa <[email protected]>
1 parent 9fdca24 commit e1d47f0

File tree

14 files changed

+203
-151
lines changed

14 files changed

+203
-151
lines changed

src/content/changelogs/durable-objects.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ entries:
1717
- publish_date: "2024-09-26"
1818
title: (Beta) SQLite storage backend & SQL API available on new Durable Object classes
1919
description: |-
20-
The new beta version of Durable Objects is available where each Durable Object has a private, embedded SQLite database. When deploying a new Durable Object class, users can [opt-in to a SQLite storage backend](/durable-objects/best-practices/access-durable-objects-storage/#sqlite-storage-backend) in order to access new [SQL API](/durable-objects/api/storage-api/#sqlexec) and [point-in-time-recovery API](/durable-objects/api/storage-api/#point-in-time-recovery), part of Durable Objects Storage API.
20+
The new beta version of Durable Objects is available where each Durable Object has a private, embedded SQLite database. When deploying a new Durable Object class, users can [opt-in to a SQLite storage backend](/durable-objects/best-practices/access-durable-objects-storage/#sqlite-storage-backend) in order to access new [SQL API](/durable-objects/api/sql-storage/#exec) and [point-in-time-recovery API](/durable-objects/api/sql-storage/#point-in-time-recovery), part of Durable Objects Storage API.
2121
2222
You cannot enable a SQLite storage backend on an existing, deployed Durable Object class. Automatic migration of deployed classes from their key-value storage backend to SQLite storage backend will be available in the future.
2323

src/content/docs/durable-objects/api/alarms.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Alarms
33
pcx_content_type: concept
44
sidebar:
5-
order: 6
5+
order: 7
66
---
77

88
import { Type, GlossaryTooltip } from "~/components";
@@ -29,20 +29,20 @@ Alarms can be used to build distributed primitives, like queues or batching of w
2929

3030
## Storage methods
3131

32-
### getAlarm
32+
### `getAlarm`
3333

3434
- <code>getAlarm()</code>: <Type text="number | null" />
3535

3636
- If there is an alarm set, then return the currently set alarm time as the number of milliseconds elapsed since the UNIX epoch. Otherwise, return `null`.
3737

38-
### setAlarm
38+
### `setAlarm`
3939

4040
- <code>{" "}setAlarm(scheduledTimeMs <Type text="number" />)</code>
4141
: <Type text="void" />
4242

4343
- Set the time for the alarm to run. Specify the time as the number of milliseconds elapsed since the UNIX epoch.
4444

45-
### deleteAlarm
45+
### `deleteAlarm`
4646

4747
- `deleteAlarm()`: <Type text='void' />
4848

@@ -52,7 +52,7 @@ Alarms can be used to build distributed primitives, like queues or batching of w
5252

5353
## Handler methods
5454

55-
### alarm
55+
### `alarm`
5656

5757
- `alarm()`: <Type text='void' />
5858

src/content/docs/durable-objects/api/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: Runtime APIs
2+
title: Workers Binding API
33
pcx_content_type: navigation
44
sidebar:
55
order: 4
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
---
2+
title: SQL Storage
3+
pcx_content_type: concept
4+
sidebar:
5+
order: 5
6+
7+
---
8+
9+
import { Render, Type, MetaInfo, GlossaryTooltip } from "~/components";
10+
11+
The `SqlStorage` interface encapsulates methods that modify the SQLite database embedded within a Durable Object. The `SqlStorage` interface is accessible via the `sql` property of `DurableObjectStorage` class.
12+
13+
For example, using `sql.exec()`, a user can create a table, then insert rows into the table.
14+
15+
```ts
16+
import { DurableObject } from "cloudflare:workers";
17+
18+
export class MyDurableObject extends DurableObject {
19+
sql: SqlStorage;
20+
constructor(ctx: DurableObjectState, env: Env) {
21+
super(ctx, env);
22+
this.sql = ctx.storage.sql;
23+
24+
this.sql.exec(`CREATE TABLE IF NOT EXISTS artist(
25+
artistid INTEGER PRIMARY KEY,
26+
artistname TEXT
27+
);INSERT INTO artist (artistid, artistname) VALUES
28+
(123, 'Alice'),
29+
(456, 'Bob'),
30+
(789, 'Charlie');`
31+
);
32+
}
33+
}
34+
```
35+
36+
:::note[SQLite in Durable Objects Beta]
37+
SQL API methods accessed with `ctx.storage.sql` are only allowed on [Durable Object classes with SQLite storage backend](/durable-objects/reference/durable-objects-migrations/#enable-sqlite-storage-backend-on-new-durable-object-class-migration) and will return an error if called on Durable Object classes with a key-value storage backend.
38+
:::
39+
40+
Specifically for Durable Object classes with SQLite storage backend, KV operations which were previously asynchronous (for example, [`get`](/durable-objects/api/storage-api/#get), [`put`](/durable-objects/api/storage-api/#put), [`delete`](/durable-objects/api/storage-api/#delete), [`deleteAll`](/durable-objects/api/storage-api/#deleteall), [`list`](/durable-objects/api/storage-api/#list)) are synchronous, even though they return promises. These methods will have completed their operations before they return the promise.
41+
42+
## Methods
43+
44+
### `exec`
45+
46+
<code>exec(query: <Type text='string'/>, ...bindings: <Type text='any[]'/>)</code>: <Type text='SqlStorageCursor' />
47+
48+
#### Parameters
49+
50+
* `query`: <Type text ='string' />
51+
* The SQL query string to be executed. `query` can contain `?` placeholders for parameter bindings. Multiple SQL statements, separated with a semicolon, can be executed in the `query`. With multiple SQL statements, any parameter bindings are applied to the last SQL statement in the `query`, and the returned cursor is only for the last SQL statement.
52+
* `bindings`: <Type text='any[]' /> <MetaInfo text='Optional' />
53+
* Optional variable number of arguments that correspond to the `?` placeholders in `query`.
54+
55+
#### Returns
56+
57+
A cursor (`SqlStorageCursor`) to iterate over query row results as objects. `SqlStorageCursor` is a JavaScript [Iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol), which supports iteration using `for (let row of cursor)`. `SqlStorageCursor` is also a JavaScript [Iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol), which supports iteration using `cursor.next()`.
58+
59+
`SqlStorageCursor` supports the following methods:
60+
61+
* `next()`
62+
* Returns an object representing the next value of the cursor. The returned object has `done` and `value` properties adhering to the JavaScript [Iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol). `done` is set to `false` when a next value is present, and `value` is set to the next row object in the query result. `done` is set to `true` when the entire cursor is consumed, and no `value` is set.
63+
* `toArray()`
64+
* Iterates through remaining cursor value(s) and returns an array of returned row objects.
65+
* `one()`
66+
* Returns a row object if query result has exactly one row. If query result has zero rows or more than one row, `one()` throws an exception.
67+
* `raw()`: <Type text='Iterator' />
68+
* Returns an Iterator over the same query results, with each row as an array of column values (with no column names) rather than an object.
69+
* Returned Iterator supports `next()`, `toArray()`, and `one()` methods above.
70+
* Returned cursor and `raw()` iterator iterate over the same query results and can be combined. For example:
71+
72+
```ts
73+
let cursor = this.sql.exec("SELECT * FROM artist ORDER BY artistname ASC;");
74+
let rawResult = cursor.raw().next();
75+
76+
if (!rawResult.done) {
77+
console.log(rawResult.value); // prints [ 123, 'Alice' ]
78+
} else {
79+
// query returned zero results
80+
}
81+
82+
console.log(cursor.toArray()); // prints [{ artistid: 456, artistname: 'Bob' },{ artistid: 789, artistname: 'Charlie' }]
83+
```
84+
85+
`SqlStorageCursor` had the following properties:
86+
87+
* `columnNames`: <Type text='string[]' />
88+
* The column names of the query in the order they appear in each row array returned by the `raw` iterator.
89+
* `rowsRead`: <Type text='number' />
90+
* The number of rows read so far as part of this SQL `query`. This may increase as you iterate the cursor. The final value is used for [SQL billing](/durable-objects/platform/pricing/#sqlite-storage-backend).
91+
* `rowsWritten`: <Type text='number' />
92+
* The number of rows written so far as part of this SQL `query`. This may increase as you iterate the cursor. The final value is used for [SQL billing](/durable-objects/platform/pricing/#sqlite-storage-backend).
93+
94+
Note that `sql.exec()` cannot execute transaction-related statements like `BEGIN TRANSACTION` or `SAVEPOINT`. Instead, use the [`ctx.storage.transaction()`](#transaction) or [`ctx.storage.transactionSync()`](#transactionsync) APIs to start a transaction, and then execute SQL queries in your callback.
95+
96+
#### Examples
97+
98+
<Render file="durable-objects-sql" />
99+
100+
### `databaseSize`
101+
102+
`databaseSize`: <Type text ='number' />
103+
104+
#### Returns
105+
106+
The current SQLite database size in bytes.
107+
108+
```ts
109+
let size = ctx.storage.sql.databaseSize;
110+
```
111+
112+
## Point in time recovery
113+
114+
For [Durable Objects classes with SQL storage](/durable-objects/reference/durable-objects-migrations/#enable-sqlite-storage-backend-on-new-durable-object-class-migration), the following point-in-time-recovery (PITR) API methods are available to restore a Durable Object's embedded SQLite database to any point in time in the past 30 days. These methods apply to the entire SQLite database contents, including both the object's stored SQL data and stored key-value data using the key-value `put()` API. The PITR API is not supported in local development because a durable log of data changes is not stored locally.
115+
116+
The PITR API represents points in times using 'bookmarks'. A bookmark is a mostly alphanumeric string like `0000007b-0000b26e-00001538-0c3e87bb37b3db5cc52eedb93cd3b96b`. Bookmarks are designed to be lexically comparable: a bookmark representing an earlier point in time compares less than one representing a later point, using regular string comparison.
117+
118+
### `getCurrentBookmark`
119+
120+
<code>ctx.storage.getCurrentBookmark()</code>: <Type text='Promise<string>' />
121+
122+
* Returns a bookmark representing the current point in time in the object's history.
123+
124+
### `getBookmarkForTime`
125+
126+
<code>ctx.storage.getBookmarkForTime(timestamp: <Type text='number | Date'/>)</code>: <Type text='Promise<string>' />
127+
128+
* Returns a bookmark representing approximately the given point in time, which must be within the last 30 days. If the timestamp is represented as a number, it is converted to a date as if using `new Date(timestamp)`.
129+
130+
### `onNextSessionRestoreBookmark`
131+
132+
<code>ctx.storage.onNextSessionRestoreBookmark(bookmark: <Type text='string'/>)</code>: <Type text='Promise<string>' />
133+
134+
* Configures the Durable Object so that the next time it restarts, it should restore its storage to exactly match what the storage contained at the given bookmark. After calling this, the application should typically invoke `ctx.abort()` to restart the Durable Object, thus completing the point-in-time recovery.
135+
136+
This method returns a special bookmark representing the point in time immediately before the recovery takes place (even though that point in time is still technically in the future). Thus, after the recovery completes, it can be undone by performing a second recovery to this bookmark.
137+
138+
139+
```ts
140+
let now = new Date();
141+
// restore to 2 days ago
142+
let bookmark = ctx.storage.getBookmarkForTime(now - 2);
143+
ctx.storage.onNextSessionRestoreBookmark(bookmark);
144+
```

0 commit comments

Comments
 (0)