grpc: directory replication API for websites to mirror accounts/channels
Snapshot (full read) + Subscribe (live stream) over the same committed-entry channel gossip uses. Identity and metadata only — password hashes, SCRAM verifiers, cert fingerprints, and the finer channel-ops-list events never cross this API. Bearer-token authenticated, optional server TLS. Verified end-to-end against a live test-net registration, not just unit tests.
This commit is contained in:
parent
bdcce01f11
commit
e5a0d2acdf
11 changed files with 1188 additions and 8 deletions
|
|
@ -236,6 +236,24 @@ impl LogEntry {
|
|||
}
|
||||
}
|
||||
|
||||
// Read-only accessors for consumers outside this module (the gRPC replication
|
||||
// layer subscribes to the same broadcast channel gossip does, and translates
|
||||
// each entry to a wire message).
|
||||
impl LogEntry {
|
||||
pub fn origin(&self) -> &str {
|
||||
&self.origin
|
||||
}
|
||||
pub fn seq(&self) -> u64 {
|
||||
self.seq
|
||||
}
|
||||
pub fn lamport(&self) -> u64 {
|
||||
self.lamport
|
||||
}
|
||||
pub fn event(&self) -> &Event {
|
||||
&self.event
|
||||
}
|
||||
}
|
||||
|
||||
// Append-only log, the sole persistent source of truth: `open` replays it,
|
||||
// `append` stamps and writes a locally-authored entry, and `ingest` folds in an
|
||||
// entry authored by another node. The version vector (highest seq applied per
|
||||
|
|
@ -886,6 +904,11 @@ impl Db {
|
|||
self.channels.values()
|
||||
}
|
||||
|
||||
/// All registered accounts, for a directory snapshot (see the gRPC layer).
|
||||
pub fn accounts(&self) -> impl Iterator<Item = &Account> {
|
||||
self.accounts.values()
|
||||
}
|
||||
|
||||
/// Names of channels founded by `account` (case-insensitive).
|
||||
pub fn channels_owned_by(&self, account: &str) -> Vec<String> {
|
||||
self.channels
|
||||
|
|
|
|||
|
|
@ -122,6 +122,11 @@ impl Engine {
|
|||
self.db.missing_for(peer)
|
||||
}
|
||||
|
||||
// A full read of current directory state, for the gRPC Snapshot RPC.
|
||||
pub fn directory_snapshot(&self) -> (Vec<db::Account>, Vec<db::ChannelInfo>) {
|
||||
(self.db.accounts().cloned().collect(), self.db.channels().cloned().collect())
|
||||
}
|
||||
|
||||
pub fn gossip_ingest(&mut self, entry: LogEntry) -> std::io::Result<()> {
|
||||
// If ingesting a peer's entry removed an account a local session relied on
|
||||
// (lost a conflict, or dropped elsewhere), clean up after it.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue