fix: Fix the demo app when migrations mismatch (#93)
This commit is contained in:
parent
65832eda0a
commit
a9fa6b6b91
3 changed files with 50 additions and 5 deletions
|
|
@ -1011,9 +1011,10 @@ class DemoController extends ChangeNotifier {
|
|||
if (!dbDir.existsSync()) {
|
||||
dbDir.createSync(recursive: true);
|
||||
}
|
||||
final replica = await OfflineReplica.open(
|
||||
final databasePath = p.join(dbDir.path, '${user.username}-${slot.name}.db');
|
||||
final replica = await OfflineReplica.openOrReset(
|
||||
client: client,
|
||||
databasePath: p.join(dbDir.path, '${user.username}-${slot.name}.db'),
|
||||
databasePath: databasePath,
|
||||
persistentUserId: user.authUserId,
|
||||
);
|
||||
_sessions[key] = replica;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
import 'package:flutter/foundation.dart' show kDebugMode;
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart' show debugPrint, kDebugMode;
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:serverpod_database/serverpod_database.dart'
|
||||
show ClientDatabaseSession;
|
||||
import 'package:serverpod_offline_sync_client/serverpod_offline_sync_client.dart';
|
||||
|
|
@ -13,8 +16,10 @@ import 'table_ops.dart' show demoSyncTables;
|
|||
/// understand the package. The four steps are:
|
||||
///
|
||||
/// 1. [open] opens a local SQLite database ([Client.createSession])
|
||||
/// and wraps it in a [CrdtDatabaseSession]. The rest of the app
|
||||
/// reads and writes generated models through [session].
|
||||
/// and wraps it in a [CrdtDatabaseSession]. Use
|
||||
/// [openOrReset] when the file may predate the shipped
|
||||
/// schema. The rest of the app reads and writes generated models through
|
||||
/// [session].
|
||||
/// 2. CRUD happens against [session] with the generated model APIs (see
|
||||
/// the `seed*` methods in `DemoController` for the plain, recommended form,
|
||||
/// e.g. `Person.db.insertRow(crdtSession, person)`).
|
||||
|
|
@ -63,6 +68,41 @@ class OfflineReplica {
|
|||
return OfflineReplica._(rawSession, crdtSession, persistentUserId);
|
||||
}
|
||||
|
||||
/// Like [open], but deletes [databasePath] and retries once when opening
|
||||
/// fails — for example when migrations were regenerated during development
|
||||
/// and a leftover file records a version this build no longer ships.
|
||||
///
|
||||
/// A replica is a disposable local cache; syncing re-pulls server state.
|
||||
static Future<OfflineReplica> openOrReset({
|
||||
required Client client,
|
||||
required String databasePath,
|
||||
required UuidValue persistentUserId,
|
||||
}) async {
|
||||
var retry = true;
|
||||
while (true) {
|
||||
try {
|
||||
return await open(
|
||||
client: client,
|
||||
databasePath: databasePath,
|
||||
persistentUserId: persistentUserId,
|
||||
);
|
||||
} catch (_) {
|
||||
if (!retry) rethrow;
|
||||
retry = false;
|
||||
for (final suffix in const ['', '-wal', '-shm']) {
|
||||
final file = File('$databasePath$suffix');
|
||||
if (file.existsSync()) file.deleteSync();
|
||||
}
|
||||
if (kDebugMode) {
|
||||
debugPrint(
|
||||
'offline_sync_demo: discarded stale replica '
|
||||
'${p.basename(databasePath)}.',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pushes local pending changes through [client] and merges remote ones once.
|
||||
///
|
||||
/// Connectivity is expressed entirely by [client]: pass an online client to
|
||||
|
|
|
|||
|
|
@ -178,6 +178,10 @@ final Map<String, TableOps> demoTableOps = {
|
|||
create: (id, label, foreignKeys) =>
|
||||
UniqueComposite(id: id, scope: label, value: label),
|
||||
),
|
||||
_ops<UniqueDiscriminator>(
|
||||
create: (id, label, foreignKeys) =>
|
||||
UniqueDiscriminator(id: id, categoryId: 0, name: label),
|
||||
),
|
||||
_ops<UniqueSetNullChild>(
|
||||
create: (id, label, foreignKeys) => UniqueSetNullChild(
|
||||
id: id,
|
||||
|
|
|
|||
Loading…
Reference in a new issue