Update background polling for SSKs

This commit is contained in:
nielsandriesse 2020-09-15 11:30:45 +10:00
parent f11f289f9d
commit a8b53f6cf3
6 changed files with 51 additions and 38 deletions

View file

@ -586,6 +586,7 @@
C39DD28A24F3336E008590FC /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C39DD28724F3318C008590FC /* Colors.xcassets */; };
C39DD28B24F3336F008590FC /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C39DD28724F3318C008590FC /* Colors.xcassets */; };
C3C3CF8924D8EED300E1CCE7 /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C3CF8824D8EED300E1CCE7 /* TextView.swift */; };
C3D0972B2510499C00F6E3E4 /* BackgroundPoller.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3D0972A2510499C00F6E3E4 /* BackgroundPoller.swift */; };
C3DAB3242480CB2B00725F25 /* SRCopyableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */; };
C3DFFAC623E96F0D0058DAF8 /* Sheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */; };
C3DFFAC823E970080058DAF8 /* OpenGroupSuggestionSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DFFAC723E970080058DAF8 /* OpenGroupSuggestionSheet.swift */; };
@ -1376,6 +1377,7 @@
C3AA6BB824CE8F1B002358B6 /* Migrating Translations from Android.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "Migrating Translations from Android.md"; sourceTree = "<group>"; };
C3AECBEA24EF5244005743DE /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = translations/fa.lproj/Localizable.strings; sourceTree = "<group>"; };
C3C3CF8824D8EED300E1CCE7 /* TextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextView.swift; sourceTree = "<group>"; };
C3D0972A2510499C00F6E3E4 /* BackgroundPoller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundPoller.swift; sourceTree = "<group>"; };
C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRCopyableLabel.swift; sourceTree = "<group>"; };
C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sheet.swift; sourceTree = "<group>"; };
C3DFFAC723E970080058DAF8 /* OpenGroupSuggestionSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupSuggestionSheet.swift; sourceTree = "<group>"; };
@ -2672,6 +2674,7 @@
isa = PBXGroup;
children = (
B8544E3223D50E4900299F14 /* AppearanceUtilities.swift */,
C3D0972A2510499C00F6E3E4 /* BackgroundPoller.swift */,
C31A6C5B247F2CF3001123EF /* CGRect+Utilities.swift */,
C35E8AAD2485E51D00ACB629 /* IP2Country.swift */,
B84664F4235022F30083A1CD /* MentionUtilities.swift */,
@ -3802,6 +3805,7 @@
3496955E219B605E00DCFE74 /* PhotoLibrary.swift in Sources */,
45D231771DC7E8F10034FA89 /* SessionResetJob.swift in Sources */,
340FC8A9204DAC8D007AEB0F /* NotificationSettingsOptionsViewController.m in Sources */,
C3D0972B2510499C00F6E3E4 /* BackgroundPoller.swift in Sources */,
C3548F0624456447009433A8 /* PNModeVC.swift in Sources */,
B80A579F23DFF1F300876683 /* NewClosedGroupVC.swift in Sources */,
452037D11EE84975004E4CDF /* DebugUISessionState.m in Sources */,

View file

@ -357,36 +357,8 @@ static NSTimeInterval launchStartedAt;
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
NSLog(@"[Loki] Performing background fetch.");
[AppReadiness runNowOrWhenAppDidBecomeReady:^{
NSMutableArray *promises = [NSMutableArray new];
__block AnyPromise *fetchMessagesPromise = [AppEnvironment.shared.messageFetcherJob run].then(^{
fetchMessagesPromise = nil;
}).catch(^{
fetchMessagesPromise = nil;
});
[promises addObject:fetchMessagesPromise];
[fetchMessagesPromise retainUntilComplete];
__block NSDictionary<NSString *, LKPublicChat *> *publicChats;
[OWSPrimaryStorage.sharedManager.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
publicChats = [LKDatabaseUtilities getAllPublicChats:transaction];
}];
for (LKPublicChat *publicChat in publicChats) {
if (![publicChat isKindOfClass:LKPublicChat.class]) { continue; }
LKPublicChatPoller *poller = [[LKPublicChatPoller alloc] initForPublicChat:publicChat];
[poller stop];
AnyPromise *fetchGroupMessagesPromise = [poller pollForNewMessages];
[promises addObject:fetchGroupMessagesPromise];
[fetchGroupMessagesPromise retainUntilComplete];
}
PMKJoin(promises).then(^(id results) {
completionHandler(UIBackgroundFetchResultNewData);
}).catch(^(id error) {
completionHandler(UIBackgroundFetchResultFailed);
});
[LKBackgroundPoller pollWithCompletionHandler:completionHandler];
}];
}

View file

@ -0,0 +1,28 @@
import PromiseKit
@objc(LKBackgroundPoller)
public final class BackgroundPoller : NSObject {
private override init() { }
@objc(pollWithCompletionHandler:)
public static func poll(completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
var promises: [Promise<Void>] = []
promises.append(AppEnvironment.shared.messageFetcherJob.run()) // FIXME: It'd be nicer to just use Poller directly
promises.append(contentsOf: ClosedGroupPoller().pollOnce())
var openGroups: [String:PublicChat] = [:]
Storage.read { transaction in
openGroups = LokiDatabaseUtilities.getAllPublicChats(in: transaction)
}
openGroups.values.forEach { openGroup in
let poller = PublicChatPoller(for: openGroup)
poller.stop()
promises.append(poller.pollForNewMessages())
}
when(resolved: promises).done { _ in
completionHandler(.newData)
}.catch { _ in
completionHandler(.failed)
}
}
}

View file

@ -245,7 +245,7 @@ public final class SnodeAPI : NSObject {
guard let json = rawResponse as? JSON, let rawMessages = json["messages"] as? [JSON] else { return [] }
if let (lastHash, expirationDate) = updateLastMessageHashValueIfPossible(for: snode, associatedWith: publicKey, from: rawMessages),
UserDefaults.standard[.isUsingFullAPNs] {
LokiPushNotificationManager.acknowledgeDelivery(forMessageWithHash: lastHash, expiration: expirationDate, hexEncodedPublicKey: getUserHexEncodedPublicKey())
LokiPushNotificationManager.acknowledgeDelivery(forMessageWithHash: lastHash, expiration: expirationDate, publicKey: getUserHexEncodedPublicKey())
}
let rawNewMessages = removeDuplicates(from: rawMessages, associatedWith: publicKey)
let newMessages = parseProtoEnvelopes(from: rawNewMessages)

View file

@ -31,24 +31,31 @@ public final class ClosedGroupPoller : NSObject {
}
}
public func pollOnce() -> [Promise<Void>] {
guard !isPolling else { return [] }
isPolling = true
return poll()
}
@objc public func stop() {
isPolling = false
timer?.invalidate()
}
// MARK: Private API
private func poll() {
guard isPolling else { return }
private func poll() -> [Promise<Void>] {
guard isPolling else { return [] }
let publicKeys = Storage.getUserClosedGroupPublicKeys()
publicKeys.forEach { publicKey in
SnodeAPI.getSwarm(for: publicKey).then2 { [weak self] swarm -> Promise<[SSKProtoEnvelope]> in
return publicKeys.map { publicKey in
let promise = SnodeAPI.getSwarm(for: publicKey).then2 { [weak self] swarm -> Promise<[SSKProtoEnvelope]> in
// randomElement() uses the system's default random generator, which is cryptographically secure
guard let snode = swarm.randomElement() else { return Promise(error: Error.insufficientSnodes) }
guard let self = self, self.isPolling else { return Promise(error: Error.pollingCanceled) }
return SnodeAPI.getRawMessages(from: snode, associatedWith: publicKey).map2 {
SnodeAPI.parseRawMessagesResponse($0, from: snode, associatedWith: publicKey)
}
}.done2 { [weak self] messages in
}
promise.done2 { [weak self] messages in
guard let self = self, self.isPolling else { return }
if !messages.isEmpty {
print("[Loki] Received \(messages.count) new message(s) in closed group with public key: \(publicKey).")
@ -61,9 +68,11 @@ public final class ClosedGroupPoller : NSObject {
print("[Loki] Failed to deserialize envelope due to error: \(error).")
}
}
}.catch2 { error in
}
promise.catch2 { error in
print("[Loki] Polling failed for closed group with public key: \(publicKey) due to error: \(error).")
}
return promise.map { _ in }
}
}
}

View file

@ -1,8 +1,8 @@
import PromiseKit
internal extension AnyPromise {
public extension AnyPromise {
internal static func from<T : Any>(_ promise: Promise<T>) -> AnyPromise {
public static func from<T : Any>(_ promise: Promise<T>) -> AnyPromise {
let result = AnyPromise(promise)
result.retainUntilComplete()
return result