Skip to content

Add the peer-transport crate syncing document sessions between peers - #4869

Merged
TrueDoctor merged 1 commit into
masterfrom
graph-storage-12-transport
Oct 31, 2026
Merged

TrueDoctor merged 1 commit into
masterfrom
graph-storage-12-transport

Conversation

@TrueDoctor

Copy link
Copy Markdown
Member

No description provided.

@TrueDoctor
TrueDoctor added this pull request to stack #4870 October 30, 2026 22:01

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 11 files

Confidence score: 3/5

  • In replica.rs, a stale or guest link can send Sync while the replica is awaiting a response, overwrite the target, and emit Synced. Accept it only from the requested link while it still has the host role.
  • In replica.rs, peers joining after a cursor update never receive the current position. Retain and send the latest position during the join handshake, or explicitly reannounce it.
  • In target.rs, failed replay operations stay deferred and are retried on every poll without logging the error, so an operation that can never apply may churn silently. Log the failure and provide a way to avoid endless retries.
  • In lib.rs, mock is exported as public API in every build even though it is only used by tests. Gate the module with #[cfg(test)].

You’re at about 97% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="document/peer-transport/src/replica.rs">

<violation number="1" location="document/peer-transport/src/replica.rs:287">
P2: A peer joining after this cursor update never learns the current pointer because the replica does not cache or reannounce it. Retain the latest position and send it on the join handshake, or explicitly reannounce it to the new link.</violation>

<violation number="2" location="document/peer-transport/src/replica.rs:692">
P1: `Sync` is accepted from any link while awaiting, even if that link is not the requested host. A stale or guest response can overwrite the target and emit `Synced`; require the requested link and a current host role before applying it.</violation>
</file>

<file name="document/peer-transport/src/lib.rs">

<violation number="1" location="document/peer-transport/src/lib.rs:1">
P2: `mock` is only used by the test module in `replica.rs`, but this line exports it as public API in every build. Gate it with `#[cfg(test)] mod mock;` so the test harness stays out of the library.</violation>
</file>

<file name="document/peer-transport/src/target.rs">

<violation number="1" location="document/peer-transport/src/target.rs:121">
P2: `apply_remote_hot_ops` drops the error from every failed replay and keeps the op for retry. An op that can never apply stays in `deferred` and is retried on every poll, with no log of why it failed. Log the error and drop ops that fail for a reason other than a missing referent.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

log::debug!("Join handshake: sync answered with {} deltas and {} hot ops", sync.deltas.len(), sync.hot_log.len());
self.transport.send(from, &SyncPacket::Sync(Box::new(sync)))?;
}
SyncPacket::Sync(sync) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Sync is accepted from any link while awaiting, even if that link is not the requested host. A stale or guest response can overwrite the target and emit Synced; require the requested link and a current host role before applying it.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At document/peer-transport/src/replica.rs, line 692:

<comment>`Sync` is accepted from any link while awaiting, even if that link is not the requested host. A stale or guest response can overwrite the target and emit `Synced`; require the requested link and a current host role before applying it.</comment>

<file context>
@@ -0,0 +1,1124 @@
+				log::debug!("Join handshake: sync answered with {} deltas and {} hot ops", sync.deltas.len(), sync.hot_log.len());
+				self.transport.send(from, &SyncPacket::Sync(Box::new(sync)))?;
+			}
+			SyncPacket::Sync(sync) => {
+				log::debug!("Join handshake: sync received with {} deltas, full registry {}", sync.deltas.len(), sync.registry.is_some());
+				self.sync_requested_from = None;
</file context>

Comment thread document/peer-transport/src/replica.rs Resolved
if self.peers.is_empty() {
return Ok(());
}
self.transport.broadcast_except(None, &SyncPacket::Cursor { position })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: A peer joining after this cursor update never learns the current pointer because the replica does not cache or reannounce it. Retain the latest position and send it on the join handshake, or explicitly reannounce it to the new link.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At document/peer-transport/src/replica.rs, line 287:

<comment>A peer joining after this cursor update never learns the current pointer because the replica does not cache or reannounce it. Retain the latest position and send it on the join handshake, or explicitly reannounce it to the new link.</comment>

<file context>
@@ -0,0 +1,1124 @@
+		if self.peers.is_empty() {
+			return Ok(());
+		}
+		self.transport.broadcast_except(None, &SyncPacket::Cursor { position })
+	}
+
</file context>

Comment thread document/peer-transport/src/token.rs Resolved
@@ -0,0 +1,19 @@
pub mod mock;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: mock is only used by the test module in replica.rs, but this line exports it as public API in every build. Gate it with #[cfg(test)] mod mock; so the test harness stays out of the library.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At document/peer-transport/src/lib.rs, line 1:

<comment>`mock` is only used by the test module in `replica.rs`, but this line exports it as public API in every build. Gate it with `#[cfg(test)] mod mock;` so the test harness stays out of the library.</comment>

<file context>
@@ -0,0 +1,19 @@
+pub mod mock;
+mod packet;
+mod replica;
</file context>
Suggested change
pub mod mock;
#[cfg(test)]
mod mock;

Comment thread document/peer-transport/src/mock.rs Resolved

fn apply_remote_hot_ops(&mut self, ops: Vec<HotOp>) -> Result<Vec<HotOp>, TargetError> {
// A failure usually means a referent has not arrived.
Ok(ops.into_iter().filter(|hot_op| self.replay_hot_op(hot_op.clone()).is_err()).collect())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: apply_remote_hot_ops drops the error from every failed replay and keeps the op for retry. An op that can never apply stays in deferred and is retried on every poll, with no log of why it failed. Log the error and drop ops that fail for a reason other than a missing referent.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At document/peer-transport/src/target.rs, line 121:

<comment>`apply_remote_hot_ops` drops the error from every failed replay and keeps the op for retry. An op that can never apply stays in `deferred` and is retried on every poll, with no log of why it failed. Log the error and drop ops that fail for a reason other than a missing referent.</comment>

<file context>
@@ -0,0 +1,172 @@
+
+	fn apply_remote_hot_ops(&mut self, ops: Vec<HotOp>) -> Result<Vec<HotOp>, TargetError> {
+		// A failure usually means a referent has not arrived.
+		Ok(ops.into_iter().filter(|hot_op| self.replay_hot_op(hot_op.clone()).is_err()).collect())
+	}
+
</file context>

Comment thread document/peer-transport/src/target.rs Resolved
Comment thread document/peer-transport/src/mock.rs Resolved
Comment thread document/peer-transport/src/room.rs Resolved
@TrueDoctor
TrueDoctor force-pushed the graph-storage-12-transport branch from 3331916 to e103486 Compare October 31, 2026 16:01
@TrueDoctor
TrueDoctor merged commit 10d68f1 into master Oct 31, 2026
14 checks passed
@TrueDoctor
TrueDoctor deleted the graph-storage-12-transport branch October 31, 2026 18:07
@TrueDoctor TrueDoctor mentioned this pull request Oct 31, 2026
6 of 51 tasks

This branch was successfully deployed

1 active deployment
graphite-dev (Preview) — e1034867 Deployed Oct 31, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant