@ -47,8 +47,10 @@ open class Storage {
fileprivate var dbWriter : DatabaseWriter ?
internal var testDbWriter : DatabaseWriter ? { dbWriter }
private var unprocessedMigrationRequirements : Atomic < [ MigrationRequirement ] > = Atomic ( MigrationRequirement . allCases )
private var migrator : DatabaseMigrator ?
private var migrationProgressUpdater : Atomic < ( ( String , CGFloat ) -> ( ) ) >?
private var migrationRequirementProcesser : Atomic < ( Database ? , MigrationRequirement ) -> ( ) >?
// MARK: - I n i t i a l i z a t i o n
@ -77,6 +79,7 @@ open class Storage {
migrationTargets : ( customMigrationTargets ? ? [ ] ) ,
async : false ,
onProgressUpdate : nil ,
onMigrationRequirement : { _ , _ in } ,
onComplete : { _ , _ in }
)
return
@ -148,6 +151,7 @@ open class Storage {
migrationTargets : [ MigratableTarget . Type ] ,
async : Bool = true ,
onProgressUpdate : ( ( CGFloat , TimeInterval ) -> ( ) ) ? ,
onMigrationRequirement : @ escaping ( Database ? , MigrationRequirement ) -> ( ) ,
onComplete : @ escaping ( Swift . Result < Void , Error > , Bool ) -> ( )
) {
guard isValid , let dbWriter : DatabaseWriter = dbWriter else {
@ -232,13 +236,24 @@ open class Storage {
onProgressUpdate ? ( totalProgress , totalMinExpectedDuration )
}
} )
self . migrationRequirementProcesser = Atomic ( onMigrationRequirement )
// S t o r e t h e l o g i c t o r u n w h e n t h e m i g r a t i o n c o m p l e t e s
let migrationCompleted : ( Swift . Result < Void , Error > ) -> ( ) = { [ weak self ] result in
// P r o c e s s a n y u n p r o c e s s e d r e q u i r e m e n t s w h i c h n e e d t o b e p r o c e s s e d b e f o r e c o m p l e t i o n
// t h e n c l e a r o u t t h e s t a t e
self ? . unprocessedMigrationRequirements . wrappedValue
. filter { $0 . shouldProcessAtCompletionIfNotRequired }
. forEach { self ? . migrationRequirementProcesser ? . wrappedValue ( nil , $0 ) }
self ? . migrationsCompleted . mutate { $0 = true }
self ? . migrationProgressUpdater = nil
self ? . migrationRequirementProcesser = nil
SUKLegacy . clearLegacyDatabaseInstance ( )
// R e s e t i n c a s e t h e r e i s a r e q u i r e m e n t o n a m i g r a t i o n w h i c h r u n s w h e n r e t u r n i n g f r o m
// t h e b a c k g r o u n d
self ? . unprocessedMigrationRequirements . mutate { $0 = MigrationRequirement . allCases }
// D o n ' t l o g a n y t h i n g i n t h e c a s e o f a ' s u c c e s s ' o r i f t h e d a t a b a s e i s s u s p e n d e d ( t h e
// l a t t e r w i l l h a p p e n i f t h e u s e r h a p p e n s t o r e t u r n t o t h e b a c k g r o u n d t o o q u i c k l y o n
// l a u n c h s o i s u n n e c e s s a r i l y a l a r m i n g , i t a l s o g e t s c a u g h t a n d l o g g e d s e p a r a t e l y b y
@ -288,6 +303,22 @@ open class Storage {
}
}
public func willStartMigration ( _ db : Database , _ migration : Migration . Type ) {
let unprocessedRequirements : Set < MigrationRequirement > = migration . requirements . asSet ( )
. intersection ( unprocessedMigrationRequirements . wrappedValue . asSet ( ) )
// N o n e e d t o d o a n y t h i n g i f t h e r e a r e n o u n p r o c e s s e d r e q u i r e m e n t s
guard ! unprocessedRequirements . isEmpty else { return }
// P r o c e s s a l l o f t h e r e q u i r e m e n t s f o r t h i s m i g r a t i o n
unprocessedRequirements . forEach { migrationRequirementProcesser ? . wrappedValue ( db , $0 ) }
// R e m o v e a n y p r o c e s s e d r e q u i r e m e n t s f r o m t h e l i s t ( d o n ' t w a n t t o p r o c e s s t h e m m u l t i p l e t i m e s )
unprocessedMigrationRequirements . mutate {
$0 = Array ( $0 . asSet ( ) . subtracting ( migration . requirements . asSet ( ) ) )
}
}
public static func update (
progress : CGFloat ,
for migration : Migration . Type ,