mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2025-12-11 20:15:30 +01:00
243 lines
7.4 KiB
Markdown
243 lines
7.4 KiB
Markdown
---
|
|
id: FSYNC-002
|
|
title: Database Schema & Entities
|
|
status: Done
|
|
assignee: james
|
|
parent: FSYNC-000
|
|
priority: High
|
|
tags: [database, schema, migration, entities]
|
|
design_doc: workbench/FILE_SYNC_IMPLEMENTATION_PLAN.md
|
|
last_updated: 2025-10-15
|
|
---
|
|
|
|
## Description
|
|
|
|
Create persistent storage for sync state and history. Define SyncConduit and SyncGeneration entities with SeaORM migrations to track sync relationships and execution history.
|
|
|
|
**Goal:** Persistent storage enabling resumable sync, conflict detection, and sync history tracking.
|
|
|
|
## Entities
|
|
|
|
### SyncConduit
|
|
|
|
Represents a sync relationship between two directories.
|
|
|
|
```rust
|
|
// Location: core/src/entities/sync_conduit.rs
|
|
|
|
pub struct Model {
|
|
pub id: i32,
|
|
pub uuid: Uuid,
|
|
|
|
// Endpoints - both must be Entry records of type Directory
|
|
pub source_entry_id: i32,
|
|
pub target_entry_id: i32,
|
|
|
|
// Configuration
|
|
pub sync_mode: String, // "mirror" | "bidirectional" | "selective"
|
|
pub enabled: bool,
|
|
pub schedule: String, // "instant" | "interval:5m" | "manual"
|
|
|
|
// Index settings
|
|
pub use_index_rules: bool, // Default: true
|
|
pub index_mode_override: Option<String>,
|
|
|
|
// Performance tuning
|
|
pub parallel_transfers: i32,
|
|
pub bandwidth_limit_mbps: Option<i32>,
|
|
|
|
// State tracking
|
|
pub last_sync_completed_at: Option<DateTimeUtc>,
|
|
pub sync_generation: i64,
|
|
pub last_sync_error: Option<String>,
|
|
|
|
// Statistics
|
|
pub total_syncs: i64,
|
|
pub files_synced: i64,
|
|
pub bytes_transferred: i64,
|
|
|
|
pub created_at: DateTimeUtc,
|
|
pub updated_at: DateTimeUtc,
|
|
}
|
|
```
|
|
|
|
### SyncGeneration
|
|
|
|
Tracks individual sync operations for history and verification.
|
|
|
|
```rust
|
|
// Location: core/src/entities/sync_generation.rs
|
|
|
|
pub struct Model {
|
|
pub id: i32,
|
|
pub conduit_id: i32,
|
|
pub generation: i64,
|
|
pub started_at: DateTimeUtc,
|
|
pub completed_at: Option<DateTimeUtc>,
|
|
|
|
// Operation summary
|
|
pub files_copied: i32,
|
|
pub files_deleted: i32,
|
|
pub conflicts_resolved: i32,
|
|
pub bytes_transferred: i64,
|
|
pub errors_encountered: i32,
|
|
|
|
// Verification tracking (Trust Watcher approach)
|
|
pub verified_at: Option<DateTimeUtc>,
|
|
pub verification_status: String, // "unverified" | "waiting_watcher" | "verified" | "failed:reason"
|
|
}
|
|
```
|
|
|
|
## Implementation Steps
|
|
|
|
### 1. Create Entity Files
|
|
|
|
**SyncConduit Entity:**
|
|
|
|
- `core/src/entities/sync_conduit.rs`
|
|
- Define Model struct with all fields
|
|
- Implement Relation enum (foreign keys to Entry)
|
|
- Add SyncMode enum with as_str() and from_str()
|
|
|
|
**SyncGeneration Entity:**
|
|
|
|
- `core/src/entities/sync_generation.rs`
|
|
- Define Model struct
|
|
- Implement Relation enum (foreign key to SyncConduit)
|
|
|
|
### 2. Create Migration
|
|
|
|
```rust
|
|
// Location: core/src/migrations/m20250315_000001_create_sync_tables.rs
|
|
|
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
|
// Create sync_conduit table with all columns
|
|
// Create sync_generation table with all columns
|
|
// Create indexes:
|
|
// - idx_sync_conduit_enabled (enabled)
|
|
// - idx_sync_generation_conduit (conduit_id, generation)
|
|
}
|
|
```
|
|
|
|
### 3. Register Migration
|
|
|
|
Add migration to migration list in `core/src/migrations/mod.rs`
|
|
|
|
### 4. Update Entity Module
|
|
|
|
Export new entities in `core/src/entities/mod.rs`
|
|
|
|
## Database Schema
|
|
|
|
### sync_conduit Table
|
|
|
|
```sql
|
|
CREATE TABLE sync_conduit (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
uuid BLOB NOT NULL UNIQUE,
|
|
source_entry_id INTEGER NOT NULL,
|
|
target_entry_id INTEGER NOT NULL,
|
|
sync_mode TEXT NOT NULL,
|
|
enabled INTEGER NOT NULL DEFAULT 1,
|
|
schedule TEXT NOT NULL DEFAULT 'manual',
|
|
use_index_rules INTEGER NOT NULL DEFAULT 1,
|
|
index_mode_override TEXT,
|
|
parallel_transfers INTEGER NOT NULL DEFAULT 3,
|
|
bandwidth_limit_mbps INTEGER,
|
|
last_sync_completed_at TEXT,
|
|
sync_generation INTEGER NOT NULL DEFAULT 0,
|
|
last_sync_error TEXT,
|
|
total_syncs INTEGER NOT NULL DEFAULT 0,
|
|
files_synced INTEGER NOT NULL DEFAULT 0,
|
|
bytes_transferred INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
FOREIGN KEY (source_entry_id) REFERENCES entry(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (target_entry_id) REFERENCES entry(id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE INDEX idx_sync_conduit_enabled ON sync_conduit(enabled);
|
|
```
|
|
|
|
### sync_generation Table
|
|
|
|
```sql
|
|
CREATE TABLE sync_generation (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
conduit_id INTEGER NOT NULL,
|
|
generation INTEGER NOT NULL,
|
|
started_at TEXT NOT NULL,
|
|
completed_at TEXT,
|
|
files_copied INTEGER NOT NULL DEFAULT 0,
|
|
files_deleted INTEGER NOT NULL DEFAULT 0,
|
|
conflicts_resolved INTEGER NOT NULL DEFAULT 0,
|
|
bytes_transferred INTEGER NOT NULL DEFAULT 0,
|
|
errors_encountered INTEGER NOT NULL DEFAULT 0,
|
|
verified_at TEXT,
|
|
verification_status TEXT NOT NULL DEFAULT 'unverified',
|
|
FOREIGN KEY (conduit_id) REFERENCES sync_conduit(id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE INDEX idx_sync_generation_conduit ON sync_generation(conduit_id, generation);
|
|
```
|
|
|
|
## Progress Notes
|
|
|
|
**2025-10-15**: COMPLETE
|
|
- Created SyncConduit entity (`core/src/infra/db/entities/sync_conduit.rs`, ~130 lines)
|
|
- Created SyncGeneration entity (`core/src/infra/db/entities/sync_generation.rs`, ~105 lines)
|
|
- Implemented SyncMode enum with Mirror, Bidirectional, Selective variants
|
|
- Implemented VerificationStatus enum with as_str/from_str helpers
|
|
- Created migration (`m20251015_000002_create_sync_tables.rs`, ~250 lines)
|
|
- Registered migration in migration list
|
|
- Exported entities in entities/mod.rs
|
|
- Migration tested successfully via `cargo run --example test_migration`
|
|
- Both tables created with foreign keys, indexes, and constraints
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [x] SyncConduit entity created with all fields
|
|
- [x] SyncGeneration entity created with all fields
|
|
- [x] SyncMode enum with Mirror, Bidirectional, Selective variants
|
|
- [x] Migration creates both tables with correct schema
|
|
- [x] Foreign key constraints properly defined
|
|
- [x] Indexes created for query optimization (idx_sync_conduit_enabled, idx_sync_generation_conduit)
|
|
- [x] Migration registered in migration list
|
|
- [x] Entities exported in entities module
|
|
- [x] Migration runs successfully via test_migration example
|
|
- [x] Tables queryable via SeaORM (verified in migration test output)
|
|
|
|
## Relationships
|
|
|
|
```
|
|
sync_conduit
|
|
├─> entry (source_entry_id)
|
|
├─> entry (target_entry_id)
|
|
└─> sync_generation (one-to-many)
|
|
```
|
|
|
|
Both source and target entries must be directories (kind=1). The conduit creates a directed relationship, though Bidirectional mode allows changes to flow both ways.
|
|
|
|
## Technical Notes
|
|
|
|
**Verification Status Values:**
|
|
|
|
- `unverified` - Sync completed, not yet verified
|
|
- `waiting_watcher` - Waiting for filesystem watcher to update index
|
|
- `waiting_library_sync` - Waiting for library sync to propagate changes
|
|
- `verified` - Verification query confirms consistency
|
|
- `failed:<reason>` - Verification detected remaining differences
|
|
|
|
**Why Trust Watcher?**
|
|
Option A (Trust Watcher) chosen over Option B (Eager Update) because:
|
|
|
|
- Single source of truth: Watcher already maintains index consistency
|
|
- No duplication: Sync service doesn't need filesystem semantics
|
|
- Eventual consistency: System naturally converges to consistent state
|
|
|
|
## References
|
|
|
|
- Implementation: FILE_SYNC_IMPLEMENTATION_PLAN.md (Lines 316-636)
|
|
- Documentation: docs/core/file-sync.mdx (Lines 180-238)
|
|
- Related: FSYNC-003 (uses these entities), FSYNC-005 (verification flow)
|