Skip to content

Commit 4ca758b

Browse files
authored
Using TypeScriptExample component instead of manually duplicating (#24216)
1 parent cfc2fa6 commit 4ca758b

File tree

2 files changed

+6
-169
lines changed

2 files changed

+6
-169
lines changed

src/content/docs/durable-objects/examples/websocket-hibernation-server.mdx

Lines changed: 3 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ description: Build a WebSocket server using WebSocket Hibernation on Durable
1212
Objects and Workers.
1313
---
1414

15-
import { TabItem, Tabs, WranglerConfig } from "~/components";
15+
import { TabItem, Tabs, WranglerConfig, TypeScriptExample } from "~/components";
1616

1717
This example is similar to the [Build a WebSocket server](/durable-objects/examples/websocket-server/) example, but uses the WebSocket Hibernation API. The WebSocket Hibernation API should be preferred for WebSocket server applications built on Durable Objects, since it significantly decreases duration charge, and provides additional features that pair well with WebSocket applications. For more information, refer to [Use Durable Objects with WebSockets](/durable-objects/best-practices/websockets/).
1818

@@ -22,84 +22,7 @@ WebSocket Hibernation is unavailable for outgoing WebSocket use cases. Hibernati
2222

2323
:::
2424

25-
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
26-
27-
```js
28-
import { DurableObject } from "cloudflare:workers";
29-
30-
// Worker
31-
export default {
32-
async fetch(request, env, ctx) {
33-
if (request.url.endsWith("/websocket")) {
34-
// Expect to receive a WebSocket Upgrade request.
35-
// If there is one, accept the request and return a WebSocket Response.
36-
const upgradeHeader = request.headers.get("Upgrade");
37-
if (!upgradeHeader || upgradeHeader !== "websocket") {
38-
return new Response("Durable Object expected Upgrade: websocket", {
39-
status: 426,
40-
});
41-
}
42-
43-
// This example will refer to the same Durable Object,
44-
// since the name "foo" is hardcoded.
45-
let id = env.WEBSOCKET_HIBERNATION_SERVER.idFromName("foo");
46-
let stub = env.WEBSOCKET_HIBERNATION_SERVER.get(id);
47-
48-
return stub.fetch(request);
49-
}
50-
51-
return new Response(null, {
52-
status: 400,
53-
statusText: "Bad Request",
54-
headers: {
55-
"Content-Type": "text/plain",
56-
},
57-
});
58-
},
59-
};
60-
61-
// Durable Object
62-
export class WebSocketHibernationServer extends DurableObject {
63-
async fetch(request) {
64-
// Creates two ends of a WebSocket connection.
65-
const webSocketPair = new WebSocketPair();
66-
const [client, server] = Object.values(webSocketPair);
67-
68-
// Calling `acceptWebSocket()` informs the runtime that this WebSocket is to begin terminating
69-
// request within the Durable Object. It has the effect of "accepting" the connection,
70-
// and allowing the WebSocket to send and receive messages.
71-
// Unlike `ws.accept()`, `state.acceptWebSocket(ws)` informs the Workers Runtime that the WebSocket
72-
// is "hibernatable", so the runtime does not need to pin this Durable Object to memory while
73-
// the connection is open. During periods of inactivity, the Durable Object can be evicted
74-
// from memory, but the WebSocket connection will remain open. If at some later point the
75-
// WebSocket receives a message, the runtime will recreate the Durable Object
76-
// (run the `constructor`) and deliver the message to the appropriate handler.
77-
this.ctx.acceptWebSocket(server);
78-
79-
return new Response(null, {
80-
status: 101,
81-
webSocket: client,
82-
});
83-
}
84-
85-
async webSocketMessage(ws, message) {
86-
// Upon receiving a message from the client, reply with the same message,
87-
// but will prefix the message with "[Durable Object]: " and return the
88-
// total number of connections.
89-
ws.send(
90-
`[Durable Object] message: ${message}, connections: ${this.ctx.getWebSockets().length}`,
91-
);
92-
}
93-
94-
async webSocketClose(ws, code, reason, wasClean) {
95-
// If the client closes the connection, the runtime will invoke the webSocketClose() handler.
96-
ws.close(code, "Durable Object is closing WebSocket");
97-
}
98-
}
99-
```
100-
101-
</TabItem> <TabItem label="TypeScript" icon="seti:typescript">
102-
25+
<TypeScriptExample>
10326
```ts
10427
import { DurableObject } from "cloudflare:workers";
10528

@@ -185,8 +108,7 @@ export class WebSocketHibernationServer extends DurableObject {
185108
}
186109
}
187110
```
188-
189-
</TabItem> </Tabs>
111+
</TypeScriptExample>
190112

191113
Finally, configure your Wrangler file to include a Durable Object [binding](/durable-objects/get-started/#4-configure-durable-object-bindings) and [migration](/durable-objects/reference/durable-objects-migrations/) based on the namespace and class name chosen previously.
192114

src/content/docs/durable-objects/examples/websocket-server.mdx

Lines changed: 3 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ sidebar:
1010
description: Build a WebSocket server using Durable Objects and Workers.
1111
---
1212

13-
import { TabItem, Tabs, GlossaryTooltip, WranglerConfig } from "~/components";
13+
import { TabItem, Tabs, GlossaryTooltip, WranglerConfig, TypeScriptExample } from "~/components";
1414

1515
This example shows how to build a WebSocket server using <GlossaryTooltip term="Durable Object">Durable Objects</GlossaryTooltip> and Workers. The example exposes an endpoint to create a new WebSocket connection. This WebSocket connection echos any message while including the total number of WebSocket connections currently established. For more information, refer to [Use Durable Objects with WebSockets](/durable-objects/best-practices/websockets/).
1616

@@ -20,91 +20,7 @@ WebSocket connections pin your Durable Object to memory, and so duration charges
2020

2121
:::
2222

23-
<Tabs> <TabItem label="JavaScript" icon="seti:javascript">
24-
25-
```js
26-
import { DurableObject } from "cloudflare:workers";
27-
28-
// Worker
29-
export default {
30-
async fetch(request, env, ctx) {
31-
if (request.url.endsWith("/websocket")) {
32-
// Expect to receive a WebSocket Upgrade request.
33-
// If there is one, accept the request and return a WebSocket Response.
34-
const upgradeHeader = request.headers.get("Upgrade");
35-
if (!upgradeHeader || upgradeHeader !== "websocket") {
36-
return new Response("Durable Object expected Upgrade: websocket", {
37-
status: 426,
38-
});
39-
}
40-
41-
// This example will refer to the same Durable Object,
42-
// since the name "foo" is hardcoded.
43-
let id = env.WEBSOCKET_SERVER.idFromName("foo");
44-
let stub = env.WEBSOCKET_SERVER.get(id);
45-
46-
return stub.fetch(request);
47-
}
48-
49-
return new Response(null, {
50-
status: 400,
51-
statusText: "Bad Request",
52-
headers: {
53-
"Content-Type": "text/plain",
54-
},
55-
});
56-
},
57-
};
58-
59-
// Durable Object
60-
export class WebSocketServer extends DurableObject {
61-
currentlyConnectedWebSockets;
62-
63-
constructor(ctx, env) {
64-
// This is reset whenever the constructor runs because
65-
// regular WebSockets do not survive Durable Object resets.
66-
//
67-
// WebSockets accepted via the Hibernation API can survive
68-
// a certain type of eviction, but we will not cover that here.
69-
super(ctx, env);
70-
this.currentlyConnectedWebSockets = 0;
71-
}
72-
73-
async fetch(request) {
74-
// Creates two ends of a WebSocket connection.
75-
const webSocketPair = new WebSocketPair();
76-
const [client, server] = Object.values(webSocketPair);
77-
78-
// Calling `accept()` tells the runtime that this WebSocket is to begin terminating
79-
// request within the Durable Object. It has the effect of "accepting" the connection,
80-
// and allowing the WebSocket to send and receive messages.
81-
server.accept();
82-
this.currentlyConnectedWebSockets += 1;
83-
84-
// Upon receiving a message from the client, the server replies with the same message,
85-
// and the total number of connections with the "[Durable Object]: " prefix
86-
server.addEventListener("message", (event) => {
87-
server.send(
88-
`[Durable Object] currentlyConnectedWebSockets: ${this.currentlyConnectedWebSockets}`,
89-
);
90-
});
91-
92-
// If the client closes the connection, the runtime will close the connection too.
93-
server.addEventListener("close", (cls) => {
94-
this.currentlyConnectedWebSockets -= 1;
95-
server.close(cls.code, "Durable Object is closing WebSocket");
96-
});
97-
98-
return new Response(null, {
99-
status: 101,
100-
webSocket: client,
101-
});
102-
}
103-
}
104-
```
105-
106-
</TabItem> <TabItem label="TypeScript" icon="seti:typescript">
107-
23+
<TypeScriptExample>
10824
```ts
10925
import { DurableObject } from "cloudflare:workers";
11026

@@ -189,8 +105,7 @@ export class WebSocketServer extends DurableObject {
189105
}
190106
}
191107
```
192-
193-
</TabItem> </Tabs>
108+
</TypeScriptExample>
194109

195110
Finally, configure your Wrangler file to include a Durable Object [binding](/durable-objects/get-started/#4-configure-durable-object-bindings) and [migration](/durable-objects/reference/durable-objects-migrations/) based on the <GlossaryTooltip term="namespace">namespace</GlossaryTooltip> and class name chosen previously.
196111

0 commit comments

Comments
 (0)