You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`start_at` and `start_in` return a `Result` handle (like `.start()`).
80
+
81
+
## Throttling
82
+
83
+
Rate-limit how often a function can be executed:
84
+
85
+
```python
86
+
from datetime import timedelta
87
+
88
+
@trace(throttle=timedelta(hours=24) /50) # ~29 min cooldown
89
+
defexpensive_api_call(query: str) -> str: ...
90
+
```
91
+
92
+
If a task arrives during the cooldown window, the worker returns a `ThrottleError` immediately (no retry). The cooldown is only recorded after a successful execution.
93
+
61
94
## Third-party packages
62
95
63
96
Workers auto-install missing packages. When the import name differs from the pip package:
6.**Reconstruct** -- Produce a self-contained Python script from the store. `compile()` and `exec()` it into a fresh namespace.
109
-
7.**Execute** -- Call the function with the provided arguments. Async functions are awaited directly; sync functions run in an executor with explicit context propagation (for progress reporting). Apply retry/timeout policies via `asyncio.wait_for`.
110
-
8.**Send result** -- Wrap the return value (or exception traceback) in a `ResultEnvelope` and send it back. If cancelled during execution, skip result delivery.
118
+
9.**Execute** -- Call the function with the provided arguments. Async functions are awaited directly; sync functions run in an executor with explicit context propagation (for progress reporting). Apply retry/timeout policies via `asyncio.wait_for`.
119
+
10.**Send result** -- Wrap the return value (or exception traceback) in a `ResultEnvelope` and send it back. If cancelled during execution, skip result delivery.
120
+
11.**Record throttle** -- If the task has a `throttle` value and execution succeeded, record a cooldown in the backend.
121
+
12.**Re-enqueue recurring** -- If the task has a `recur_interval` and its schedule hasn't been cancelled, submit a new task instance with `scheduled_at = now + interval`.
@@ -117,7 +128,7 @@ The `Result` object supports two waiting strategies:
117
128
118
129
**With stall detection** (default, `stall_timeout=10.0`) -- An async polling loop calls `try_get_result()` and checks heartbeats every second. If the heartbeat hasn't changed for longer than `stall_timeout`, `TaskStalled` is raised.
119
130
120
-
**Unwrap** -- If status is `"ok"`, return the value. If `"error"`, raise `RemoteError` with the remote traceback.
131
+
**Unwrap** -- If status is `"ok"`, return the value. If `"error"`, raise `RemoteError` with the remote traceback. If `"throttled"`, raise `ThrottleError`.
121
132
122
133
## Transport backends
123
134
@@ -137,6 +148,10 @@ The `Backend` ABC defines an async transport interface:
137
148
|`async is_cancelled(task_id)`| Check cancellation flag (default returns `False`) |
138
149
|`async send_progress(task_id, json)`| Store latest progress data (no-op default) |
139
150
|`async get_progress(task_id)`| Get latest progress JSON (default returns `None`) |
151
+
|`async cancel_schedule(schedule_id)`| Mark recurring schedule cancelled (no-op default) |
0 commit comments