Skip to content

Commit 4e0121e

Browse files
committed
Adds Python examples in durable-objects/api/ files.
1 parent 5344722 commit 4e0121e

File tree

9 files changed

+544
-10
lines changed

9 files changed

+544
-10
lines changed

src/content/docs/durable-objects/api/alarms.mdx

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ sidebar:
55
order: 8
66
---
77

8-
import { Type, GlossaryTooltip } from "~/components";
8+
import { Type, GlossaryTooltip, Tabs, TabItem } from "~/components";
99

1010
## Background
1111

@@ -84,6 +84,10 @@ This example shows how to both set alarms with the `setAlarm(timestamp)` method
8484
- If an unexpected error terminates the Durable Object, the `alarm()` handler may be re-instantiated on another machine.
8585
- Following a short delay, the `alarm()` handler will run from the beginning on the other machine.
8686

87+
<Tabs>
88+
89+
<TabItem label="JavaScript" icon="seti:javascript">
90+
8791
```js
8892
import { DurableObject } from "cloudflare:workers";
8993

@@ -115,8 +119,47 @@ export class AlarmExample extends DurableObject {
115119
}
116120
```
117121

122+
</TabItem>
123+
124+
<TabItem label="Python" icon="seti:python">
125+
126+
```python
127+
from workers import DurableObject, WorkerEntrypoint
128+
129+
class Default(WorkerEntrypoint):
130+
async def fetch(self, request):
131+
return await self.env.ALARM_EXAMPLE.getByName("foo").fetch(request)
132+
133+
SECONDS = 1000
134+
135+
class AlarmExample(DurableObject):
136+
def __init__(self, ctx, env):
137+
super().__init__(ctx, env)
138+
self.storage = ctx.storage
139+
140+
async def fetch(self, request):
141+
# If there is no alarm currently set, set one for 10 seconds from now
142+
current_alarm = await self.storage.getAlarm()
143+
if current_alarm is None:
144+
self.storage.setAlarm(Date.now() + 10 * SECONDS)
145+
146+
async def alarm(self):
147+
# The alarm handler will be invoked whenever an alarm fires.
148+
# You can use this to do work, read from the Storage API, make HTTP calls
149+
# and set future alarms to run using self.storage.setAlarm() from within this handler.
150+
pass
151+
```
152+
153+
</TabItem>
154+
155+
</Tabs>
156+
118157
The following example shows how to use the `alarmInfo` property to identify if the alarm event has been attempted before.
119158

159+
<Tabs>
160+
161+
<TabItem label="JavaScript" icon="seti:javascript">
162+
120163
```js
121164
class MyDurableObject extends DurableObject {
122165
async alarm(alarmInfo) {
@@ -129,6 +172,21 @@ class MyDurableObject extends DurableObject {
129172
}
130173
```
131174
175+
</TabItem>
176+
177+
<TabItem label="Python" icon="seti:python">
178+
179+
```python
180+
class MyDurableObject(DurableObject):
181+
async def alarm(self, alarm_info):
182+
if alarm_info and alarm_info.get('retryCount', 0) != 0:
183+
print(f"This alarm event has been attempted {alarm_info.get('retryCount')} times before.")
184+
```
185+
186+
</TabItem>
187+
188+
</Tabs>
189+
132190
## Related resources
133191
134192
- Understand how to [use the Alarms API](/durable-objects/examples/alarms-api/) in an end-to-end example.

src/content/docs/durable-objects/api/base.mdx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import { Render, Tabs, TabItem, GlossaryTooltip, Type, MetaInfo, TypeScriptExamp
99

1010
The `DurableObject` base class is an abstract class which all Durable Objects inherit from. This base class provides a set of optional methods, frequently referred to as handler methods, which can respond to events, for example a webSocketMessage when using the [WebSocket Hibernation API](/durable-objects/best-practices/websockets/#websocket-hibernation-api). To provide a concrete example, here is a Durable Object `MyDurableObject` which extends `DurableObject` and implements the fetch handler to return "Hello, World!" to the calling Worker.
1111

12-
<TypeScriptExample>
12+
<Tabs>
13+
14+
<TypeScriptExample omitTabs={true}>
1315
```ts
1416
export class MyDurableObject extends DurableObject {
1517
constructor(ctx: DurableObjectState, env: Env) {
@@ -23,6 +25,23 @@ export class MyDurableObject extends DurableObject {
2325
```
2426
</TypeScriptExample>
2527

28+
<TabItem label="Python" icon="seti:python">
29+
30+
```python
31+
from workers import DurableObject, Response
32+
33+
class MyDurableObject(DurableObject):
34+
def __init__(self, ctx, env):
35+
super().__init__(ctx, env)
36+
37+
async def fetch(self, request):
38+
return Response("Hello, World!")
39+
```
40+
41+
</TabItem>
42+
43+
</Tabs>
44+
2645
## Methods
2746

2847
### `fetch`

src/content/docs/durable-objects/api/container.mdx

Lines changed: 162 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ It is likely preferable to use the official `Container` class, which provides he
2525
a more idiomatic API for working with containers on top of Durable Objects.
2626
:::
2727

28-
<TypeScriptExample filename="index.ts">
28+
<Tabs>
29+
30+
<TypeScriptExample filename="index.ts" omitTabs={true}>
2931
```ts
3032
export class MyDurableObject extends DurableObject {
3133
constructor(ctx: DurableObjectState, env: Env) {
@@ -42,24 +44,63 @@ export class MyDurableObject extends DurableObject {
4244
```
4345
</TypeScriptExample>
4446

47+
<TabItem label="Python" icon="seti:python">
48+
49+
```python
50+
from workers import DurableObject
51+
52+
class MyDurableObject(DurableObject):
53+
def __init__(self, ctx, env):
54+
super().__init__(ctx, env)
55+
56+
# boot the container when starting the DO
57+
async def start_container():
58+
self.ctx.container.start()
59+
self.ctx.blockConcurrencyWhile(start_container)
60+
```
61+
62+
</TabItem>
63+
64+
</Tabs>
65+
4566

4667
## Attributes
4768

4869
### `running`
4970

5071
`running` returns `true` if the container is currently running. It does not ensure that the container has fully started and ready to accept requests.
5172

73+
<Tabs>
74+
75+
<TabItem label="JavaScript" icon="seti:javascript">
76+
5277
```js
53-
this.ctx.container.running;
78+
this.ctx.container.running;
79+
```
80+
81+
</TabItem>
82+
83+
<TabItem label="Python" icon="seti:python">
84+
85+
```python
86+
self.ctx.container.running
5487
```
5588

89+
</TabItem>
90+
91+
</Tabs>
92+
5693
## Methods
5794

5895
### `start`
5996

6097
`start` boots a container. This method does not block until the container is fully started.
6198
You may want to confirm the container is ready to accept requests before using it.
6299

100+
<Tabs>
101+
102+
<TabItem label="JavaScript" icon="seti:javascript">
103+
63104
```js
64105
this.ctx.container.start({
65106
env: {
@@ -70,6 +111,26 @@ this.ctx.container.start({
70111
});
71112
```
72113

114+
</TabItem>
115+
116+
<TabItem label="Python" icon="seti:python">
117+
118+
```python
119+
from pyodide.ffi import to_js
120+
121+
self.ctx.container.start(
122+
env = to_js({
123+
"FOO": "bar",
124+
}),
125+
enableInternet = False,
126+
entrypoint = to_js(["node", "server.js"]),
127+
)
128+
```
129+
130+
</TabItem>
131+
132+
</Tabs>
133+
73134
#### Parameters
74135

75136
- `options` (optional): An object with the following properties:
@@ -85,10 +146,26 @@ this.ctx.container.start({
85146

86147
`destroy` stops the container and optionally returns a custom error message to the `monitor()` error callback.
87148

149+
<Tabs>
150+
151+
<TabItem label="JavaScript" icon="seti:javascript">
152+
88153
```js
89154
this.ctx.container.destroy("Manually Destroyed");
90155
```
91156

157+
</TabItem>
158+
159+
<TabItem label="Python" icon="seti:python">
160+
161+
```python
162+
self.ctx.container.destroy("Manually Destroyed")
163+
```
164+
165+
</TabItem>
166+
167+
</Tabs>
168+
92169
#### Parameters
93170

94171
- `error` (optional): A string that will be sent to the error handler of the `monitor` method. This is useful for logging or debugging purposes.
@@ -101,11 +178,28 @@ this.ctx.container.destroy("Manually Destroyed");
101178

102179
`signal` sends an IPC signal to the container, such as SIGKILL or SIGTERM. This is useful for stopping the container gracefully or forcefully.
103180

181+
<Tabs>
182+
183+
<TabItem label="JavaScript" icon="seti:javascript">
184+
104185
```js
105186
const SIGTERM = 15;
106187
this.ctx.container.signal(SIGTERM);
107188
```
108189

190+
</TabItem>
191+
192+
<TabItem label="Python" icon="seti:python">
193+
194+
```python
195+
SIGTERM = 15
196+
self.ctx.container.signal(SIGTERM)
197+
```
198+
199+
</TabItem>
200+
201+
</Tabs>
202+
109203
#### Parameters
110204

111205
- `signal`: a number representing the signal to send to the container. This is typically a POSIX signal number, such as SIGTERM (15) or SIGKILL (9).
@@ -118,6 +212,10 @@ this.ctx.container.signal(SIGTERM);
118212

119213
`getTcpPort` returns a TCP port from the container. This can be used to communicate with the container over TCP and HTTP.
120214

215+
<Tabs>
216+
217+
<TabItem label="JavaScript" icon="seti:javascript">
218+
121219
```js
122220
const port = this.ctx.container.getTcpPort(8080);
123221
const res = await port.fetch("http://container/set-state", {
@@ -141,6 +239,38 @@ try {
141239
}
142240
```
143241

242+
</TabItem>
243+
244+
<TabItem label="Python" icon="seti:python">
245+
246+
```python
247+
port = self.ctx.container.getTcpPort(8080)
248+
res = await port.fetch(
249+
"http://container/set-state",
250+
body = initial_state,
251+
method = "POST",
252+
)
253+
```
254+
255+
```python
256+
from workers import Response
257+
258+
conn = self.ctx.container.getTcpPort(8080).connect('10.0.0.1:8080')
259+
await conn.opened
260+
261+
try:
262+
if request.body:
263+
await request.body.pipeTo(conn.writable)
264+
return Response(conn.readable)
265+
except Exception as err:
266+
print(f"Request body piping failed: {err}")
267+
return Response("Failed to proxy request body", status=502)
268+
```
269+
270+
</TabItem>
271+
272+
</Tabs>
273+
144274
#### Parameters
145275

146276
- `port` (number): a TCP port number to use for communication with the container.
@@ -154,6 +284,10 @@ try {
154284
`monitor` returns a promise that resolves when a container exits and errors if a container errors. This is useful for setting up
155285
callbacks to handle container status changes in your Workers code.
156286

287+
<Tabs>
288+
289+
<TabItem label="JavaScript" icon="seti:javascript">
290+
157291
```js
158292
class MyContainer extends DurableObject {
159293
constructor(ctx, env) {
@@ -173,6 +307,32 @@ class MyContainer extends DurableObject {
173307
}
174308
```
175309

310+
</TabItem>
311+
312+
<TabItem label="Python" icon="seti:python">
313+
314+
```python
315+
from workers import DurableObject
316+
317+
class MyContainer(DurableObject):
318+
def __init__(self, ctx, env):
319+
super().__init__(ctx, env)
320+
321+
def on_container_exit():
322+
print("Container exited")
323+
324+
# the "err" value can be customized by the destroy() method
325+
async def on_container_error(err):
326+
print(f"Container errored: {err}")
327+
328+
self.ctx.container.start()
329+
self.ctx.container.monitor().then(on_container_exit).catch(on_container_error)
330+
```
331+
332+
</TabItem>
333+
334+
</Tabs>
335+
176336
#### Parameters
177337

178338
- None

0 commit comments

Comments
 (0)