Don't start app version migrations until storage is ready.
This commit is contained in:
parent
2c1e633914
commit
2265ae08aa
|
@ -161,6 +161,11 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
||||||
}
|
}
|
||||||
notificationsProtocolBlock:^{
|
notificationsProtocolBlock:^{
|
||||||
return SignalApp.sharedApp.notificationsManager;
|
return SignalApp.sharedApp.notificationsManager;
|
||||||
|
}
|
||||||
|
migrationCompletion:^{
|
||||||
|
OWSAssertIsOnMainThread();
|
||||||
|
|
||||||
|
[self versionMigrationsDidComplete];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[UIUtil applySignalAppearence];
|
[UIUtil applySignalAppearence];
|
||||||
|
@ -176,14 +181,6 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
||||||
mainWindow.rootViewController = [self loadingRootViewController];
|
mainWindow.rootViewController = [self loadingRootViewController];
|
||||||
[mainWindow makeKeyAndVisible];
|
[mainWindow makeKeyAndVisible];
|
||||||
|
|
||||||
// performUpdateCheck must be invoked after Environment has been initialized because
|
|
||||||
// upgrade process may depend on Environment.
|
|
||||||
[VersionMigrations performUpdateCheckWithCompletion:^{
|
|
||||||
OWSAssertIsOnMainThread();
|
|
||||||
|
|
||||||
[self versionMigrationsDidComplete];
|
|
||||||
}];
|
|
||||||
|
|
||||||
// Accept push notification when app is not open
|
// Accept push notification when app is not open
|
||||||
NSDictionary *remoteNotif = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
|
NSDictionary *remoteNotif = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
|
||||||
if (remoteNotif) {
|
if (remoteNotif) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
@ -14,7 +14,8 @@ typedef id<NotificationsProtocol> _Nonnull (^NotificationsManagerBlock)(void);
|
||||||
@interface AppSetup : NSObject
|
@interface AppSetup : NSObject
|
||||||
|
|
||||||
+ (void)setupEnvironment:(CallMessageHandlerBlock)callMessageHandlerBlock
|
+ (void)setupEnvironment:(CallMessageHandlerBlock)callMessageHandlerBlock
|
||||||
notificationsProtocolBlock:(NotificationsManagerBlock)notificationsManagerBlock;
|
notificationsProtocolBlock:(NotificationsManagerBlock)notificationsManagerBlock
|
||||||
|
migrationCompletion:(dispatch_block_t)migrationCompletion;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,14 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
+ (void)setupEnvironment:(CallMessageHandlerBlock)callMessageHandlerBlock
|
+ (void)setupEnvironment:(CallMessageHandlerBlock)callMessageHandlerBlock
|
||||||
notificationsProtocolBlock:(NotificationsManagerBlock)notificationsManagerBlock
|
notificationsProtocolBlock:(NotificationsManagerBlock)notificationsManagerBlock
|
||||||
|
migrationCompletion:(dispatch_block_t)migrationCompletion
|
||||||
{
|
{
|
||||||
OWSAssert(callMessageHandlerBlock);
|
OWSAssert(callMessageHandlerBlock);
|
||||||
OWSAssert(notificationsManagerBlock);
|
OWSAssert(notificationsManagerBlock);
|
||||||
|
OWSAssert(migrationCompletion);
|
||||||
|
|
||||||
|
__block OWSBackgroundTask *_Nullable backgroundTask =
|
||||||
|
[OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
|
||||||
|
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
|
@ -46,7 +51,16 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
[NSKeyedUnarchiver setClass:[OWSUserProfile class] forClassName:[OWSUserProfile collection]];
|
[NSKeyedUnarchiver setClass:[OWSUserProfile class] forClassName:[OWSUserProfile collection]];
|
||||||
[NSKeyedUnarchiver setClass:[OWSDatabaseMigration class] forClassName:[OWSDatabaseMigration collection]];
|
[NSKeyedUnarchiver setClass:[OWSDatabaseMigration class] forClassName:[OWSDatabaseMigration collection]];
|
||||||
|
|
||||||
[OWSStorage setupStorage];
|
[OWSStorage setupStorageWithMigrationBlock:^() {
|
||||||
|
// Don't start database migrations until storage is ready.
|
||||||
|
[VersionMigrations performUpdateCheckWithCompletion:^() {
|
||||||
|
OWSAssertIsOnMainThread();
|
||||||
|
|
||||||
|
migrationCompletion();
|
||||||
|
|
||||||
|
backgroundTask = nil;
|
||||||
|
}];
|
||||||
|
}];
|
||||||
[[Environment current].contactsManager startObserving];
|
[[Environment current].contactsManager startObserving];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
+ (void)performUpdateCheckWithCompletion:(VersionMigrationCompletion)completion
|
+ (void)performUpdateCheckWithCompletion:(VersionMigrationCompletion)completion
|
||||||
{
|
{
|
||||||
|
DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// performUpdateCheck must be invoked after Environment has been initialized because
|
// performUpdateCheck must be invoked after Environment has been initialized because
|
||||||
// upgrade process may depend on Environment.
|
// upgrade process may depend on Environment.
|
||||||
OWSAssert([Environment current]);
|
OWSAssert([Environment current]);
|
||||||
|
|
|
@ -58,16 +58,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
OWSAssert(completion);
|
OWSAssert(completion);
|
||||||
|
|
||||||
OWSDatabaseConnection *dbConnection = (OWSDatabaseConnection *)self.primaryStorage.newDatabaseConnection;
|
OWSDatabaseConnection *dbConnection = (OWSDatabaseConnection *)self.primaryStorage.newDatabaseConnection;
|
||||||
// These migrations won't be run until storage registrations are enqueued,
|
|
||||||
// but this transaction might begin before all registrations are marked as
|
|
||||||
// complete, so disable this checking.
|
|
||||||
//
|
|
||||||
// TODO: Once we move "app readiness" into AppSetup, we should explicitly
|
|
||||||
// not start these migrations until storage is ready. We can then remove
|
|
||||||
// this statement which disables checking.
|
|
||||||
#ifdef DEBUG
|
|
||||||
dbConnection.canWriteBeforeStorageReady = YES;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||||
[self runUpWithTransaction:transaction];
|
[self runUpWithTransaction:transaction];
|
||||||
|
@ -88,18 +78,12 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
return self.dbReadWriteConnection;
|
return self.dbReadWriteConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database migrations need to occur _before_ storage is ready (by definition),
|
|
||||||
// so we need to use a connection with canWriteBeforeStorageReady set in
|
|
||||||
// debug builds.
|
|
||||||
+ (YapDatabaseConnection *)dbReadWriteConnection
|
+ (YapDatabaseConnection *)dbReadWriteConnection
|
||||||
{
|
{
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
static YapDatabaseConnection *sharedDBConnection;
|
static YapDatabaseConnection *sharedDBConnection;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
sharedDBConnection = [OWSPrimaryStorage sharedManager].newDatabaseConnection;
|
sharedDBConnection = [OWSPrimaryStorage sharedManager].newDatabaseConnection;
|
||||||
|
|
||||||
OWSAssert([sharedDBConnection isKindOfClass:[OWSDatabaseConnection class]]);
|
|
||||||
((OWSDatabaseConnection *)sharedDBConnection).canWriteBeforeStorageReady = YES;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return sharedDBConnection;
|
return sharedDBConnection;
|
||||||
|
|
|
@ -22,10 +22,6 @@ extern NSString *const StorageIsReadyNotification;
|
||||||
|
|
||||||
@property (atomic, weak) id<OWSDatabaseConnectionDelegate> delegate;
|
@property (atomic, weak) id<OWSDatabaseConnectionDelegate> delegate;
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
@property (atomic) BOOL canWriteBeforeStorageReady;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- (instancetype)init NS_UNAVAILABLE;
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
- (instancetype)initWithDatabase:(YapDatabase *)database
|
- (instancetype)initWithDatabase:(YapDatabase *)database
|
||||||
delegate:(id<OWSDatabaseConnectionDelegate>)delegate NS_DESIGNATED_INITIALIZER;
|
delegate:(id<OWSDatabaseConnectionDelegate>)delegate NS_DESIGNATED_INITIALIZER;
|
||||||
|
@ -48,6 +44,8 @@ extern NSString *const StorageIsReadyNotification;
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
|
typedef void (^OWSStorageMigrationBlock)(void);
|
||||||
|
|
||||||
@interface OWSStorage : NSObject
|
@interface OWSStorage : NSObject
|
||||||
|
|
||||||
- (instancetype)init NS_UNAVAILABLE;
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
@ -60,7 +58,7 @@ extern NSString *const StorageIsReadyNotification;
|
||||||
// This object can be used to filter database notifications.
|
// This object can be used to filter database notifications.
|
||||||
@property (nonatomic, readonly, nullable) id dbNotificationObject;
|
@property (nonatomic, readonly, nullable) id dbNotificationObject;
|
||||||
|
|
||||||
+ (void)setupStorage;
|
+ (void)setupStorageWithMigrationBlock:(OWSStorageMigrationBlock)migrationBlock;
|
||||||
|
|
||||||
+ (void)resetAllStorage;
|
+ (void)resetAllStorage;
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ typedef NSData *_Nullable (^CreateDatabaseMetadataBlock)(void);
|
||||||
{
|
{
|
||||||
id<OWSDatabaseConnectionDelegate> delegate = self.delegate;
|
id<OWSDatabaseConnectionDelegate> delegate = self.delegate;
|
||||||
OWSAssert(delegate);
|
OWSAssert(delegate);
|
||||||
OWSAssert(delegate.areAllRegistrationsComplete || self.canWriteBeforeStorageReady);
|
OWSAssert(delegate.areAllRegistrationsComplete);
|
||||||
|
|
||||||
OWSBackgroundTask *_Nullable backgroundTask = nil;
|
OWSBackgroundTask *_Nullable backgroundTask = nil;
|
||||||
if (CurrentAppContext().isMainApp) {
|
if (CurrentAppContext().isMainApp) {
|
||||||
|
@ -101,7 +101,7 @@ typedef NSData *_Nullable (^CreateDatabaseMetadataBlock)(void);
|
||||||
{
|
{
|
||||||
id<OWSDatabaseConnectionDelegate> delegate = self.delegate;
|
id<OWSDatabaseConnectionDelegate> delegate = self.delegate;
|
||||||
OWSAssert(delegate);
|
OWSAssert(delegate);
|
||||||
OWSAssert(delegate.areAllRegistrationsComplete || self.canWriteBeforeStorageReady);
|
OWSAssert(delegate.areAllRegistrationsComplete);
|
||||||
|
|
||||||
__block OWSBackgroundTask *_Nullable backgroundTask = nil;
|
__block OWSBackgroundTask *_Nullable backgroundTask = nil;
|
||||||
if (CurrentAppContext().isMainApp) {
|
if (CurrentAppContext().isMainApp) {
|
||||||
|
@ -176,13 +176,6 @@ typedef NSData *_Nullable (^CreateDatabaseMetadataBlock)(void);
|
||||||
- (YapDatabaseConnection *)registrationConnection
|
- (YapDatabaseConnection *)registrationConnection
|
||||||
{
|
{
|
||||||
YapDatabaseConnection *connection = [super registrationConnection];
|
YapDatabaseConnection *connection = [super registrationConnection];
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Flag the registration connection as such.
|
|
||||||
OWSAssert([connection isKindOfClass:[OWSDatabaseConnection class]]);
|
|
||||||
((OWSDatabaseConnection *)connection).canWriteBeforeStorageReady = YES;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,29 +325,24 @@ typedef NSData *_Nullable (^CreateDatabaseMetadataBlock)(void);
|
||||||
OWS_ABSTRACT_METHOD();
|
OWS_ABSTRACT_METHOD();
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSArray<OWSStorage *> *)allStorages
|
+ (void)setupStorageWithMigrationBlock:(OWSStorageMigrationBlock)migrationBlock
|
||||||
{
|
{
|
||||||
return @[
|
OWSAssert(migrationBlock);
|
||||||
OWSPrimaryStorage.sharedManager,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void)setupStorage
|
|
||||||
{
|
|
||||||
__block OWSBackgroundTask *_Nullable backgroundTask =
|
__block OWSBackgroundTask *_Nullable backgroundTask =
|
||||||
[OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
|
[OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
|
||||||
|
|
||||||
for (OWSStorage *storage in self.allStorages) {
|
[OWSPrimaryStorage.sharedManager runSyncRegistrations];
|
||||||
[storage runSyncRegistrations];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (OWSStorage *storage in self.allStorages) {
|
[OWSPrimaryStorage.sharedManager runAsyncRegistrationsWithCompletion:^{
|
||||||
[storage runAsyncRegistrationsWithCompletion:^{
|
OWSAssert(self.isStorageReady);
|
||||||
if ([self postRegistrationCompleteNotificationIfPossible]) {
|
|
||||||
backgroundTask = nil;
|
[self postRegistrationCompleteNotification];
|
||||||
}
|
|
||||||
}];
|
migrationBlock();
|
||||||
}
|
|
||||||
|
backgroundTask = nil;
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (YapDatabaseConnection *)registrationConnection
|
- (YapDatabaseConnection *)registrationConnection
|
||||||
|
@ -363,11 +351,11 @@ typedef NSData *_Nullable (^CreateDatabaseMetadataBlock)(void);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns YES IFF all registrations are complete.
|
// Returns YES IFF all registrations are complete.
|
||||||
+ (BOOL)postRegistrationCompleteNotificationIfPossible
|
+ (void)postRegistrationCompleteNotification
|
||||||
{
|
{
|
||||||
if (!self.isStorageReady) {
|
OWSAssert(self.isStorageReady);
|
||||||
return NO;
|
|
||||||
}
|
DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
|
@ -375,18 +363,11 @@ typedef NSData *_Nullable (^CreateDatabaseMetadataBlock)(void);
|
||||||
object:nil
|
object:nil
|
||||||
userInfo:nil];
|
userInfo:nil];
|
||||||
});
|
});
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (BOOL)isStorageReady
|
+ (BOOL)isStorageReady
|
||||||
{
|
{
|
||||||
for (OWSStorage *storage in self.allStorages) {
|
return OWSPrimaryStorage.sharedManager.areAllRegistrationsComplete;
|
||||||
if (!storage.areAllRegistrationsComplete) {
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)tryToLoadDatabase
|
- (BOOL)tryToLoadDatabase
|
||||||
|
|
|
@ -90,18 +90,18 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
|
||||||
// We shouldn't set up our environment until after we've consulted isReadyForAppExtensions.
|
// We shouldn't set up our environment until after we've consulted isReadyForAppExtensions.
|
||||||
AppSetup.setupEnvironment({
|
AppSetup.setupEnvironment({
|
||||||
return NoopCallMessageHandler()
|
return NoopCallMessageHandler()
|
||||||
}) {
|
},
|
||||||
|
notificationsProtocolBlock: {
|
||||||
return NoopNotificationsManager()
|
return NoopNotificationsManager()
|
||||||
}
|
},
|
||||||
|
migrationCompletion: { [weak self] in
|
||||||
|
SwiftAssertIsOnMainThread(#function)
|
||||||
|
|
||||||
// performUpdateCheck must be invoked after Environment has been initialized because
|
guard let strongSelf = self else { return }
|
||||||
// upgrade process may depend on Environment.
|
|
||||||
VersionMigrations.performUpdateCheck(completion: { [weak self] in
|
|
||||||
SwiftAssertIsOnMainThread(#function)
|
|
||||||
|
|
||||||
guard let strongSelf = self else { return }
|
// performUpdateCheck must be invoked after Environment has been initialized because
|
||||||
|
// upgrade process may depend on Environment.
|
||||||
strongSelf.versionMigrationsDidComplete()
|
strongSelf.versionMigrationsDidComplete()
|
||||||
})
|
})
|
||||||
|
|
||||||
// We don't need to use "screen protection" in the SAE.
|
// We don't need to use "screen protection" in the SAE.
|
||||||
|
|
Loading…
Reference in New Issue