@sproutboat/runtime 0.27.1 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -0
- package/package.json +1 -1
- package/src/native-fetch-prelude.js +677 -35
- package/src/transport-broker.js +159 -8
- package/src/transport-embedded.js +23 -5
- package/test/native-request-streaming.ts +221 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# @sproutboat/runtime
|
|
2
2
|
|
|
3
|
+
## 0.29.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8df17ef: Durable Objects like workerd from compatibility date `2026-10-28`:
|
|
8
|
+
|
|
9
|
+
- **Input gate.** While an object's storage read is in flight, no other event
|
|
10
|
+
(`stub.fetch()`, an alarm) enters it, so `const v = await storage.get("n"); await
|
|
11
|
+
storage.put("n", v + 1)` is safe under concurrent calls. Ten concurrent increments used
|
|
12
|
+
to end at 1. An event that awaits anything else (a fetch, a timer) lets the next one
|
|
13
|
+
in, as in workerd. `blockConcurrencyWhile()` and `transaction()` hold the gate until
|
|
14
|
+
they settle, and `stub.fetch()` always returns a Promise.
|
|
15
|
+
- **Storage returns Promises** (`get`, `put`, `delete`, `deleteAll`, `list`, the alarm
|
|
16
|
+
methods), and adds `sync()` and `transaction()` (with `txn.rollback()`; a throw rolls
|
|
17
|
+
back; a transaction reads its own writes).
|
|
18
|
+
- **Structured values.** Date, Map, Set, RegExp, ArrayBuffer and typed arrays, BigInt,
|
|
19
|
+
`undefined` inside containers, NaN, the infinities and -0 round-trip.
|
|
20
|
+
`put(k, undefined)` throws a TypeError and a function throws a DataCloneError, before
|
|
21
|
+
anything is written.
|
|
22
|
+
- `list()` takes `start`, `startAfter`, `end` and `reverse`, and `limit: 0` throws.
|
|
23
|
+
`setAlarm()` refuses a value that is not a Date or a number. `deleteAll()` also drops
|
|
24
|
+
the alarm.
|
|
25
|
+
|
|
26
|
+
Earlier dates keep synchronous JSON storage and no gate. Values written from
|
|
27
|
+
`2026-10-28` start with `#sb1:`, and every date reads both formats.
|
|
28
|
+
|
|
29
|
+
Both transports' `do.storage.list` take `start`, `startAfter`, `end` and `reverse`, and
|
|
30
|
+
match the prefix exactly (SQL `LIKE` also matched `_` and `%` as wildcards, ignoring
|
|
31
|
+
case, so a prefix such as `user_` listed other keys).
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- 8df17ef: Queues fixes at every compatibility date (data loss, so not gated):
|
|
36
|
+
|
|
37
|
+
- On the embedded transport (standalone sprouts and sproutd), `sendBatch()` stored every
|
|
38
|
+
body as the text `"[object Object]"`. It now stores the body it was given, and both
|
|
39
|
+
`send()` and `sendBatch()` honour `delaySeconds` there, as the broker already did.
|
|
40
|
+
- A consumer whose `queue()` throws now retries every message it had not explicitly
|
|
41
|
+
acked or retried, as on Workers. The embedded transport used to ack the whole batch,
|
|
42
|
+
so a failing consumer lost its messages. Explicit `ack()` / `ackAll()` calls made
|
|
43
|
+
before the throw still count (Cloudflare's documented behaviour; miniflare retries
|
|
44
|
+
those too).
|
|
45
|
+
|
|
46
|
+
From compatibility date `2026-10-28`, `sendBatch(messages, { delaySeconds })` delays
|
|
47
|
+
every message whose own `delaySeconds` is unset or 0. Earlier dates ignore the batch
|
|
48
|
+
option.
|
|
49
|
+
|
|
50
|
+
## 0.28.0
|
|
51
|
+
|
|
52
|
+
### Minor Changes
|
|
53
|
+
|
|
54
|
+
- 829ed12: Request bodies stream, from compatibility date `2026-10-27`, as in workerd:
|
|
55
|
+
|
|
56
|
+
- **Ingress.** The native server runs the handler as soon as a request's headers arrive. `request.body` hands out the bytes as they come in, and the server pauses the socket while more than 1 MiB waits unread, so a large upload read through the stream keeps memory flat (a 128 MiB upload peaks at 38 MiB RSS). `text()`, `json()`, `arrayBuffer()` and `bytes()` read the whole body and return Promises.
|
|
57
|
+
- **Limit.** `SB_REQUEST_BODY_MAX` defaults to 100 MiB for streamed bodies (it stays 1 MiB before the date, where the body is held in memory whole). A larger `Content-Length` gets `413 Payload Too Large` before the handler runs; a chunked body that grows past it closes the connection, and the handler's stream fails.
|
|
58
|
+
- **Service bindings and `fetch()`.** On the broker transport, a `ReadableStream` request body goes out as it is read, in `FRAME_V1_MORE` frames after the request's head, instead of being read to the end first. The broker feeds them to the upstream request as a stream (with backpressure) and says so in its `ping` reply (`bodyStream: true`); against an older broker, bodies are sent whole as before. A streamed body can't follow a 307 or 308 redirect.
|
|
59
|
+
|
|
60
|
+
Internal trigger and RPC calls keep buffered bodies. Before `2026-10-27` nothing changes: the handler gets the whole body at once and `request.text()` answers synchronously, which a deployed handler may rely on, hence the new date.
|
|
61
|
+
|
|
3
62
|
## 0.27.1
|
|
4
63
|
|
|
5
64
|
### Patch Changes
|