fix: deliver events to every matching subscription on a connection #6

Merged
padreug merged 3 commits from fix/notify-all-subscriptions into main 2026-09-12 12:40:13 +00:00
Owner

Problem

NostrClientConnection.notify_event returned after the first filter that matched, so a connection holding several subscriptions only ever received a live event on one of them.

That is invisible when each client has its own connection, but nostrclient multiplexes every one of its clients through a single upstream connection. On four84, nwcprovider (via nostrclient over loopback) subscribes to its own kind-23195 responses; that filter is registered before any wallet app's. Every NWC reply was therefore handed to the provider's subscription and delivery stopped, so the wallet app's subscription on the same connection never saw it. Amethyst reported "Wallet request timed out" even though the journal showed both the 23194 request and the 23195 reply on the relay.

Pairing the same app directly against wss://…/nostrrelay/<id> worked, because the app then had its own connection and filter list.

Reproduced with a two-client simulation (nwcsim3.py, provider also subscribed to its own responses): direct relay delivers, via nostrclient it times out. Upstream lnbits/nostrrelay (a87bc1f) has the identical first-match return True, so this is recorded in the new docs/upstream-candidates.md.

Change

  • relay/client_connection.py — iterate all filters, send once per subscription id, return whether anything was delivered.
  • Per-filter "didn't match" log demoted INFO → DEBUG (it was emitting one line per filter per event; 36 lines per NWC reply on four84).
  • tests/test_notify.py — three tests: multi-subscription delivery, dedupe when one subscription has several matching filters, nothing sent when nothing matches.
  • docs/upstream-candidates.md — started.
  • Version bumped to 1.1.0-aio.3 (separate commit).

Verification

  • pytest on tests/test_notify.py + tests/test_nip17.py: 12 passed.
  • ruff / mypy: only pre-existing findings on main (E501 lines, NostrFilter(**kwargs) typing), none introduced.

Release steps after merge

  1. git tag v1.1.0-aio.3 && git push origin v1.1.0-aio.3
  2. sha256 of the archive, add a new entry to aiolabs/lnbits-extensions/extensions.json (keep the 1.1.0-aio.2 entry).
  3. Upgrade nostrrelay on four84, re-run the Amethyst pairing.

🤖 Generated with Claude Code

https://claude.ai/code/session_013Tbyw6FwjhEJg3gHfPHxWt

## Problem `NostrClientConnection.notify_event` returned after the **first** filter that matched, so a connection holding several subscriptions only ever received a live event on one of them. That is invisible when each client has its own connection, but **nostrclient multiplexes every one of its clients through a single upstream connection**. On four84, nwcprovider (via nostrclient over loopback) subscribes to its own kind-23195 responses; that filter is registered before any wallet app's. Every NWC reply was therefore handed to the provider's subscription and delivery stopped, so the wallet app's subscription on the same connection never saw it. Amethyst reported "Wallet request timed out" even though the journal showed both the 23194 request and the 23195 reply on the relay. Pairing the same app directly against `wss://…/nostrrelay/<id>` worked, because the app then had its own connection and filter list. Reproduced with a two-client simulation (`nwcsim3.py`, provider also subscribed to its own responses): direct relay delivers, via nostrclient it times out. Upstream `lnbits/nostrrelay` (`a87bc1f`) has the identical first-match `return True`, so this is recorded in the new `docs/upstream-candidates.md`. ## Change - `relay/client_connection.py` — iterate all filters, send once per subscription id, return whether anything was delivered. - Per-filter "didn't match" log demoted INFO → DEBUG (it was emitting one line per filter per event; 36 lines per NWC reply on four84). - `tests/test_notify.py` — three tests: multi-subscription delivery, dedupe when one subscription has several matching filters, nothing sent when nothing matches. - `docs/upstream-candidates.md` — started. - Version bumped to `1.1.0-aio.3` (separate commit). ## Verification - `pytest` on `tests/test_notify.py` + `tests/test_nip17.py`: 12 passed. - ruff / mypy: only pre-existing findings on main (E501 lines, `NostrFilter(**kwargs)` typing), none introduced. ## Release steps after merge 1. `git tag v1.1.0-aio.3 && git push origin v1.1.0-aio.3` 2. sha256 of the archive, add a **new** entry to `aiolabs/lnbits-extensions/extensions.json` (keep the `1.1.0-aio.2` entry). 3. Upgrade nostrrelay on four84, re-run the Amethyst pairing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_013Tbyw6FwjhEJg3gHfPHxWt
notify_event returned after the first filter that matched, so a
connection holding several subscriptions only ever received an event on
one of them. That is invisible with one subscription per client, but a
multiplexer such as nostrclient funnels all of its clients through a
single connection. With nwcprovider subscribed to its own kind-23195
responses, every NWC reply was handed to that subscription and stopped
there; the wallet app's subscription on the same connection never saw
it, and Amethyst reported "wallet request timed out". Direct to the
relay it worked, because the app then had its own connection.

Deliver once per subscription id instead, and demote the per-filter
miss log to debug: it emitted one INFO line per filter per event.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tbyw6FwjhEJg3gHfPHxWt
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tbyw6FwjhEJg3gHfPHxWt
chore: bump version to 1.1.0-aio.3
Some checks failed
ci.yml / chore: bump version to 1.1.0-aio.3 (pull_request) Failing after 0s
e09402de56
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tbyw6FwjhEJg3gHfPHxWt
padreug deleted branch fix/notify-all-subscriptions 2026-09-12 12:40:13 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/nostrrelay!6
No description provided.