update
This commit is contained in:
+35
-12
@@ -222,19 +222,39 @@ let messages = fold(&rumors, Timestamp::now(), |actor, citation, author| {
|
||||
Relay history pages through the local cache:
|
||||
|
||||
```rust
|
||||
use community::history::{self, Window};
|
||||
use community::history::{self, PageRegistry, Window};
|
||||
|
||||
let page = history::page(client, &channel, &held, &relays, Window::newest(), 20, 50).await?;
|
||||
// The same registry `CommunityRegistry` shares with its notification pump: it is
|
||||
// what carries each page's EOSE and CLOSED back to the round waiting on it.
|
||||
let page = history::page(
|
||||
client,
|
||||
&pages,
|
||||
&channel,
|
||||
&held,
|
||||
&relays,
|
||||
Window::opening(cursor),
|
||||
20,
|
||||
50,
|
||||
)
|
||||
.await?;
|
||||
let cached = cache::query_rumors(&client, &channel, None, 50, Some(&cord03::ROW_KINDS)).await?;
|
||||
```
|
||||
|
||||
A relay is only ever *asked*: `history::page` subscribes each one to the page's
|
||||
filter (which is what makes the client verify a wrap, deduplicate it and persist
|
||||
it), waits for EOSE, and then reads the page back out of the local database —
|
||||
no wrap is ever consumed straight off the wire, and `fetch_events` is not used
|
||||
anywhere. The wrap lands in the client's shared event store through that
|
||||
ordinary ingest path; `cache_rumor` then puts the decrypted rumor beside it, and
|
||||
only the rumor is ever served to a reader.
|
||||
A relay is only ever *asked*: `history::page` installs **one REQ per page** over
|
||||
`ReqTarget::manual` for the community's own relays (which is what makes the client
|
||||
verify a wrap, deduplicate it and persist it), waits for every relay to settle,
|
||||
and then reads the page back out of the local database — no wrap is ever consumed
|
||||
straight off the wire, and `fetch_events` is not used anywhere. The wrap lands in
|
||||
the client's shared event store through that ordinary ingest path; `cache_rumor`
|
||||
then puts the decrypted rumor beside it, and only the rumor is ever served to a
|
||||
reader.
|
||||
|
||||
EOSE and CLOSED are **not** watched inside the page. The registry's notification
|
||||
pump is the only consumer of `client.notifications()`; it delivers one
|
||||
`PageReport` per settling relay into the `PageRegistry` under the page's
|
||||
subscription id, and the page waits on that channel with `PAGE_TIMEOUT`. The id
|
||||
is opaque (`concord-history-<n>`) because a NIP-01 id is capped at 64 characters,
|
||||
and the registry is what maps it back to the waiting round.
|
||||
|
||||
A page ends on EOSE. A CLOSED ends it as unanswered, *except* NIP-42's
|
||||
`auth-required`: the SDK re-issues that REQ under the same subscription id once
|
||||
@@ -246,11 +266,14 @@ reports what it saw: `oldest_ms`/`newest_ms` feed the caller's `ChannelCursor`,
|
||||
`exhausted` is earned only by a short page *after* history was seen, and an
|
||||
all-empty answer sets `failed` so a later round re-asks instead of sealing the
|
||||
channel at "no more history". Page down with `Window::older_than(seen.oldest_ms)`,
|
||||
open a channel with `Window::opening(cursor)` (wide cold, `newest_ms - 60s` warm),
|
||||
and read the region between two cursors with `Window::between(..)`. `query_rumors`
|
||||
is the read path when the group keys are gone; pass `kinds` to budget rows apart
|
||||
from the events that only decorate them. Run `cache::purge_expired(client, &channel, now)`
|
||||
on the same cadence as any other local sweep — the timer is cooperative, so the
|
||||
local store is the artifact that has to forget.
|
||||
from the events that only decorate them. `cache::wrapper_index` reads the cached
|
||||
rows back keyed by the wrap they came from, which is what lets `sync::fold` observe
|
||||
author and message times without re-opening a wrap it already cached, and
|
||||
`cache::purge_expired(client, &channel, now)` runs at the top of every round — the
|
||||
timer is cooperative, so the local store is the artifact that has to forget.
|
||||
|
||||
`ChatAction::TimerNotice { seconds }` is a policy notice, not a message: render it
|
||||
as an inline row only when its author passes
|
||||
|
||||
Reference in New Issue
Block a user