-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[DO] Runtime API rename, cleaning up Storage API chapter #18288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
1c0e919
Initialising PR for separating Storage API from SQL API.
Oxyjun 37b694d
Explicitly stating "Durable Object Storage API" for consistency.
Oxyjun 173f642
Removing `ctx.storage.sql` from the definitions of the SQL methods.
Oxyjun 4785b1b
Moving point in time recovery section to SQL Storage chapter.
Oxyjun 27684e4
Introducing SqlStorage and Sql properly.
Oxyjun 0d5d661
Adding an explanation that KV operations are synchronous for SQLite b…
Oxyjun 36b16e7
Adding clarification on asynchronous KV operations.
Oxyjun ccd6b87
Adding backticks to all methods in headings.
Oxyjun 7cb8b89
Fixing broken links part 1
Oxyjun 8d30e02
Fixing broken links part 2.
Oxyjun bfd4e94
Apply suggestions from code review
Oxyjun 2e31c06
Update src/content/docs/durable-objects/api/sql-storage.mdx
Oxyjun af00991
Fixes from PCX review.
Oxyjun 08fbd59
Merge branch 'jun/do/storage-api-separation' of github.com:cloudflare…
Oxyjun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| --- | ||
| title: Runtime APIs | ||
| title: Workers Binding API | ||
| pcx_content_type: navigation | ||
| sidebar: | ||
| order: 4 | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| --- | ||
| title: SQL Storage | ||
| pcx_content_type: concept | ||
| sidebar: | ||
| order: 5 | ||
|
|
||
| --- | ||
|
|
||
| import { Render, Type, MetaInfo, GlossaryTooltip } from "~/components"; | ||
|
|
||
| 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. | ||
|
|
||
| For example, using `sql.exec()`, a user can create a table, then insert rows into the table. | ||
|
|
||
| ```ts | ||
| import { DurableObject } from "cloudflare:workers"; | ||
|
|
||
| export class MyDurableObject extends DurableObject { | ||
| sql: SqlStorage; | ||
| constructor(ctx: DurableObjectState, env: Env) { | ||
| super(ctx, env); | ||
| this.sql = ctx.storage.sql; | ||
|
|
||
| this.sql.exec(`CREATE TABLE IF NOT EXISTS artist( | ||
| artistid INTEGER PRIMARY KEY, | ||
| artistname TEXT | ||
| );INSERT INTO artist (artistid, artistname) VALUES | ||
| (123, 'Alice'), | ||
| (456, 'Bob'), | ||
| (789, 'Charlie');` | ||
| ); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| :::note[SQLite in Durable Objects Beta] | ||
| 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. | ||
| ::: | ||
|
|
||
| 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. | ||
|
|
||
| ## Methods | ||
|
|
||
| ### `exec` | ||
|
|
||
| <code>exec(query: <Type text='string'/>, ...bindings: <Type text='any[]'/>)</code>: <Type text='SqlStorageCursor' /> | ||
|
|
||
| #### Parameters | ||
|
|
||
| * `query`: <Type text ='string' /> | ||
| * 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. | ||
| * `bindings`: <Type text='any[]' /> <MetaInfo text='Optional' /> | ||
| * Optional variable number of arguments that correspond to the `?` placeholders in `query`. | ||
|
|
||
| #### Returns | ||
|
|
||
| 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()`. | ||
|
|
||
| `SqlStorageCursor` supports the following methods: | ||
|
|
||
| * `next()` | ||
| * 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. | ||
| * `toArray()` | ||
| * Iterates through remaining cursor value(s) and returns an array of returned row objects. | ||
| * `one()` | ||
| * 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. | ||
| * `raw()`: <Type text='Iterator' /> | ||
| * 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. | ||
| * Returned Iterator supports `next()`, `toArray()`, and `one()` methods above. | ||
| * Returned cursor and `raw()` iterator iterate over the same query results and can be combined. For example: | ||
|
|
||
| ```ts | ||
| let cursor = this.sql.exec("SELECT * FROM artist ORDER BY artistname ASC;"); | ||
| let rawResult = cursor.raw().next(); | ||
|
|
||
| if (!rawResult.done) { | ||
| console.log(rawResult.value); // prints [ 123, 'Alice' ] | ||
| } else { | ||
| // query returned zero results | ||
| } | ||
|
|
||
| console.log(cursor.toArray()); // prints [{ artistid: 456, artistname: 'Bob' },{ artistid: 789, artistname: 'Charlie' }] | ||
| ``` | ||
|
|
||
| `SqlStorageCursor` had the following properties: | ||
Oxyjun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| * `columnNames`: <Type text='string[]' /> | ||
| * The column names of the query in the order they appear in each row array returned by the `raw` iterator. | ||
| * `rowsRead`: <Type text='number' /> | ||
| * 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). | ||
| * `rowsWritten`: <Type text='number' /> | ||
| * 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). | ||
|
|
||
| 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. | ||
|
|
||
| #### Examples | ||
|
|
||
| <Render file="durable-objects-sql" /> | ||
|
|
||
| ### `databaseSize` | ||
|
|
||
| `databaseSize`: <Type text ='number' /> | ||
|
|
||
| #### Returns | ||
|
|
||
| The current SQLite database size in bytes. | ||
Oxyjun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ```ts | ||
| let size = ctx.storage.sql.databaseSize; | ||
| ``` | ||
|
|
||
| ## Point in time recovery | ||
|
|
||
| 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. | ||
|
|
||
| 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. | ||
|
|
||
| ### `getCurrentBookmark` | ||
|
|
||
| <code>ctx.storage.getCurrentBookmark()</code>: <Type text='Promise<string>' /> | ||
|
|
||
| * Returns a bookmark representing the current point in time in the object's history. | ||
|
|
||
| ### `getBookmarkForTime` | ||
|
|
||
| <code>ctx.storage.getBookmarkForTime(timestamp: <Type text='number | Date'/>)</code>: <Type text='Promise<string>' /> | ||
|
|
||
| * 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)`. | ||
|
|
||
| ### `onNextSessionRestoreBookmark` | ||
|
|
||
| <code>ctx.storage.onNextSessionRestoreBookmark(bookmark: <Type text='string'/>)</code>: <Type text='Promise<string>' /> | ||
|
|
||
| * 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. | ||
|
|
||
| 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. | ||
|
|
||
|
|
||
| ```ts | ||
| let now = new Date(); | ||
| // restore to 2 days ago | ||
| let bookmark = ctx.storage.getBookmarkForTime(now - 2); | ||
| ctx.storage.onNextSessionRestoreBookmark(bookmark); | ||
| ``` | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.