diff --git a/docs/watch-history-logging.md b/docs/watch-history-logging.md new file mode 100644 index 00000000..b5cf1e89 --- /dev/null +++ b/docs/watch-history-logging.md @@ -0,0 +1,15 @@ +# Watch History Logging Cheatsheet + +The watch history publisher emits developer-mode console messages from `publishWatchHistorySnapshot()`. + +- `Watch history snapshot updated` (info) — all chunks and the index event were accepted by at least one relay. The summary includes: + - `actor`: abbreviated pubkey that authored the snapshot. + - `itemCount`: number of watch history entries that made it into the snapshot payload. + - `snapshot`: identifier constructed from the current unix timestamp and a random suffix. + - `latestPointer`: truncated pointer key for the newest watch entry that survived chunking. + - `latestWatchedAt`: ISO timestamp derived from the most recent entry's `watchedAt` (falls back to `Date.now()` when missing). +- `Watch history snapshot publish incomplete` (warning) — at least one chunk or the index event failed to reach any relay. When this fires the snapshot is still cached locally and the client will retry publication later. + +Errors that precede the info log do **not** necessarily indicate a failure. For example, a message like `WebSocket connection to 'ws://127.0.0.1:4869/' failed` simply means one relay in the user's configured relay list is offline. The publisher only requires that at least one relay accepts each chunk before reporting success. + +Refer to the log source in `js/nostr.js` for the exact structure and retry behavior. diff --git a/js/nostr.js b/js/nostr.js index 70221267..c23c7579 100644 --- a/js/nostr.js +++ b/js/nostr.js @@ -2558,6 +2558,35 @@ class NostrClient { this.scheduleWatchHistoryRepublish(normalizedActor, persistedItems); } + if (isDevMode) { + const latestItem = persistedItems[0] || null; + const latestPointerKey = pointerKey(latestItem); + const latestPointerSummary = latestPointerKey + ? latestPointerKey.length > 32 + ? `${latestPointerKey.slice(0, 32)}…` + : latestPointerKey + : null; + const actorPreview = + normalizedActor.length > 16 + ? `${normalizedActor.slice(0, 8)}…${normalizedActor.slice(-4)}` + : normalizedActor; + const summary = { + actor: actorPreview, + itemCount: persistedItems.length, + snapshot: snapshotId, + latestPointer: latestPointerSummary, + latestWatchedAt: Number.isFinite(latestItem?.watchedAt) + ? new Date(Math.max(0, Math.floor(latestItem.watchedAt))).toISOString() + : null, + }; + + if (overallSuccess) { + console.info("[nostr] Watch history snapshot updated:", summary); + } else { + console.warn("[nostr] Watch history snapshot publish incomplete:", summary); + } + } + const pointerEvent = signedIndexEvent || chunkResults.find((chunk) => chunk.success)?.event ||