@ -329,9 +329,10 @@ open class Storage {
}
} ( )
// N o t e : W e n e e d t o d i s p a t c h t h i s t o t h e n e x t r u n t o o p t o p r e v e n t a n y p o t e n t i a l r e - e n t r a n c y
// i s s u e s s i n c e t h e ' a s y n c M i g r a t e ' r e t u r n s a r e s u l t c o n t a i n i n g a D B i n s t a n c e
DispatchQueue . global ( qos : . userInitiated ) . async {
// N o t e : W e n e e d t o d i s p a t c h t h i s a f t e r a s m a l l 0 . 0 1 d e l a y t o p r e v e n t a n y p o t e n t i a l
// r e - e n t r a n c y i s s u e s s i n c e t h e ' a s y n c M i g r a t e ' r e t u r n s a r e s u l t c o n t a i n i n g a D B i n s t a n c e
// w i t h i n a t r a n s a c t i o n
DispatchQueue . global ( qos : . userInitiated ) . asyncAfter ( deadline : . now ( ) + 0.01 , using : dependencies ) {
migrationCompleted ( finalResult )
}
}
@ -524,8 +525,8 @@ open class Storage {
case valid ( DatabaseWriter )
case invalid ( Error )
init ( _ storage : Storage ) {
switch ( storage .isSuspended , storage .isValid , storage . dbWriter ) {
init ( _ storage : Storage ? ) {
switch ( storage ? .isSuspended , storage ? .isValid , storage ? . dbWriter ) {
case ( true , _ , _ ) : self = . invalid ( StorageError . databaseSuspended )
case ( false , true , . some ( let dbWriter ) ) : self = . valid ( dbWriter )
default : self = . invalid ( StorageError . databaseInvalid )
@ -632,7 +633,7 @@ open class Storage {
) -> AnyPublisher < T , Error > {
switch StorageState ( self ) {
case . invalid ( let error ) : return StorageState . logIfNeeded ( error , isWrite : true )
case . valid (let dbWriter ) :
case . valid :
// / * * N o t e : * * G R D B d o e s h a v e a ` w r i t e P u b l i s h e r ` m e t h o d b u t i t a p p e a r s t o a s y n c h r o n o u s l y t r i g g e r
// / b o t h t h e ` o u t p u t ` a n d ` c o m p l e t e ` c l o s u r e s a t t h e s a m e t i m e w h i c h c a u s e s a l o t o f u n e x p e c t e d
// / b e h a v i o u r s ( t h i s b e h a v i o u r i s a p p a r e n t l y e x p e c t e d b u t s t i l l c a u s e s a n u m b e r o f o d d b e h a v i o u r s i n o u r c o d e
@ -642,11 +643,19 @@ open class Storage {
// / w h i c h b e h a v e s i n a m u c h m o r e e x p e c t e d w a y t h a n t h e G R D B ` w r i t e P u b l i s h e r ` d o e s
let info : CallInfo = CallInfo ( fileName , functionName , lineNumber , true , self )
return Deferred {
Future { resolver in
do { resolver ( Result . success ( try dbWriter . write ( Storage . perform ( info : info , updates : updates ) ) ) ) }
catch {
StorageState . logIfNeeded ( error , isWrite : true )
resolver ( Result . failure ( error ) )
Future { [ weak self ] resolver in
// / T h e ` S t o r a g e S t a t e ` m a y h a v e c h a n g e d b e t w e e n t h e c r e a t i o n o f t h e p u b l i s h e r a n d i t a c t u a l l y
// / b e i n g e x e c u t e d s o w e n e e d t o c h e c k a g a i n
switch StorageState ( self ) {
case . invalid ( let error ) : return StorageState . logIfNeeded ( error , isWrite : true )
case . valid ( let dbWriter ) :
do {
resolver ( Result . success ( try dbWriter . write ( Storage . perform ( info : info , updates : updates ) ) ) )
}
catch {
StorageState . logIfNeeded ( error , isWrite : true )
resolver ( Result . failure ( error ) )
}
}
}
} . eraseToAnyPublisher ( )
@ -678,7 +687,7 @@ open class Storage {
) -> AnyPublisher < T , Error > {
switch StorageState ( self ) {
case . invalid ( let error ) : return StorageState . logIfNeeded ( error , isWrite : false )
case . valid (let dbWriter ) :
case . valid :
// / * * N o t e : * * G R D B d o e s h a v e a ` r e a d P u b l i s h e r ` m e t h o d b u t i t a p p e a r s t o a s y n c h r o n o u s l y t r i g g e r
// / b o t h t h e ` o u t p u t ` a n d ` c o m p l e t e ` c l o s u r e s a t t h e s a m e t i m e w h i c h c a u s e s a l o t o f u n e x p e c t e d
// / b e h a v i o u r s ( t h i s b e h a v i o u r i s a p p a r e n t l y e x p e c t e d b u t s t i l l c a u s e s a n u m b e r o f o d d b e h a v i o u r s i n o u r c o d e
@ -688,11 +697,19 @@ open class Storage {
// / w h i c h b e h a v e s i n a m u c h m o r e e x p e c t e d w a y t h a n t h e G R D B ` r e a d P u b l i s h e r ` d o e s
let info : CallInfo = CallInfo ( fileName , functionName , lineNumber , false , self )
return Deferred {
Future { resolver in
do { resolver ( Result . success ( try dbWriter . read ( Storage . perform ( info : info , updates : value ) ) ) ) }
catch {
StorageState . logIfNeeded ( error , isWrite : false )
resolver ( Result . failure ( error ) )
Future { [ weak self ] resolver in
// / T h e ` S t o r a g e S t a t e ` m a y h a v e c h a n g e d b e t w e e n t h e c r e a t i o n o f t h e p u b l i s h e r a n d i t a c t u a l l y
// / b e i n g e x e c u t e d s o w e n e e d t o c h e c k a g a i n
switch StorageState ( self ) {
case . invalid ( let error ) : return StorageState . logIfNeeded ( error , isWrite : false )
case . valid ( let dbWriter ) :
do {
resolver ( Result . success ( try dbWriter . read ( Storage . perform ( info : info , updates : value ) ) ) )
}
catch {
StorageState . logIfNeeded ( error , isWrite : false )
resolver ( Result . failure ( error ) )
}
}
}
} . eraseToAnyPublisher ( )