Skip to content

Commit fb51935

Browse files
chore: release nostream@3.10.1
1 parent aa7564c commit fb51935

3 files changed

Lines changed: 17 additions & 16 deletions

File tree

‎.changeset/rate-limit-wire-correctness.md‎

Lines changed: 0 additions & 15 deletions
This file was deleted.

‎CHANGELOG.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# nostream
22

3+
## 3.10.1
4+
5+
### Patch Changes
6+
7+
- [#1011](https://github.com/cameri/nostream/pull/1011) [`fd7679b`](https://github.com/cameri/nostream/commit/fd7679bed7ba2b10f5148f50ece415e869814475) Thanks [@chappie-daemon](https://github.com/chappie-daemon)! - fix(rate-limit): send the backoff the strategy actually means, name an outage as an error, and bucket messages by type
8+
9+
Three defects on one wire path, from the spike in [#1004](https://github.com/cameri/nostream/issues/1004).
10+
11+
**The EWMA backoff was a half-life, sent as a delay.** `RateLimit.period` is the decay half-life under `ewma`, so the time until a limit lifts is `period · log2(R_new / rate)`, not `period`. With `rate: 6, period: 60000`, a client four times over the limit was told to wait 60 s and needed 120 s. The Lua script now returns its score instead of a yes/no, and the limiter returns `period · log2(score / rate)`. It was only accidentally safe before: the hash carried a TTL of exactly `period`, so a quiet client's state expired anyway — an unstated coupling that would break the moment anyone lengthened the TTL to keep state warm.
12+
13+
**A limiter outage was announced as `rate-limited`.** A failing backend made every connected client back off for a fault on this side. It now answers `error: rate limiter unavailable` and still rejects the event; fail-closed behaviour is unchanged.
14+
15+
**The message bucket ignored the message type.** One bucket per client meant a `REQ` could be refused because its `EVENT`s had filled it — the wrong message throttled, and the wrong one told to back off. The bucket key now carries the type, read from a bounded prefix of the frame because the limiter runs before validation.
16+
17+
`IRateLimiter.hit` returns `IRateLimiterResult` (`limited`, plus `retryAfterMs` when the strategy can estimate one) so each strategy answers in its own terms; a caller with no estimate keeps sending the period.
18+
319
## 3.10.0
420

521
### Minor Changes

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nostream",
3-
"version": "3.10.0",
3+
"version": "3.10.1",
44
"packageManager": "pnpm@10.33.0",
55
"private": true,
66
"description": "A Nostr relay written in Typescript.",

0 commit comments

Comments
 (0)