Archived
rename crates/ to engrams/, bindings/ to receptors/
- crates/ → engrams/ (Rust engrams live here) - bindings/ → receptors/ (cross-language access points into the graph) - Cargo.toml workspace paths updated
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
/// HTTP client for talking to a remote Engram peer.
|
||||
///
|
||||
/// All peer-to-peer communication goes through this client.
|
||||
/// Authentication is via `Authorization: Bearer {api_key}` on every request.
|
||||
use crate::types::{Peer, SerializableActivatedNode, SyncDelta};
|
||||
use anyhow::Context;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub struct SyncClient {
|
||||
peer: Peer,
|
||||
http: reqwest::Client,
|
||||
our_id: Uuid,
|
||||
}
|
||||
|
||||
impl SyncClient {
|
||||
pub fn new(peer: Peer, our_id: Uuid) -> Self {
|
||||
let http = reqwest::Client::builder()
|
||||
.timeout(std::time::Duration::from_secs(30))
|
||||
.build()
|
||||
.expect("failed to build reqwest client");
|
||||
Self { peer, http, our_id }
|
||||
}
|
||||
|
||||
/// Pull a delta from the remote peer containing everything since `since` (Unix ms).
|
||||
///
|
||||
/// GET {address}/sync/delta?since={since}&peer_id={our_id}
|
||||
pub async fn pull_delta(&self, since: i64) -> anyhow::Result<SyncDelta> {
|
||||
let url = format!(
|
||||
"{}/sync/delta?since={}&peer_id={}",
|
||||
self.peer.address, since, self.our_id
|
||||
);
|
||||
let resp = self
|
||||
.http
|
||||
.get(&url)
|
||||
.header("Authorization", format!("Bearer {}", self.peer.api_key))
|
||||
.send()
|
||||
.await
|
||||
.context("pull_delta: request failed")?;
|
||||
|
||||
if !resp.status().is_success() {
|
||||
let status = resp.status();
|
||||
let body = resp.text().await.unwrap_or_default();
|
||||
anyhow::bail!("pull_delta: peer returned {}: {}", status, body);
|
||||
}
|
||||
|
||||
resp.json::<SyncDelta>()
|
||||
.await
|
||||
.context("pull_delta: failed to decode response")
|
||||
}
|
||||
|
||||
/// Push our delta to the remote peer.
|
||||
///
|
||||
/// POST {address}/sync/push
|
||||
pub async fn push_delta(&self, delta: &SyncDelta) -> anyhow::Result<()> {
|
||||
let url = format!("{}/sync/push", self.peer.address);
|
||||
let resp = self
|
||||
.http
|
||||
.post(&url)
|
||||
.header("Authorization", format!("Bearer {}", self.peer.api_key))
|
||||
.json(delta)
|
||||
.send()
|
||||
.await
|
||||
.context("push_delta: request failed")?;
|
||||
|
||||
if !resp.status().is_success() {
|
||||
let status = resp.status();
|
||||
let body = resp.text().await.unwrap_or_default();
|
||||
anyhow::bail!("push_delta: peer returned {}: {}", status, body);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fan spreading activation out to a remote peer.
|
||||
///
|
||||
/// POST {address}/swarm/activate — the remote peer runs activation locally
|
||||
/// (include_peers=false so it does not fan out further, preventing cycles).
|
||||
pub async fn remote_activate(
|
||||
&self,
|
||||
seeds: &[Uuid],
|
||||
query_embedding: &[f32],
|
||||
max_depth: u8,
|
||||
limit: usize,
|
||||
) -> anyhow::Result<Vec<SerializableActivatedNode>> {
|
||||
use crate::types::SwarmActivateRequest;
|
||||
|
||||
let url = format!("{}/swarm/activate", self.peer.address);
|
||||
let req = SwarmActivateRequest {
|
||||
seeds: seeds.to_vec(),
|
||||
query_embedding: query_embedding.to_vec(),
|
||||
max_depth,
|
||||
limit,
|
||||
include_peers: false, // no further fan-out — prevents cycles
|
||||
};
|
||||
|
||||
let resp = self
|
||||
.http
|
||||
.post(&url)
|
||||
.header("Authorization", format!("Bearer {}", self.peer.api_key))
|
||||
.json(&req)
|
||||
.send()
|
||||
.await
|
||||
.context("remote_activate: request failed")?;
|
||||
|
||||
if !resp.status().is_success() {
|
||||
let status = resp.status();
|
||||
let body = resp.text().await.unwrap_or_default();
|
||||
anyhow::bail!("remote_activate: peer returned {}: {}", status, body);
|
||||
}
|
||||
|
||||
// The remote returns a SwarmActivateResponse; we only want local_results
|
||||
let response: crate::types::SwarmActivateResponse = resp
|
||||
.json()
|
||||
.await
|
||||
.context("remote_activate: failed to decode response")?;
|
||||
Ok(response.local_results)
|
||||
}
|
||||
|
||||
pub fn peer(&self) -> &Peer {
|
||||
&self.peer
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user