-
Notifications
You must be signed in to change notification settings - Fork 10k
[DO] Reference DO name using init
#20309
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 9 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
e5b7a95
Merge commit '3dea049f67246f2d1fe1748dab4e40284cb1731a' into jun/do/i…
Oxyjun d8bb9b3
Adding placeholder file
Oxyjun 8413bfa
Merge commit '3bd7c03c761d841684c6135103335750b6ab28f2' into jun/do/i…
Oxyjun 758c810
Setting up file for main code example.
Oxyjun 626846b
Adding new example chapter.
Oxyjun 884dab4
Adding temporary code snippet for workaround.
Oxyjun 4e66eb9
Fixing code block language
Oxyjun aa1f110
Update src/content/docs/durable-objects/examples/reference-do-name-us…
Oxyjun 12d91d9
update the code example
harshil1712 8f9a85c
Quick review + removing TypeScriptExample to avoid
Oxyjun a7206a0
Fixing linebreaks
Oxyjun 167cff9
remove example for D1
harshil1712 75f25c6
Shortening title
Oxyjun 99beb00
Merge branch 'jun/do/idFromName-example' of github.com:cloudflare/clo…
Oxyjun ba418b1
minor updates
harshil1712 5e8f2f8
Merge branch 'jun/do/idFromName-example' of github.com:cloudflare/clo…
harshil1712 c5b22d2
PCX review
Oxyjun cc3db5e
Apply suggestions from code review
Oxyjun e1fe994
Adding minor fix to trigger GH pipeline.
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --- | ||
| type: example | ||
| summary: TBC | ||
| tags: | ||
| - Hono | ||
| - D1 | ||
| pcx_content_type: example | ||
| title: Use `init` RPC call to boostrap you Durable Object | ||
| sidebar: | ||
| order: 13 | ||
| description: TBC | ||
|
|
||
| --- | ||
|
|
||
| import { TabItem, Tabs } from "~/components" | ||
|
|
297 changes: 297 additions & 0 deletions
297
src/content/docs/durable-objects/examples/reference-do-name-using-init.mdx
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,297 @@ | ||
| --- | ||
| type: example | ||
| summary: Access the name from within a Durable Object using RpcTarget. | ||
| tags: | ||
| - Durable Objects | ||
| pcx_content_type: example | ||
| title: Reference a Durable Object name within the Durable Object class using RpcTarget | ||
| sidebar: | ||
| order: 3 | ||
| description: Access the name from within a Durable Object using RpcTarget. | ||
| --- | ||
|
|
||
| import { | ||
| TabItem, | ||
| Tabs, | ||
| GlossaryTooltip, | ||
| TypeScriptExample, | ||
| } from "~/components"; | ||
|
|
||
| Once you create a Durable Object using [`idFromName`](/durable-objects/api/namespace/#idfromname), you cannot access the Durable Object [`name`](/durable-objects/api/id/#name) within the Durable Object class itself. Moreover, if you want to set some metadata for the Durable Object, you can't do it directly in the Durable Object. You will have to pass the metadata to every method you call on the Durable Object. This is not ideal. | ||
|
|
||
| A solution to this is using an `RpcTarget` class. . You can return an instance of this class from the the Durable Object class and use it to configure the Durable Object metadata. | ||
|
|
||
| Based on your needs, you can either store the metadata in the `RpcTarget` class that will be temporary, or use Durable Object storage to store the metadata and reference it in the `RpcTarget` class. | ||
|
|
||
| This example does not persist the Durable Object metadata. It demonstrates how to | ||
|
|
||
| 1. create an `RpcTarget` class | ||
| 2. set the Durable Object metadata (name in this example) in the `RpcTarget` class | ||
| 3. pass the metadata (name in this example) to a Durable Object method | ||
| 4. cleans up the `RpcTarget` class after use | ||
|
|
||
| <TypeScriptExample> | ||
| ```ts | ||
| import { DurableObject, RpcTarget } from 'cloudflare:workers'; | ||
|
|
||
| /** | ||
| * Create an RpcDO class that extends RpcTarget | ||
| * Use this class to set the Durable Object metadata | ||
| * Pass the metadata in the Durable Object methods | ||
| * @param mainDo - The main Durable Object class | ||
| * @param doName - The name of the Durable Object | ||
| */ | ||
|
|
||
| export class RpcDO extends RpcTarget { | ||
| constructor(private mainDo: MyDurableObject, private doName: string) { | ||
| super(); | ||
| } | ||
|
|
||
| /** | ||
| * Pass the name to the Durable Object method | ||
| * @param name - The name to pass to the Durable Object method | ||
| */ | ||
| async passDoName(name: string): Promise<string> { | ||
|
|
||
| // Call the Durable Object method and pass the name and the Durable Object name | ||
| return this.mainDo.getDoName(name, this.doName); | ||
| } | ||
|
|
||
| /** | ||
| * Call the Durable Object method without passing the Durable Object name | ||
| * @param name - The name to pass to the Durable Object method | ||
| */ | ||
| async noDoName(name: string) { | ||
| return this.mainDo.noName(name); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| /** | ||
| * Create a Durable Object class | ||
| * You can use the RpcDO class to set the Durable Object metadata | ||
| */ | ||
|
|
||
| export class MyDurableObject extends DurableObject<Env> { | ||
| constructor(ctx: DurableObjectState, env: Env) { | ||
| super(ctx, env); | ||
| } | ||
|
|
||
| /** | ||
| * Initialize the RpcDO class | ||
| * You can set the Durable Object metadata here | ||
| * It reutrns an instance of the RpcDO class | ||
| * @param doName - The name of the Durable Object | ||
| */ | ||
| async setMetaData(doName: string) { | ||
| return new RpcDO(this, doName); | ||
| } | ||
|
|
||
| /** | ||
| * Function that takes the name and the Durable Object name | ||
| * @param name - The name to pass to the Durable Object method | ||
| * @param doName - The name of the Durable Object | ||
| */ | ||
| async getDoName(name: string, doName: string): Promise<string> { | ||
| console.log({ | ||
| name: name, | ||
| durableObjectName: doName | ||
| }) | ||
| return `Hello, ${name}! The name of this DO is ${doName}`; | ||
| } | ||
|
|
||
| /** | ||
| * Function that is not in the RpcTarget | ||
| * Not every function has to be in the RpcTarget | ||
| */ | ||
|
|
||
| private async notInRpcTarget() { | ||
| return 'This is not in the RpcTarget'; | ||
| } | ||
|
|
||
| /** | ||
| * Function that takes the name and doesn't use the Durable Object name | ||
| * @param name - The name to pass to the Durable Object method | ||
| */ | ||
| async noName(name: string) { | ||
| // Call the private function that is not in the RpcTarget | ||
| console.log(this.notInRpcTarget()); | ||
|
|
||
| return `Hello, ${name}! This doesn't use the DO name.`; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| export default { | ||
| async fetch(request, env, ctx): Promise<Response> { | ||
| let id: DurableObjectId = env.MY_DURABLE_OBJECT.idFromName(new URL(request.url).pathname); | ||
| let stub = env.MY_DURABLE_OBJECT.get(id); | ||
|
|
||
| /** | ||
| * Set the Durable Object metadata using the RpcTarget | ||
| * Notice that no await is needed here | ||
| */ | ||
| const rpcTarget = stub.setMetaData(id.name ?? 'default'); | ||
|
|
||
| // Call the Durable Object method using the RpcTarget. | ||
| // The DO name is passed in the RpcTarget | ||
| const greeting = await rpcTarget.passDoName('world'); | ||
|
|
||
| // Call the Durable Object method that doesn't use the Durable Object name | ||
| const noWow = await rpcTarget.noDoName('world'); | ||
|
|
||
| // Clean up the RpcTarget. | ||
| try { | ||
| (await rpcTarget)[Symbol.dispose]?.(); | ||
| console.log('RpcTarget cleaned up.'); | ||
| } catch (e) { | ||
| console.error({ | ||
| message: 'RpcTarget could not be cleaned up.', | ||
| error: String(e), | ||
| errorPropertirs: e, | ||
| }); | ||
| } | ||
|
|
||
| return new Response(greeting, { status: 200 }); | ||
| }, | ||
|
|
||
| } satisfies ExportedHandler<Env>; | ||
|
|
||
| ``` | ||
| </TypeScriptExample> | ||
|
|
||
| This example persists the Durable Object metadata. It demonstrates similar steps as the previous example, but uses Durable Object storage to store the metadata. | ||
|
|
||
| <TypeScriptExample> | ||
| ```ts | ||
| import { DurableObject, RpcTarget } from 'cloudflare:workers'; | ||
|
|
||
| /** | ||
| * Create an RpcDO class that extends RpcTarget | ||
| * Use this class to set the Durable Object metadata | ||
| * Pass the metadata in the Durable Object methods | ||
| * @param mainDo - The main Durable Object class | ||
| * @param doName - The name of the Durable Object | ||
| */ | ||
|
|
||
| export class RpcDO extends RpcTarget { | ||
| constructor(private mainDo: MyDurableObject, private doName: string) { | ||
| super(); | ||
| } | ||
|
|
||
| /** | ||
| * Pass the name to the Durable Object method | ||
| * @param name - The name to pass to the Durable Object method | ||
| */ | ||
| async passDoName(name: string): Promise<string> { | ||
|
|
||
| // Call the Durable Object method and pass the name and the Durable Object name | ||
| return this.mainDo.getDoName(name, this.doName); | ||
| } | ||
|
|
||
| /** | ||
| * Call the Durable Object method without passing the Durable Object name | ||
| * @param name - The name to pass to the Durable Object method | ||
| */ | ||
| async noDoName(name: string) { | ||
| return this.mainDo.noName(name); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| /** | ||
| * Create a Durable Object class | ||
| * You can use the RpcDO class to set the Durable Object metadata | ||
| */ | ||
|
|
||
| export class MyDurableObject extends DurableObject<Env> { | ||
| constructor(ctx: DurableObjectState, env: Env) { | ||
| super(ctx, env); | ||
| } | ||
|
|
||
| /** | ||
| * Initialize the RpcDO class | ||
| * You can set the Durable Object metadata here | ||
| * It reutrns an instance of the RpcDO class | ||
| * @param doName - The name of the Durable Object | ||
| */ | ||
| async setMetaData(doName: string) { | ||
| // Use DO storage to store the Durable Object name | ||
| await this.ctx.storage.put('doName', doName); | ||
| return new RpcDO(this, doName); | ||
| } | ||
|
|
||
| /** | ||
| * Function that takes the name and the Durable Object name | ||
| * @param name - The name to pass to the Durable Object method | ||
| * @param doName - The name of the Durable Object | ||
| */ | ||
| async getDoName(name: string, doName: string): Promise<string> { | ||
| // If doName is not availabe from the RpcTarget class, get if from the storage | ||
| doName = doName ?? await this.ctx.storage.get('doName'); | ||
| console.log({ | ||
| name: name, | ||
| durableObjectName: doName | ||
| }) | ||
| return `Hello, ${name}! The name of this DO is ${doName}`; | ||
| } | ||
|
|
||
| /** | ||
| * Function that is not in the RpcTarget | ||
| * Not every function has to be in the RpcTarget | ||
| */ | ||
|
|
||
| private async notInRpcTarget() { | ||
| return 'This is not in the RpcTarget'; | ||
| } | ||
|
|
||
| /** | ||
| * Function that takes the name and doesn't use the Durable Object name | ||
| * @param name - The name to pass to the Durable Object method | ||
| */ | ||
| async noName(name: string) { | ||
| // Call the private function that is not in the RpcTarget | ||
| console.log(this.notInRpcTarget()); | ||
|
|
||
| return `Hello, ${name}! This doesn't use the DO name.`; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| export default { | ||
| async fetch(request, env, ctx): Promise<Response> { | ||
| let id: DurableObjectId = env.MY_DURABLE_OBJECT.idFromName(new URL(request.url).pathname); | ||
| let stub = env.MY_DURABLE_OBJECT.get(id); | ||
|
|
||
| /** | ||
| * Set the Durable Object metadata using the RpcTarget | ||
| * Notice that no await is needed here | ||
| */ | ||
| const rpcTarget = stub.setMetaData(id.name ?? 'default'); | ||
|
|
||
| // Call the Durable Object method using the RpcTarget. | ||
| // The DO name is passed in the RpcTarget | ||
| const greeting = await rpcTarget.passDoName('world'); | ||
|
|
||
| // Call the Durable Object method that doesn't use the Durable Object name | ||
| const noWow = await rpcTarget.noDoName('world'); | ||
|
|
||
| // Clean up the RpcTarget. | ||
| try { | ||
| (await rpcTarget)[Symbol.dispose]?.(); | ||
| console.log('RpcTarget cleaned up.'); | ||
| } catch (e) { | ||
| console.error({ | ||
| message: 'RpcTarget could not be cleaned up.', | ||
| error: String(e), | ||
| errorPropertirs: e, | ||
| }); | ||
| } | ||
|
|
||
| return new Response(greeting, { status: 200 }); | ||
| }, | ||
|
|
||
| } satisfies ExportedHandler<Env>; | ||
|
|
||
| ``` | ||
| </TypeScriptExample> | ||
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.