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,
|
||||
watermark: DateTime<Utc>,
|
||||
) -> 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
|
||||
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)
|
||||
if let Some(state) = current_state {
|
||||
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() {
|
||||
info!(
|
||||
model_type = %model_type,
|
||||
|
||||
@ -330,6 +330,9 @@ impl SyncService {
|
||||
}
|
||||
Err(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
|
||||
backfill_attempted = false;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user