Fix database issues around device transfer.
This commit is contained in:
parent
d8edbce0a3
commit
a261fcda06
@ -124,6 +124,12 @@ public class GRDBDatabaseStorageAdapter: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: This should only be used in exceptional circumstances,
|
||||
// e.g. after reloading the database due to a device transfer.
|
||||
func forceUpdateSnapshot() {
|
||||
uiDatabaseObserver?.forceUpdateSnapshot()
|
||||
}
|
||||
|
||||
func testing_tearDownUIDatabase() {
|
||||
// UIDatabaseObserver is a general purpose observer, whose delegates
|
||||
// are notified when things change, but are not given any specific details
|
||||
|
||||
@ -15,10 +15,13 @@ public class GRDBSchemaMigrator: NSObject {
|
||||
@objc
|
||||
public func runSchemaMigrations() {
|
||||
if hasCreatedInitialSchema {
|
||||
Logger.info("Using incrementalMigrator.")
|
||||
try! incrementalMigrator.migrate(grdbStorage.pool)
|
||||
} else {
|
||||
Logger.info("Using newUserMigrator.")
|
||||
try! newUserMigrator.migrate(grdbStorage.pool)
|
||||
}
|
||||
Logger.info("Migrations complete.")
|
||||
|
||||
SSKPreferences.markGRDBSchemaAsLatest()
|
||||
}
|
||||
@ -32,6 +35,7 @@ public class GRDBSchemaMigrator: NSObject {
|
||||
}
|
||||
|
||||
let appliedMigrations = try! incrementalMigrator.appliedMigrations(in: grdbStorage.pool)
|
||||
Logger.info("appliedMigrations: \(appliedMigrations).")
|
||||
return appliedMigrations.contains(MigrationId.createInitialSchema.rawValue)
|
||||
}
|
||||
|
||||
@ -132,20 +136,31 @@ public class GRDBSchemaMigrator: NSObject {
|
||||
return migrator
|
||||
}()
|
||||
|
||||
class DatabaseMigratorWrapper {
|
||||
var migrator = DatabaseMigrator()
|
||||
|
||||
func registerMigration(_ identifier: String, migrate: @escaping (Database) throws -> Void) {
|
||||
migrator.registerMigration(identifier) { (database: Database) throws in
|
||||
Logger.info("Running migration: \(identifier)")
|
||||
try migrate(database)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used by existing users to incrementally update from their existing schema
|
||||
// to the latest.
|
||||
private lazy var incrementalMigrator: DatabaseMigrator = {
|
||||
var migrator = DatabaseMigrator()
|
||||
var migratorWrapper = DatabaseMigratorWrapper()
|
||||
|
||||
registerSchemaMigrations(migrator: &migrator)
|
||||
registerSchemaMigrations(migrator: migratorWrapper)
|
||||
|
||||
// Data Migrations must run *after* schema migrations
|
||||
registerDataMigrations(migrator: &migrator)
|
||||
registerDataMigrations(migrator: migratorWrapper)
|
||||
|
||||
return migrator
|
||||
return migratorWrapper.migrator
|
||||
}()
|
||||
|
||||
private func registerSchemaMigrations(migrator: inout DatabaseMigrator) {
|
||||
private func registerSchemaMigrations(migrator: DatabaseMigratorWrapper) {
|
||||
|
||||
// The migration blocks should never throw. If we introduce a crashing
|
||||
// migration, we want the crash logs reflect where it occurred.
|
||||
@ -703,7 +718,7 @@ public class GRDBSchemaMigrator: NSObject {
|
||||
// MARK: - Schema Migration Insertion Point
|
||||
}
|
||||
|
||||
func registerDataMigrations(migrator: inout DatabaseMigrator) {
|
||||
func registerDataMigrations(migrator: DatabaseMigratorWrapper) {
|
||||
|
||||
// The migration blocks should never throw. If we introduce a crashing
|
||||
// migration, we want the crash logs reflect where it occurred.
|
||||
|
||||
@ -132,11 +132,15 @@ public class SDSDatabaseStorage: SDSTransactable {
|
||||
AssertIsOnMainThread()
|
||||
assert(storageCoordinatorState == .GRDB)
|
||||
|
||||
Logger.info("")
|
||||
|
||||
let wasRegistered = TSAccountManager.sharedInstance().isRegistered
|
||||
|
||||
_grdbStorage = createGrdbStorage()
|
||||
let grdbStorage = createGrdbStorage()
|
||||
_grdbStorage = grdbStorage
|
||||
|
||||
GRDBSchemaMigrator().runSchemaMigrations()
|
||||
grdbStorage.forceUpdateSnapshot()
|
||||
|
||||
SSKEnvironment.shared.warmCaches()
|
||||
OWSIdentityManager.shared().recreateDatabaseQueue()
|
||||
|
||||
@ -595,6 +595,9 @@ extension ObservedDatabaseChanges: UIDatabaseChanges {
|
||||
owsFailDebug("should not have been notified for changes to FTS tables")
|
||||
continue
|
||||
}
|
||||
guard tableName != "grdb_migrations" else {
|
||||
continue
|
||||
}
|
||||
guard let collection = tableNameToCollectionMap[tableName] else {
|
||||
owsFailDebug("Unknown table: \(tableName)")
|
||||
continue
|
||||
|
||||
@ -361,7 +361,6 @@ extension UIDatabaseObserver: TransactionObserver {
|
||||
}
|
||||
|
||||
// Update the snapshot now.
|
||||
lastSnapshotUpdateDate = Date()
|
||||
updateSnapshot()
|
||||
}
|
||||
|
||||
@ -413,10 +412,22 @@ extension UIDatabaseObserver: TransactionObserver {
|
||||
return targetUpdateFrequencySeconds
|
||||
}
|
||||
|
||||
// See comment on databaseDidChange.
|
||||
private func updateSnapshot() {
|
||||
// NOTE: This should only be used in exceptional circumstances,
|
||||
// e.g. after reloading the database due to a device transfer.
|
||||
func forceUpdateSnapshot() {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
Logger.info("")
|
||||
|
||||
updateSnapshot(canCheckpoint: false)
|
||||
}
|
||||
|
||||
// See comment on databaseDidChange.
|
||||
private func updateSnapshot(canCheckpoint: Bool = true) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
lastSnapshotUpdateDate = Date()
|
||||
|
||||
Logger.verbose("databaseSnapshotWillUpdate")
|
||||
for delegate in snapshotDelegates {
|
||||
delegate.uiDatabaseSnapshotWillUpdate()
|
||||
@ -424,7 +435,7 @@ extension UIDatabaseObserver: TransactionObserver {
|
||||
|
||||
latestSnapshot.read { db in
|
||||
do {
|
||||
try self.fastForwardDatabaseSnapshot(db: db)
|
||||
try self.fastForwardDatabaseSnapshot(db: db, canCheckpoint: canCheckpoint)
|
||||
} catch {
|
||||
owsFailDebug("\(error)")
|
||||
}
|
||||
@ -469,14 +480,16 @@ extension UIDatabaseObserver: TransactionObserver {
|
||||
// Currently GRDB offers no built in way to fast-forward a
|
||||
// database snapshot.
|
||||
// See: https://github.com/groue/GRDB.swift/issues/619
|
||||
func fastForwardDatabaseSnapshot(db: Database) throws {
|
||||
func fastForwardDatabaseSnapshot(db: Database, canCheckpoint: Bool = true) throws {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
// [1] end the old transaction from the old db state
|
||||
try db.commit()
|
||||
|
||||
// [2] Checkpoint the WAL
|
||||
checkpointIfNecessary()
|
||||
if canCheckpoint {
|
||||
checkpointIfNecessary()
|
||||
}
|
||||
|
||||
// [3] open a new transaction from the current db state
|
||||
try db.beginTransaction(.deferred)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user