@sproutboat/runtime 0.4.0 → 0.5.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 +12 -0
- package/package.json +1 -1
- package/src/native-fetch-prelude.js +6 -4
- package/src/transport-embedded.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @sproutboat/runtime
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Rate limiter (baronunread/sproutboat#69): `env.<NAME>.limit({ key })` now
|
|
8
|
+
returns `{ success, resetAt }`. `resetAt` is epoch milliseconds for when the
|
|
9
|
+
fixed window rolls and the counter clears, returned on every call (hit or
|
|
10
|
+
miss), so a rejection can carry an accurate `Retry-After`:
|
|
11
|
+
`Math.ceil((resetAt - Date.now()) / 1000)`. The `ratelimit.check` op already
|
|
12
|
+
had `windowStart` and `period` in hand; it just stopped discarding them.
|
|
13
|
+
Additive: existing callers reading only `success` are unaffected.
|
|
14
|
+
|
|
3
15
|
## 0.4.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/package.json
CHANGED
|
@@ -1106,9 +1106,11 @@ globalThis.__sbInstallBindings = function (target, bindings) {
|
|
|
1106
1106
|
target[b.binding] = __sbMakeDONamespace(b.binding, b.className);
|
|
1107
1107
|
}
|
|
1108
1108
|
|
|
1109
|
-
// #69 — env.<NAME>.limit({ key }) -> { success }. Fixed window: at
|
|
1110
|
-
// `limit` calls per `period` seconds for a given key. limit/period
|
|
1111
|
-
// the message so the op stays stateless (the transport has no
|
|
1109
|
+
// #69 — env.<NAME>.limit({ key }) -> { success, resetAt }. Fixed window: at
|
|
1110
|
+
// most `limit` calls per `period` seconds for a given key. limit/period
|
|
1111
|
+
// travel in the message so the op stays stateless (the transport has no
|
|
1112
|
+
// config). `resetAt` is epoch ms when the window rolls and the count clears,
|
|
1113
|
+
// so a 429 can send `Retry-After: ceil((resetAt - Date.now()) / 1000)`.
|
|
1112
1114
|
// Returns sync like the other shims (CF's is a Promise; the runtime is sync).
|
|
1113
1115
|
for (let i = 0; i < (bindings.ratelimiters || []).length; i++) {
|
|
1114
1116
|
const rl = bindings.ratelimiters[i];
|
|
@@ -1116,7 +1118,7 @@ globalThis.__sbInstallBindings = function (target, bindings) {
|
|
|
1116
1118
|
limit(options) {
|
|
1117
1119
|
const key = options && options.key != null ? String(options.key) : "";
|
|
1118
1120
|
const r = __sbRpc("ratelimit.check", { name: rl.binding, key, limit: rl.limit, period: rl.period });
|
|
1119
|
-
return { success: !!r.success };
|
|
1121
|
+
return { success: !!r.success, resetAt: Number(r.resetAt) || 0 };
|
|
1120
1122
|
},
|
|
1121
1123
|
};
|
|
1122
1124
|
}
|
|
@@ -1539,7 +1539,7 @@ function __sbEmbeddedDispatch(msg) {
|
|
|
1539
1539
|
[String(msg.name), String(msg.key == null ? "" : msg.key), windowStart],
|
|
1540
1540
|
);
|
|
1541
1541
|
const count = r.rows.length ? Number(r.rows[0][0]) : 1;
|
|
1542
|
-
return { ok: true, success: count <= limit };
|
|
1542
|
+
return { ok: true, success: count <= limit, resetAt: (windowStart + period) * 1000 };
|
|
1543
1543
|
}
|
|
1544
1544
|
|
|
1545
1545
|
throw new Error("unknown op: " + op);
|