Handle Drift DateTime encoding during cloud ID migration

This commit is contained in:
bponders12-cell 2026-09-01 21:03:50 -04:00
parent f5a47bc83c
commit 485e102c93
1 changed files with 24 additions and 2 deletions

View File

@ -77,13 +77,13 @@ class AppDatabase extends _$AppDatabase {
// Existing MotorCloud records were keyed by the deterministic legacy // Existing MotorCloud records were keyed by the deterministic legacy
// identity ride_<localId>_<UTC yyyyMMdd_HHmmss>. Preserve that identity // identity ride_<localId>_<UTC yyyyMMdd_HHmmss>. Preserve that identity
// for pre-v6 rides so their cloud records remain addressable. New rides // for pre-v6 rides so their cloud records remain addressable. New rides
// receive a reinstall-safe random stable ID in startRide(). // receive an reinstall-safe random stable ID in startRide().
final rows = await customSelect('SELECT id, start_time FROM rides WHERE cloud_ride_id IS NULL').get(); final rows = await customSelect('SELECT id, start_time FROM rides WHERE cloud_ride_id IS NULL').get();
for (final row in rows) { for (final row in rows) {
final id = row.data['id']; final id = row.data['id'];
final rawStart = row.data['start_time']; final rawStart = row.data['start_time'];
if (id is! int || rawStart == null) continue; if (id is! int || rawStart == null) continue;
final startTime = DateTime.tryParse(rawStart.toString())?.toUtc(); final startTime = _decodeStoredDateTime(rawStart);
if (startTime == null) continue; if (startTime == null) continue;
final legacyId = _legacyCloudRideId(id, startTime); final legacyId = _legacyCloudRideId(id, startTime);
await customStatement('UPDATE rides SET cloud_ride_id = ? WHERE id = ?', [legacyId, id]); await customStatement('UPDATE rides SET cloud_ride_id = ? WHERE id = ?', [legacyId, id]);
@ -92,6 +92,28 @@ class AppDatabase extends _$AppDatabase {
}, },
); );
DateTime? _decodeStoredDateTime(Object raw) {
if (raw is DateTime) return raw.toUtc();
if (raw is num) {
final value = raw.toInt();
// Drift's native DateTime representation is epoch milliseconds. Accept
// microseconds too so migration remains safe across older storage adapters.
if (value.abs() >= 100000000000000) {
return DateTime.fromMicrosecondsSinceEpoch(value, isUtc: true);
}
return DateTime.fromMillisecondsSinceEpoch(value, isUtc: true);
}
final text = raw.toString();
final parsed = DateTime.tryParse(text);
if (parsed != null) return parsed.toUtc();
final numeric = int.tryParse(text);
if (numeric == null) return null;
if (numeric.abs() >= 100000000000000) {
return DateTime.fromMicrosecondsSinceEpoch(numeric, isUtc: true);
}
return DateTime.fromMillisecondsSinceEpoch(numeric, isUtc: true);
}
String _legacyCloudRideId(int localRideId, DateTime startTimeUtc) { String _legacyCloudRideId(int localRideId, DateTime startTimeUtc) {
String two(int value) => value.toString().padLeft(2, '0'); String two(int value) => value.toString().padLeft(2, '0');
final stamp = '${startTimeUtc.year.toString().padLeft(4, '0')}${two(startTimeUtc.month)}${two(startTimeUtc.day)}_${two(startTimeUtc.hour)}${two(startTimeUtc.minute)}${two(startTimeUtc.second)}'; final stamp = '${startTimeUtc.year.toString().padLeft(4, '0')}${two(startTimeUtc.month)}${two(startTimeUtc.day)}_${two(startTimeUtc.hour)}${two(startTimeUtc.minute)}${two(startTimeUtc.second)}';