use std::sync::Arc;
use nodedb_types::sync::wire::{ArrayAdvisoryRefusedMsg, ArrayRejectMsg, PingPongMsg, SyncFrame};
use crate::sync::client::SyncClient;
use crate::sync::delegate::SyncDelegate;
pub(super) async fn handle_array_reject(
client: &Arc<SyncClient>,
delegate: &Arc<dyn SyncDelegate>,
frame: &SyncFrame,
) {
let Some(msg) = frame.decode_body::<ArrayRejectMsg>() else {
tracing::warn!("ArrayReject: failed to decode frame body");
return;
};
client.array_push().lock().await.record_reject(&msg);
if let Some(request) = delegate.handle_array_reject(&msg).await {
client.queue_array_catchup(request).await;
}
}
pub(super) fn handle_array_advisory_refused(frame: &SyncFrame) {
let Some(msg) = frame.decode_body::<ArrayAdvisoryRefusedMsg>() else {
tracing::warn!("ArrayAdvisoryRefused: failed to decode frame body");
return;
};
tracing::warn!(
array = %msg.array,
request = ?msg.request,
reason = ?msg.reason,
class = ?msg.reason.class(),
detail = %msg.detail,
"Origin refused an advisory array request"
);
}
pub(super) async fn handle_ping_pong(
client: &Arc<SyncClient>,
delegate: &Arc<dyn SyncDelegate>,
frame: &SyncFrame,
) {
let Some(msg) = frame.decode_body::<PingPongMsg>() else {
tracing::warn!("PingPong: failed to decode frame body");
return;
};
if !msg.is_pong {
tracing::trace!("received ping from Origin");
return;
}
let Some(outcome) = client
.array_push()
.lock()
.await
.complete_barrier(msg.timestamp_ms)
else {
return;
};
if outcome.parked_unattributed > 0 {
tracing::error!(
ops = outcome.parked_unattributed,
"array push: Origin refused a frame without naming the op; the window's ops \
stay queued until the next session"
);
}
if outcome.confirmed.is_empty() {
return;
}
match delegate.retire_array_ops(&outcome.confirmed).await {
Ok(()) => tracing::debug!(
ops = outcome.confirmed.len(),
"array push: Origin applied the window; ops retired"
),
Err(e) => tracing::warn!(
error = %e,
"array push: retiring applied ops failed; they stay queued and the next session \
re-sends them, which Origin deduplicates by HLC"
),
}
}