fix: migrate offline sync outbox into authenticated account
This commit is contained in:
parent
2fd5e888f7
commit
58659e8f7f
|
|
@ -12,12 +12,13 @@ class SyncOutbox {
|
||||||
Future<void> _saveChain = Future<void>.value();
|
Future<void> _saveChain = Future<void>.value();
|
||||||
bool _isLoaded = false;
|
bool _isLoaded = false;
|
||||||
|
|
||||||
/// The namespace must be tied to the current Firebase UID (or a local
|
/// The namespace is account-scoped. Pending work recorded before login is
|
||||||
/// signed-out namespace). This prevents one account's sync state from being
|
/// migrated from the local namespace into the newly authenticated account
|
||||||
/// mistaken for another account's state on the same device.
|
/// so offline rides do not become stranded when the user signs in later.
|
||||||
SyncOutbox(this._prefs, {String? storageNamespace})
|
SyncOutbox(this._prefs, {String? storageNamespace})
|
||||||
: _storageNamespace = _normalizeNamespace(storageNamespace) {
|
: _storageNamespace = _normalizeNamespace(storageNamespace) {
|
||||||
load();
|
load();
|
||||||
|
if (_storageNamespace != 'local') _migrateLocalPendingItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
static String _normalizeNamespace(String? value) {
|
static String _normalizeNamespace(String? value) {
|
||||||
|
|
@ -57,6 +58,43 @@ class SyncOutbox {
|
||||||
_isLoaded = true;
|
_isLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _migrateLocalPendingItems() {
|
||||||
|
final localKey = '${_outboxStorageKeyPrefix}_local';
|
||||||
|
final rawJson = _prefs.getString(localKey);
|
||||||
|
if (rawJson == null || rawJson.trim().isEmpty) return;
|
||||||
|
|
||||||
|
var migrated = 0;
|
||||||
|
try {
|
||||||
|
final decoded = jsonDecode(rawJson);
|
||||||
|
if (decoded is List) {
|
||||||
|
for (final entry in decoded) {
|
||||||
|
try {
|
||||||
|
final map = entry is Map<String, dynamic> ? entry : Map<String, dynamic>.from(entry as Map);
|
||||||
|
final item = SyncItem.fromJson(map);
|
||||||
|
// Local namespace work cannot legitimately be cloud-synced yet;
|
||||||
|
// keep only pending work and rebind it to the current provider.
|
||||||
|
if (item.status.isPending) {
|
||||||
|
_items[item.key] = item.status == SyncStatus.uploading
|
||||||
|
? item.copyWith(status: SyncStatus.queued, clearNextRetry: true)
|
||||||
|
: item;
|
||||||
|
migrated++;
|
||||||
|
}
|
||||||
|
} catch (itemError) {
|
||||||
|
debugPrint('[SyncOutbox] Skipped local migration item: $itemError');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('[SyncOutbox] Local outbox migration skipped: $e');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (migrated > 0) {
|
||||||
|
_prefs.setString(storageKey, jsonEncode(_items.values.map((e) => e.toJson()).toList()));
|
||||||
|
_prefs.remove(localKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<bool> _save() {
|
Future<bool> _save() {
|
||||||
final operation = _saveChain.then((_) async {
|
final operation = _saveChain.then((_) async {
|
||||||
if (_items.length > maxOutboxCapacity) {
|
if (_items.length > maxOutboxCapacity) {
|
||||||
|
|
@ -88,9 +126,7 @@ class SyncOutbox {
|
||||||
final key = '$normalizedProvider:$localRideId';
|
final key = '$normalizedProvider:$localRideId';
|
||||||
final existing = _items[key];
|
final existing = _items[key];
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
if (existing.status == SyncStatus.synced || existing.status == SyncStatus.queued || existing.status == SyncStatus.uploading) {
|
if (existing.status == SyncStatus.synced || existing.status == SyncStatus.queued || existing.status == SyncStatus.uploading) return existing;
|
||||||
return existing;
|
|
||||||
}
|
|
||||||
final rearmed = existing.copyWith(status: SyncStatus.queued, clearLastError: true, clearNextRetry: true);
|
final rearmed = existing.copyWith(status: SyncStatus.queued, clearLastError: true, clearNextRetry: true);
|
||||||
_items[key] = rearmed;
|
_items[key] = rearmed;
|
||||||
await _save();
|
await _save();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue