5 KiB
Sync System Overview (PFAPI)
Last Updated: December 2025
This directory contains the legacy PFAPI synchronization implementation for Super Productivity. This system enables data sync across devices through file-based providers (Dropbox, WebDAV, Local File).
Note: Super Productivity now has two sync systems running in parallel:
- PFAPI Sync (this directory) - File-based sync via Dropbox/WebDAV
- Operation Log Sync - Operation-based sync via SuperSync Server
See Operation Log Architecture for the newer operation-based system.
Key Components
Core Services
sync.service.ts- Main orchestrator for sync operationsmeta-sync.service.ts- Handles sync metadata file operationsmodel-sync.service.ts- Manages individual model synchronizationconflict-handler.service.ts- User interface for conflict resolution
Sync Providers
Located in sync-providers/:
- Dropbox
- WebDAV
- Local File System
Sync Algorithm
The sync system uses vector clocks for accurate conflict detection:
- Physical Timestamps (
lastUpdate) - For ordering events - Vector Clocks (
vectorClock) - For accurate causality tracking and conflict detection - Sync State (
lastSyncedUpdate,lastSyncedVectorClock) - To track last successful sync
How Sync Works
1. Change Detection
When a user modifies data:
// In meta-model-ctrl.ts
lastUpdate = Date.now();
vectorClock[clientId] = vectorClock[clientId] + 1;
2. Sync Status Determination
The system compares local and remote metadata to determine:
- InSync: No changes needed
- UpdateLocal: Download remote changes
- UpdateRemote: Upload local changes
- Conflict: Both have changes (requires user resolution)
3. Conflict Detection
Uses vector clocks for accurate detection:
const comparison = compareVectorClocks(localVector, remoteVector);
if (comparison === VectorClockComparison.CONCURRENT) {
// True conflict - changes were made independently
}
4. Data Transfer
- Upload: Sends changed models and updated metadata
- Download: Retrieves and merges remote changes
- Conflict Resolution: User chooses which version to keep
Key Files
Metadata Structure
interface LocalMeta {
lastUpdate: number; // Physical timestamp
lastSyncedUpdate: number; // Last synced timestamp
vectorClock?: VectorClock; // Causality tracking
lastSyncedVectorClock?: VectorClock; // Last synced vector clock
revMap: RevMap; // Model revision map
crossModelVersion: number; // Schema version
}
Important Considerations
- Vector Clocks: Each client maintains its own counter for accurate causality tracking
- Backwards Compatibility: Supports migration from older versions
- Conflict Minimization: Vector clocks eliminate false conflicts
- Atomic Operations: Meta file serves as transaction coordinator
Common Sync Scenarios
Scenario 1: Simple Update
- Device A makes changes
- Device A uploads to cloud
- Device B downloads changes
- Both devices now in sync
Scenario 2: Conflict Resolution
- Device A and B both make changes
- Device A syncs first
- Device B detects conflict
- User chooses which version to keep
- Chosen version propagates to all devices
Scenario 3: Multiple Devices
- Devices A, B, C all synced
- Device A makes changes while offline
- Device B makes different changes
- Device C acts as intermediary
- Vector clocks ensure proper ordering
Debugging Sync Issues
- Enable verbose logging in
pfapi/api/util/log.ts - Check vector clock states in sync status
- Verify client IDs are stable
- Ensure metadata files are properly updated
Integration with Operation Log
When using file-based sync (Dropbox, WebDAV), the Operation Log system maintains compatibility through:
- Vector Clock Updates:
VectorClockFacadeServiceupdates the PFAPI meta-model's vector clock when operations are persisted locally - State Source: PFAPI reads current state from NgRx store (not from operation log IndexedDB)
- Bridge Effect:
updateModelVectorClock$inoperation-log.effects.tsensures clocks stay in sync
This allows users to:
- Use file-based sync (Dropbox/WebDAV) while benefiting from Operation Log's local persistence
- Migrate between sync providers without data loss
Future Direction
The PFAPI sync system is stable but not receiving new features. New sync features are being developed in the Operation Log system:
- ✅ Entity-level conflict resolution (Operation Log)
- ✅ Incremental sync (Operation Log)
- 📋 Planned: Deprecate file-based sync in favor of Operation Log with file fallback
Related Documentation
- Vector Clocks - Conflict detection implementation
- Operation Log Architecture - Newer operation-based sync
- Hybrid Manifest Architecture - File-based Operation Log sync