Skip to content
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

Support multi-worker Durable Object RPC #7098

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions fixtures/do-bound/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { DurableObject, RpcTarget } from "cloudflare:workers";

export class ThingObject extends DurableObject {
fetch(request) {
return new Response("hello world");
}
get property() {
return "property:ping";
}
get prop1() {
return new Deep1();
}
method() {
return "method:ping";
}
}

class Deep1 extends RpcTarget {
get prop2() {
return "deep:prop2";
}
}

// class Deep2 extends RpcTarget {
// get prop3() {
// return "deep property";
// }
// }

export default {}; // Required to treat as modules format worker
14 changes: 14 additions & 0 deletions fixtures/do-bound/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "do-bound",
"private": true,
"scripts": {
"test:ci": "vitest run",
"test:watch": "vitest"
},
"devDependencies": {
"wrangler": "workspace:*"
},
"volta": {
"extends": "../../package.json"
}
}
13 changes: 13 additions & 0 deletions fixtures/do-bound/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

name = "do-bound"
main = "index.ts"
compatibility_date = "2024-10-28"

[durable_objects]
bindings = [
{ name = "OBJECT", class_name = "ThingObject" }
]

[[migrations]]
tag = "v1" # Should be unique for each
new_classes = ["ThingObject"]
32 changes: 32 additions & 0 deletions fixtures/do-entry/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export default {
async fetch(request, env, ctx) {
const id = env.OBJECT.newUniqueId();
const stub = env.OBJECT.get(id);

const { pathname } = new URL(request.url);
if (pathname === "/rpc") {
// stub.prop1.prop2.method('arg1')
// stub.prop1.method('arg1')
// stub.prop1 -> .then(...)
// stub.method('arg1')
return Response.json(await stub.method());
}

if (pathname === "/property") {
return Response.json(await stub.property);
}

if (pathname === "/deep-1") {
return Response.json(await stub.prop1.prop2);
}

if (pathname === "/deep-2") {
return Response.json(await stub.prop1.prop2.prop3);
}

return stub.fetch("https://placeholder:9999/", {
method: "POST",
cf: { thing: true },
});
},
};
14 changes: 14 additions & 0 deletions fixtures/do-entry/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "do-entry",
"private": true,
"scripts": {
"test:ci": "vitest run",
"test:watch": "vitest"
},
"devDependencies": {
"wrangler": "workspace:*"
},
"volta": {
"extends": "../../package.json"
}
}
9 changes: 9 additions & 0 deletions fixtures/do-entry/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

name = "do-entry"
main = "index.ts"
compatibility_date = "2024-10-28"

[durable_objects]
bindings = [
{ name = "OBJECT", class_name = "ThingObject", script_name = "do-bound" }
]
45 changes: 27 additions & 18 deletions fixtures/entrypoints-rpc-tests/tests/entrypoints.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ test("should support co-dependent services", async ({ dev }) => {
});
});

test("should support binding to Durable Object in another worker", async ({
test.only("should support binding to Durable Object in another worker", async ({
dev,
}) => {
// RPC isn't supported in this case yet :(
Expand Down Expand Up @@ -557,10 +557,8 @@ test("should support binding to Durable Object in another worker", async ({

const { pathname } = new URL(request.url);
if (pathname === "/rpc") {
const errors = [];
try { await stub.property; } catch (e) { errors.push(e); }
try { await stub.method(); } catch (e) { errors.push(e); }
return Response.json(errors.map(String));
return Response.json(await stub.property);
return Response.json(await stub.method());
}

return stub.fetch("https://placeholder:9999/", {
Expand All @@ -572,21 +570,32 @@ test("should support binding to Durable Object in another worker", async ({
`,
});

await waitFor(async () => {
const response = await fetch(url);
async function fetchJson(url: string) {
const response = await fetch(url, {
headers: {
"MF-Disable-Pretty-Error": "1",
},
});
const text = await response.text();
// Check protocol, host, and cf preserved
expect(text).toBe('POST https://placeholder:9999/ {"thing":true}');
});

const rpcResponse = await fetch(new URL("/rpc", url));
const errors = await rpcResponse.json();
expect(errors).toMatchInlineSnapshot(`
[
"Error: Cannot access \`ThingObject#property\` as Durable Object RPC is not yet supported between multiple \`wrangler dev\` sessions.",
"Error: Cannot access \`ThingObject#method\` as Durable Object RPC is not yet supported between multiple \`wrangler dev\` sessions.",
]
`);
try {
return JSON.parse(text);
} catch (err) {
throw new Error(`Couldn't parse JSON:\n\n${text}`);
}
}

// await waitFor(async () => {
// const response = await fetch(url, {
// headers: { "MF-Disable-Pretty-Error": "1" },
// });
// const text = await response.text();
// // Check protocol, host, and cf preserved
// expect(text).toBe('POST https://placeholder:9999/ {"thing":true}');
// });

const json = await fetchJson(new URL("/rpc", url).href);
expect(json).toBe("method:ping");
});

test("should support binding to Durable Object in same worker", async ({
Expand Down
12 changes: 7 additions & 5 deletions fixtures/worker-app/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { randomBytes } from "isomorphic-random-example";
import { now } from "./dep";
import { logErrors } from "./log";

console.log("startup log");
// console.log("startup log");

console.log("The following error is a fake for testing");
console.error(
"*** Received structured exception #0xc0000005: access violation; stack: 7ffe71872f57 7ff7834b643b 7ff7834b643b"
);
// console.log("The following error is a fake for testing");
// console.error(
// "*** Received structured exception #0xc0000005: access violation; stack: 7ffe71872f57 7ff7834b643b 7ff7834b643b"
// );

/** @param {Uint8Array} array */
function hexEncode(array) {
Expand All @@ -19,6 +19,8 @@ function hexEncode(array) {

export default {
async fetch(request, env) {
return Response.json(env.REMOTE_RPC.method());

console.log("request log");

const { pathname, origin, hostname, host } = new URL(request.url);
Expand Down
5 changes: 5 additions & 0 deletions fixtures/worker-app/wrangler.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ crons = ["1 * * * *"]

[version_metadata]
binding = "METADATA"

[durable_objects]
bindings = [
{ name = "REMOTE_RPC", class_name = "ThingObject", script_name = "worker-ts" }
]
14 changes: 14 additions & 0 deletions fixtures/worker-ts/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { DurableObject } from "cloudflare:workers";

/**
* Welcome to Cloudflare Workers! This is your first worker.
*
Expand Down Expand Up @@ -32,3 +34,15 @@ export default {
return new Response("Hello World!");
},
};

export class ThingObject extends DurableObject {
fetch() {
return new Response("hello");
}
get property() {
return "property:ping";
}
method() {
return "method:ping";
}
}
5 changes: 5 additions & 0 deletions fixtures/worker-ts/wrangler.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
name = "worker-ts"
main = "src/index.ts"
compatibility_date = "2023-05-04"

[durable_objects]
bindings = [
{ name = "OBJECT", class_name = "ThingObject" }
]
Loading