Phase 2c (0.6.1-beta): route engagement diffs through file_holders

propagate_engagement_diff now targets the post's flat holder set (up to
5 most-recent) instead of the post_downstream directional tree. The
holder set naturally subsumes the old upstream+downstream partition, so
the separate "also send to upstreams" loops at each engagement call
site are removed (reactions, comments, comment edit/delete, receipt
slots, comment slots).

handle_blob_header_diff on receive:
- records the sending peer as a file holder (an engagement exchange is
  proof the peer holds the post)
- re-propagates to the holder set minus the sender

Writes to post_upstream / post_downstream still occur from Phase 2b
(dual-write); those and the legacy tables will be removed in 2e.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Scott Reimers 2026-04-21 21:00:53 -04:00
parent 0b2b4f5a68
commit 3a0d2e93ab
3 changed files with 28 additions and 77 deletions

View file

@ -2320,24 +2320,24 @@ impl Network {
self.endpoint.close().await;
}
/// Propagate an engagement diff to all downstream holders of a post (CDN tree).
/// Excludes the sender to avoid loops.
/// Propagate an engagement diff to all known holders of a post (flat set,
/// up to 5 most-recent). Excludes the sender to avoid loops.
pub async fn propagate_engagement_diff(
&self,
post_id: &crate::types::PostId,
payload: &crate::protocol::BlobHeaderDiffPayload,
exclude_peer: &crate::types::NodeId,
) -> usize {
let downstream = {
let holders = {
let storage = self.storage.get().await;
storage.get_post_downstream(post_id).unwrap_or_default()
storage.get_file_holders(post_id).unwrap_or_default()
};
let mut sent = 0;
for ds_nid in &downstream {
if ds_nid == exclude_peer {
for (peer, _addrs) in &holders {
if peer == exclude_peer {
continue;
}
if self.send_to_peer_uni(ds_nid, MessageType::BlobHeaderDiff, payload).await.is_ok() {
if self.send_to_peer_uni(peer, MessageType::BlobHeaderDiff, payload).await.is_ok() {
sent += 1;
}
}