Preserve legacy cloud IDs during ride identity migration

This commit is contained in:
bponders12-cell 2026-09-01 21:03:35 -04:00
parent de06775682
commit f5a47bc83c
1 changed files with 22 additions and 8 deletions

View File

@ -23,12 +23,9 @@ class AppDatabase extends _$AppDatabase {
@override @override
MigrationStrategy get migration => MigrationStrategy( MigrationStrategy get migration => MigrationStrategy(
onCreate: (Migrator m) async { onCreate: (Migrator m) async {
// cloudRideId is part of the generated Drift schema. Do not manually
// ALTER this column here: generated sources are authoritative for fresh DBs.
await m.createAll(); await m.createAll();
// database.g.dart is generated during normal development/CI. Keep the
// schema self-healing for installations that temporarily have a stale
// generated file: cloud identity must exist even on a brand-new DB.
await customStatement('ALTER TABLE rides ADD COLUMN cloud_ride_id TEXT');
await customStatement('CREATE UNIQUE INDEX rides_cloud_ride_id_idx ON rides(cloud_ride_id)');
}, },
onUpgrade: (Migrator m, int from, int to) async { onUpgrade: (Migrator m, int from, int to) async {
if (from < 2) { if (from < 2) {
@ -75,15 +72,32 @@ class AppDatabase extends _$AppDatabase {
} }
if (from < 6) { if (from < 6) {
await m.addColumn(rides, rides.cloudRideId); await m.addColumn(rides, rides.cloudRideId);
await customStatement('CREATE UNIQUE INDEX rides_cloud_ride_id_idx ON rides(cloud_ride_id)'); await customStatement('CREATE UNIQUE INDEX IF NOT EXISTS rides_cloud_ride_id_idx ON rides(cloud_ride_id)');
final rows = await customSelect('SELECT id FROM rides WHERE cloud_ride_id IS NULL').get();
// Existing MotorCloud records were keyed by the deterministic legacy
// identity ride_<localId>_<UTC yyyyMMdd_HHmmss>. Preserve that identity
// for pre-v6 rides so their cloud records remain addressable. New rides
// receive a reinstall-safe random stable ID in startRide().
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) {
await customStatement('UPDATE rides SET cloud_ride_id = ? WHERE id = ?', [_newCloudRideId(), row.data['id']]); final id = row.data['id'];
final rawStart = row.data['start_time'];
if (id is! int || rawStart == null) continue;
final startTime = DateTime.tryParse(rawStart.toString())?.toUtc();
if (startTime == null) continue;
final legacyId = _legacyCloudRideId(id, startTime);
await customStatement('UPDATE rides SET cloud_ride_id = ? WHERE id = ?', [legacyId, id]);
} }
} }
}, },
); );
String _legacyCloudRideId(int localRideId, DateTime startTimeUtc) {
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)}';
return 'ride_${localRideId}_$stamp';
}
String _newCloudRideId() { String _newCloudRideId() {
final bytes = List<int>.generate(16, (_) => _random.nextInt(256)); final bytes = List<int>.generate(16, (_) => _random.nextInt(256));
final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();