Commit Graph
11 Commits
Author SHA1 Message Date
thePR0M3TH3ANandClaude Fable 5 1934f9386a publish: all-timeout content publishes are unconfirmed soft successes (#49)
signAndPublishEvent (video publish/edit/repost/mirror), rebroadcastEvent, and
revertVideo now use assertAnyRelayAcceptedOrUnconfirmed: when every relay
times out without rejecting, the event was sent and almost always persisted,
so it no longer surfaces as "Failed to share video". Explicit rejections
still throw.

Messaging stays honest at every consumer:
- relay tally carries `unconfirmed` (now attached on edits too);
  describePublishOutcome maps 0-accepted+unconfirmed to a WARNING ("sent,
  no relay confirmed yet") — never a fake relay count, never a hard error
- edit/revert controllers say "sent, not confirmed yet" when unconfirmed
- deletes stay CONSERVATIVE: "deleted successfully" only when >=1 relay
  ACKed a tombstone or kind-5 (anyRelayAcceptedInSummaries); an unconfirmed
  revert no longer aborts deleteAllVersions midway, so the kind-5 always runs

Tests: tests/relay-ack-unconfirmed-content.test.mjs (6).

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-03 21:01:31 -04:00
thePR0M3TH3ANandClaude Opus 4.8 47f2a9a865 [nostr] Fix spurious "failed" errors on unconfirmed list publishes across the board
Same class of bug as the subscription fix, applied everywhere an idempotent,
replaceable list is published with an optimistic UI: when no relay ACKs within the
10s window (slow/flaky relays), the event was still sent and almost always
persists (it shows up after a refresh), but assertAnyRelayAccepted threw -> the UI
showed a scary error / reverted, even though it worked.

- nostrPublish.js: add shared helpers relayPublishFailuresAreAllTimeouts() and
  assertAnyRelayAcceptedOrUnconfirmed() — the latter returns a summary flagged
  { unconfirmed: true } on all-timeout instead of throwing; explicit relay
  rejections (and pre-publish signer/encryption errors) still throw.
- Applied to the replaceable-list publishes: subscriptions (kind 30000, refactored
  to the shared helper), user mute/block list (10000), relay list (10002), DM
  relay hints (10050), hashtag preferences (30015).

Left as-is for now (higher-stakes, separate follow-up): the generic content
publish path (video/edit/delete/revert/rebroadcast) in publishHelpers/client.js —
same latent issue but the video outcome-describer needs careful handling.

Tests: tests/subscription-publish-timeout.test.mjs (8) now cover both the
classifier and assertAnyRelayAcceptedOrUnconfirmed (confirmed->summary,
all-timeout->soft, rejection->throws). hashtag-preferences suite green (14).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-01 15:20:58 -04:00
thePR0M3TH3ANandClaude Opus 4.8 3f4299a885 feat(publish): tell the user how many relays accepted their video
Publishing showed a flat "Video shared successfully!" even when most (or all)
relays rejected the event, so users couldn't tell a partial/failed publish from
a clean one. Now publishVideo captures the per-relay accept/reject summary and
stashes a compact {accepted,total} tally on the returned event via a
non-enumerable key (never serialized, never sent to relays). app.js reads it
back and reports the real outcome:
  - all relays accepted  -> "Video published to N relays!"
  - some rejected        -> warning "Video published to N of M relays …"
  - none accepted        -> error (defensive; this path normally throws first)
Falls back to the generic message when no tally is available.

Tests (describePublishOutcome + attach/readRelayPublishSummary): success/partial/
zero/singular/missing-tally messaging, and that the tally round-trips while
staying out of JSON serialization. Mutation-verified — flipping partial→success
and the summary key to enumerable both fail the suite.

Build + full lint green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 12:19:09 -04:00
thePR0M3TH3ANandClaude Opus 4.8 6984fb2ef9 fix(publish): handle nostr-tools array-return; stop uncaught rejection flood
publishEventToRelay expected the old nostr-tools publish handle (.on/.then), but
nostr-tools 2.17 SimplePool.publish(relays, event) returns an ARRAY of per-relay
promises. The array has neither .on nor .then, so the code (a) fell through to
the "optimistic success" path (publishes were never truly confirmed) and (b)
never attached a .catch to the inner promise — so every relay that rejected
("blocked", "auth-required", "publish timed out", websocket error, …) leaked an
unhandled promise rejection. With a large/flaky relay list (e.g. a 35-relay
account hitting many paid/restricted relays) that floods the event loop and can
freeze the tab — observed when republishing the relay list and when publishing a
video.

Fix: detect the array return and Promise.allSettled it — any fulfilled = success,
otherwise a failure result; every rejection is consumed. Confirmed publishes now
resolve from real acks instead of the optimistic fallback.

New tests assert a rejecting array-promise becomes a failure result with NO
unhandled rejection leak, a fulfilling one succeeds, and an all-rejecting publish
still resolves. Mutation-verified; existing publish tests pass under the suite.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 08:27:21 -04:00
thePR0M3TH3ANandClaude Opus 4.8 ac1dcff184 fix(publish): flag + log unconfirmed (optimistic) relay publishes
publishEventToRelay optimistically reports success when a relay handle exposes
no ok/failed event and isn't thenable (legacy 'seen'-only relays). That made an
UNCONFIRMED publish indistinguishable from a real ack, so a note could show
'Published' with nothing actually stored. The result now carries optimistic:true
for that path (callers can distinguish it from a confirmed ack) and logs a
dev.warn. Behavior is otherwise unchanged (still treated as success for legacy
relays). Publish audit #3.

Test: tests/nostr-publish-optimistic.test.mjs.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-16 20:28:27 -04:00
google-labs-jules[bot]andPR0M3TH3AN 6ef11d6125 perf(nostr): optimistic relay publishing
Implement "race-to-success" in publishEventToRelays to reduce perceived latency.
Default behavior now resolves as soon as one relay accepts the event.
Added `waitForAll: true` option for strict consistency requirements (e.g. watchHistory).

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-05 21:03:44 +00:00
thePR0M3TH3AN 7ae07b1369 refactor: migrate console usage to shared loggers 2025-10-15 14:37:25 -04:00
thePR0M3TH3AN d705cf176b Revert "Refactor logging to centralized logger" 2025-10-15 11:14:10 -04:00
thePR0M3TH3AN 37ba57aa37 Refactor logging to centralized logger 2025-10-15 11:11:14 -04:00
thePR0M3TH3AN bf088532dc Fix watch history publish errors against nostr-tools 1.8 2025-10-02 09:02:55 -04:00
thePR0M3TH3AN 92cc05f1f6 Refactor relay publish acknowledgements 2025-10-02 08:00:21 -04:00