mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2025-12-11 20:15:30 +01:00
Guard against self-watermarks and apply backfill
Skip self-watermarks when peer is the local device; log a warning. Apply current_state in dependency order by computing registry order. Fall back to unordered if the computation fails. On automatic backfill failure, reset device state to Uninitialized. This triggers a retry and clears backfill_attempted.
This commit is contained in:
parent
0e5e9827d1
commit
e4c60c58ca
@ -115,6 +115,17 @@ impl ResourceWatermarkStore {
|
|||||||
resource_type: &str,
|
resource_type: &str,
|
||||||
watermark: DateTime<Utc>,
|
watermark: DateTime<Utc>,
|
||||||
) -> Result<(), WatermarkError> {
|
) -> Result<(), WatermarkError> {
|
||||||
|
// Prevent self-watermarks - device should never track watermarks for its own data
|
||||||
|
if peer_device_uuid == self.device_uuid {
|
||||||
|
tracing::warn!(
|
||||||
|
device_uuid = %self.device_uuid,
|
||||||
|
peer_device_uuid = %peer_device_uuid,
|
||||||
|
resource_type = %resource_type,
|
||||||
|
"Attempted to create self-watermark (device tracking itself) - skipping"
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
// Check if newer before updating
|
// Check if newer before updating
|
||||||
let existing = self.get(conn, peer_device_uuid, resource_type).await?;
|
let existing = self.get(conn, peer_device_uuid, resource_type).await?;
|
||||||
|
|
||||||
|
|||||||
@ -781,7 +781,25 @@ impl BackfillManager {
|
|||||||
// Apply current_state snapshot (contains pre-sync data not in peer_log)
|
// Apply current_state snapshot (contains pre-sync data not in peer_log)
|
||||||
if let Some(state) = current_state {
|
if let Some(state) = current_state {
|
||||||
if let Some(state_map) = state.as_object() {
|
if let Some(state_map) = state.as_object() {
|
||||||
for (model_type, records_value) in state_map {
|
// Get dependency-ordered list of models to prevent FK violations
|
||||||
|
// CRITICAL: Must apply parent models before children (e.g., user_metadata before user_metadata_tag)
|
||||||
|
let sync_order = match crate::infra::sync::registry::compute_registry_sync_order().await {
|
||||||
|
Ok(order) => order,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Failed to compute sync order, using unordered: {}", e);
|
||||||
|
// Fallback to unordered if dependency graph fails
|
||||||
|
state_map.keys().map(|k| k.clone()).collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Apply snapshot records in dependency order
|
||||||
|
for model_type in sync_order {
|
||||||
|
// Skip if model not in snapshot
|
||||||
|
let records_value = match state_map.get(&model_type) {
|
||||||
|
Some(val) => val,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(records_array) = records_value.as_array() {
|
if let Some(records_array) = records_value.as_array() {
|
||||||
info!(
|
info!(
|
||||||
model_type = %model_type,
|
model_type = %model_type,
|
||||||
|
|||||||
@ -330,6 +330,9 @@ impl SyncService {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("Automatic backfill failed: {}", e);
|
warn!("Automatic backfill failed: {}", e);
|
||||||
|
// Reset state to Uninitialized so retry logic runs
|
||||||
|
let mut state = peer_sync.state.write().await;
|
||||||
|
*state = DeviceSyncState::Uninitialized;
|
||||||
// Reset flag to retry on next loop
|
// Reset flag to retry on next loop
|
||||||
backfill_attempted = false;
|
backfill_attempted = false;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user