Skip to content

Commit beb3e61

Browse files
committed
Inserting example which uses cookies to retrieve
bookmarks. Adding how to enable / check if enabled
1 parent 8d13b91 commit beb3e61

File tree

1 file changed

+128
-21
lines changed

1 file changed

+128
-21
lines changed

src/content/docs/d1/features/read-replication.mdx

Lines changed: 128 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,30 @@ By using <GlossaryTooltip term="session">Sessions API</GlossaryTooltip> for read
5252

5353
D1 read replication achieves this by attaching a <GlossaryTooltip term="bookmark">bookmark</GlossaryTooltip> to each write query within a Session. For more information, refer to [Bookmarks](/d1/reference/time-travel/#bookmarks).
5454

55-
### Enable read replication
55+
### Check if read replication is enabled
56+
57+
The following code uses REST API to check if read replication is enabled / disabled.
58+
59+
```ts
60+
const headers = new Headers({
61+
"Authorization": `Bearer ${TOKEN}`
62+
});
63+
64+
const response = await fetch("/v4/accounts/{account_id}/d1/database/{database_id}", {
65+
method: "GET",
66+
headers: headers
67+
});
68+
69+
const data = await response.json();
70+
console.log(data.read_replication.mode);
71+
```
72+
73+
- If the output is `auto`, read replication is enabled.
74+
- If the output is `disabled`, read replication is disabled.
75+
76+
### Enable or disable read replication
5677

57-
Use REST API to enable read replication on your D1 database.
78+
Use REST API to enable / disable read replication on your D1 database.
5879

5980
```ts
6081
const headers = new Headers({
@@ -71,6 +92,9 @@ await fetch ("/v4/accounts/{account_id}/d1/database/{database_id}", {
7192
)
7293
```
7394

95+
- Set `"mode":"auto"` to enable read replication.
96+
- Set `"mode":"disable"` to disable read replication.
97+
7498
If this is your first time using REST API, create an API token. Refer to [Create API token](/fundamentals/api/get-started/create-token/).
7599

76100
### Start a D1 Session without constraints
@@ -146,23 +170,23 @@ In this scenario, you want the first request of the page to show a list of all t
146170
Then, when opening an individual electricity bill statement, we can continue using the same Session by passing the `bookmark` from the first query to subsequent requests. Since each bill statement is immutable, any bill statement listed from the first query is guaranteed to be available in subsequent requests using the same Session.
147171
148172
```ts
149-
async function listBillStatements(accountId: string, db: D1Database): ListBillStatementsResult {
150-
const session = db.withSession("first-primary");
151-
const { results } = session
152-
.prepare("SELECT * FROM bills WHERE accountId = ?")
153-
.bind(accountId)
154-
.run();
155-
return { bookmark: session.getBookmark(), bills: results };
173+
async function listBillStatements(accountId: string, db: D1Database): Promise<ListBillStatementsResult> {
174+
const session = db.withSession('first-primary');
175+
const { results } = (await session.prepare('SELECT * FROM bills WHERE accountId = ?').bind(accountId).run()) as unknown as {
176+
results: Bill[];
177+
};
178+
return { bookmark: session.getBookmark() ?? 'first-unconstrained', bills: results };
156179
}
157180

158-
async function getBillStatement(accountId: string, billId: string, bookmark: string): GetBillStatementResult {
159-
// NOTE: We achieve sequential consistency with the given `bookmark`.
160-
const session = db.withSession(bookmark);
161-
const { results } = session
162-
.prepare("SELECT * FROM bills WHERE accountId = ? AND billId = ? LIMIT 1")
163-
.bind(accountId, billId)
164-
.first();
165-
return { bookmark: session.getBookmark(), bill: results };
181+
async function getBillStatement(accountId: string, billId: string, bookmark: string, db: D1Database): Promise<GetBillStatementResult> {
182+
// NOTE: We achieve sequential consistency with the given `bookmark`.
183+
const session = db.withSession(bookmark);
184+
const result = (await session
185+
.prepare('SELECT * FROM bills WHERE accountId = ? AND billId = ? LIMIT 1')
186+
.bind(accountId, billId)
187+
.first()) as unknown as Bill;
188+
189+
return { bookmark: session.getBookmark() ?? 'first-unconstrained', bill: result };
166190
}
167191
```
168192
@@ -189,16 +213,99 @@ const result = await session.run()
189213
190214
#### Example of using `bookmark`
191215
216+
This example follows from [Example of using `first-primary`](/d1/features/read-replication/#example-of-using-first-primary), but retrieves the `bookmark` from HTTP cookie.
192217
218+
```ts collapse={1-10, 22-42, 61-86}
219+
import { ListBillStatementsResult, GetBillStatementResult, Bill } from './types';
193220

194-
```ts
195-
//TBC
221+
async function listBillStatements(accountId: string, db: D1Database): Promise<ListBillStatementsResult> {
222+
const session = db.withSession('first-primary');
223+
const { results } = (await session.prepare('SELECT * FROM bills WHERE accountId = ?').bind(accountId).run()) as unknown as {
224+
results: Bill[];
225+
};
226+
return { bookmark: session.getBookmark() ?? 'first-unconstrained', bills: results };
227+
}
228+
229+
async function getBillStatement(accountId: string, billId: string, bookmark: string, db: D1Database): Promise<GetBillStatementResult> {
230+
// NOTE: We achieve sequential consistency with the given `bookmark`.
231+
const session = db.withSession(bookmark);
232+
const result = (await session
233+
.prepare('SELECT * FROM bills WHERE accountId = ? AND billId = ? LIMIT 1')
234+
.bind(accountId, billId)
235+
.first()) as unknown as Bill;
236+
237+
return { bookmark: session.getBookmark() ?? 'first-unconstrained', bill: result };
238+
}
239+
240+
export default {
241+
async fetch(request, env, ctx): Promise<Response> {
242+
// URL path
243+
const url = new URL(request.url);
244+
const path = url.pathname;
245+
246+
// Method
247+
const method = request.method;
248+
249+
// Fetch using first-unconstrained
250+
if (path === '/bills' && method === 'GET') {
251+
// List bills
252+
const result = await listBillStatements('1', env.DB);
253+
return new Response(JSON.stringify(result), { status: 200 });
254+
}
255+
if (path === '/bill' && method === 'GET') {
256+
// Get bill
257+
const result = await getBillStatement('1', '1', 'first-unconstrained', env.DB);
258+
return new Response(JSON.stringify(result), { status: 200 });
259+
}
260+
261+
// Fetch using bookmark from cookie
262+
if (path === '/bill/cookie' && method === 'GET') {
263+
// Get bill
264+
const cookie = request.headers.get('Cookie');
265+
const bookmark =
266+
cookie
267+
?.split(';')
268+
.find((c) => c.trim().startsWith('X-D1-Bookmark'))
269+
?.split('=')[1] ?? 'first-unconstrained';
270+
console.log('bookmark', bookmark);
271+
const result = await getBillStatement('1', '1', bookmark, env.DB);
272+
return new Response(JSON.stringify(result), {
273+
status: 200,
274+
headers: {
275+
'Set-Cookie': `X-D1-Bookmark=${result.bookmark}; Path=/; SameSite=Strict`,
276+
},
277+
});
278+
}
279+
280+
// To ingest data
281+
if (path === '/bill' && method === 'POST') {
282+
// Create bill
283+
const { accountId, amount, description, due_date } = await request.json();
284+
const session = env.DB.withSession('first-primary');
285+
const { results } = await session
286+
.prepare('INSERT INTO bills (accountId, amount, description, due_date) VALUES (?, ?, ?, ?) RETURNING *')
287+
.bind(accountId, amount, description, due_date)
288+
.run();
289+
const bookmark = session.getBookmark() ?? 'first-unconstrained';
290+
291+
return new Response(JSON.stringify(results), {
292+
status: 201,
293+
headers: {
294+
// Set bookmark cookie
295+
'Set-Cookie': `X-D1-Bookmark=${bookmark}; Path=/; SameSite=Strict`,
296+
},
297+
});
298+
}
299+
return new Response('Not Found', {
300+
status: 404,
301+
statusText: 'Not Found',
302+
});
303+
},
304+
} satisfies ExportedHandler<Env>;
196305
```
197306
198307
### Check if read replication is enabled
199308
200-
### Disable read replication
201-
202309
203310
204311
## Read replica locations

0 commit comments

Comments
 (0)