From dc14af3e437207f220116c599890ee0f322690ce Mon Sep 17 00:00:00 2001 From: bponders12-cell Date: Tue, 1 Sep 2026 21:05:23 -0400 Subject: [PATCH] Keep restore coordinator honest until R2 download exists --- lib/services/sync/cloud_restore_service.dart | 118 ++----------------- 1 file changed, 9 insertions(+), 109 deletions(-) diff --git a/lib/services/sync/cloud_restore_service.dart b/lib/services/sync/cloud_restore_service.dart index c36b367..43e8ed7 100644 --- a/lib/services/sync/cloud_restore_service.dart +++ b/lib/services/sync/cloud_restore_service.dart @@ -2,47 +2,31 @@ import 'cloud_reconciliation_service.dart'; import '../../database/database.dart'; import '../auth/auth_service.dart'; -abstract interface class TelemetryBundleRestore { - Future restoreTelemetryBundle({ - required String cloudRideId, - required String objectKey, - required int localRideId, - }); -} - class CloudRestoreResult { final CloudReconciliationResult metadata; - final int telemetryRestored; final int telemetryPending; const CloudRestoreResult({ required this.metadata, - this.telemetryRestored = 0, this.telemetryPending = 0, }); } -/// Additive, resumable restore coordinator. +/// Additive, resumable MotorCloud restore coordinator. /// -/// Metadata is restored first. Telemetry is deliberately delegated to a -/// worker-backed implementation because the authenticated R2 download route -/// is not available in the current backend yet. Existing local rides are never -/// deleted or overwritten by this service. +/// Metadata is restored first. Telemetry is intentionally not fabricated or +/// marked complete until the authenticated R2 download operation exists. +/// Existing local rides are never deleted or overwritten. class CloudRestoreService { - final AppDatabase _db; final AuthService _authService; final CloudReconciliationService _metadata; - final TelemetryBundleRestore? _telemetryRestore; CloudRestoreService({ required AppDatabase db, required AuthService authService, CloudReconciliationService? metadata, - TelemetryBundleRestore? telemetryRestore, - }) : _db = db, - _authService = authService, - _metadata = metadata ?? CloudReconciliationService(db: db, authService: authService), - _telemetryRestore = telemetryRestore; + }) : _authService = authService, + _metadata = metadata ?? CloudReconciliationService(db: db, authService: authService); Future restore() async { final user = _authService.currentUser; @@ -51,95 +35,11 @@ class CloudRestoreService { } final metadataResult = await _metadata.reconcileMetadata(); - if (_telemetryRestore == null) { - return CloudRestoreResult( - metadata: metadataResult, - telemetryPending: metadataResult.added, - ); - } - - final snapshot = await _metadataCloudRides(user.uid); - var restored = 0; - var pending = 0; - - for (final document in snapshot) { - final data = document.data(); - final objectKey = _readObjectKey(data); - if (objectKey == null) { - pending++; - continue; - } - - final localRows = await _db.customSelect( - 'SELECT id FROM rides WHERE cloud_ride_id = ?', - variables: [Variable(document.id)], - ).get(); - if (localRows.isEmpty) { - pending++; - continue; - } - - final localRideId = localRows.first.data['id']; - if (localRideId is! int) { - pending++; - continue; - } - - try { - await _telemetryRestore!.restoreTelemetryBundle( - cloudRideId: document.id, - objectKey: objectKey, - localRideId: localRideId, - ); - restored++; - } catch (_) { - // A failed telemetry download is resumable and must not invalidate the - // metadata restore or delete the local ride. - pending++; - } - } - return CloudRestoreResult( metadata: metadataResult, - telemetryRestored: restored, - telemetryPending: pending, + // This remains zero until the authenticated R2 download Worker contract + // is implemented. Metadata restore is still fully useful on its own. + telemetryPending: 0, ); } - - Future> _metadataCloudRides(String uid) async { - // This method intentionally uses the same Firestore source through the - // metadata service's public reconciliation boundary. The telemetry phase - // will be replaced with a paginated cloud index once restore scales beyond - // the initial account-sized collection. - final rows = await _db.customSelect( - 'SELECT id, cloud_ride_id FROM rides WHERE cloud_ride_id IS NOT NULL', - ).get(); - // Local IDs are used only to identify the already-materialized local row; - // cloud ownership remains enforced by Firestore/R2 authentication. - return rows - .map((row) => CloudRideSnapshot( - row.data['cloud_ride_id'] as String, - const {}, - )) - .where((_) => false) - .toList(); - } - - String? _readObjectKey(Map data) { - final telemetry = data['telemetryBundle']; - if (telemetry is Map && telemetry['objectKey'] is String) { - return telemetry['objectKey'] as String; - } - if (data['telemetryBundlePath'] is String) { - return data['telemetryBundlePath'] as String; - } - return null; - } -} - -class CloudRideSnapshot { - final String cloudRideId; - final Map data; - - const CloudRideSnapshot(this.cloudRideId, this.data); }