Ditch long polling
This commit is contained in:
parent
7d507ba3ad
commit
5ad32af0d3
|
@ -8,8 +8,8 @@ extern NSString *const AppDelegateStoryboardMain;
|
|||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
- (void)startLongPollerIfNeeded;
|
||||
- (void)stopLongPollerIfNeeded;
|
||||
- (void)startPollerIfNeeded;
|
||||
- (void)stopPollerIfNeeded;
|
||||
- (void)setUpDefaultPublicChatsIfNeeded;
|
||||
- (void)startOpenGroupPollersIfNeeded;
|
||||
- (void)stopOpenGroupPollersIfNeeded;
|
||||
|
|
|
@ -69,7 +69,7 @@ static BOOL isInternalTestVersion = NO;
|
|||
|
||||
// Loki
|
||||
@property (nonatomic) LKP2PServer *lokiP2PServer;
|
||||
@property (nonatomic) LKLongPoller *lokiLongPoller;
|
||||
@property (nonatomic) LKPoller *lokiPoller;
|
||||
@property (nonatomic) LKRSSFeedPoller *lokiNewsFeedPoller;
|
||||
@property (nonatomic) LKRSSFeedPoller *lokiMessengerUpdatesFeedPoller;
|
||||
|
||||
|
@ -181,7 +181,7 @@ static BOOL isInternalTestVersion = NO;
|
|||
[DDLog flushLog];
|
||||
|
||||
// Loki: Stop pollers
|
||||
[self stopLongPollerIfNeeded];
|
||||
[self stopPollerIfNeeded];
|
||||
[self stopOpenGroupPollersIfNeeded];
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ static BOOL isInternalTestVersion = NO;
|
|||
[DDLog flushLog];
|
||||
|
||||
// Loki: Stop pollers
|
||||
[self stopLongPollerIfNeeded];
|
||||
[self stopPollerIfNeeded];
|
||||
[self stopOpenGroupPollersIfNeeded];
|
||||
|
||||
if (self.lokiP2PServer) { [self.lokiP2PServer stop]; }
|
||||
|
@ -784,7 +784,7 @@ static BOOL isInternalTestVersion = NO;
|
|||
[LKP2PAPI broadcastOnlineStatus];
|
||||
|
||||
// Loki: Start pollers
|
||||
[self startLongPollerIfNeeded];
|
||||
[self startPollerIfNeeded];
|
||||
[self startOpenGroupPollersIfNeeded];
|
||||
|
||||
// Loki: Get device links
|
||||
|
@ -1477,7 +1477,7 @@ static BOOL isInternalTestVersion = NO;
|
|||
[self.lokiFriendRequestExpirationJob startIfNecessary];
|
||||
|
||||
// Loki: Start pollers
|
||||
[self startLongPollerIfNeeded];
|
||||
[self startPollerIfNeeded];
|
||||
[self startOpenGroupPollersIfNeeded];
|
||||
|
||||
// Loki: Get device links
|
||||
|
@ -1591,12 +1591,12 @@ static BOOL isInternalTestVersion = NO;
|
|||
|
||||
#pragma mark - Loki
|
||||
|
||||
- (void)setUpLongPollerIfNeeded
|
||||
- (void)setUpPollerIfNeeded
|
||||
{
|
||||
if (self.lokiLongPoller != nil) { return; }
|
||||
if (self.lokiPoller != nil) { return; }
|
||||
NSString *userHexEncodedPublicKey = OWSIdentityManager.sharedManager.identityKeyPair.hexEncodedPublicKey;
|
||||
if (userHexEncodedPublicKey == nil) { return; }
|
||||
self.lokiLongPoller = [[LKLongPoller alloc] initOnMessagesReceived:^(NSArray<SSKProtoEnvelope *> *messages) {
|
||||
self.lokiPoller = [[LKPoller alloc] initOnMessagesReceived:^(NSArray<SSKProtoEnvelope *> *messages) {
|
||||
for (SSKProtoEnvelope *message in messages) {
|
||||
NSData *data = [message serializedDataAndReturnError:nil];
|
||||
if (data != nil) {
|
||||
|
@ -1608,15 +1608,15 @@ static BOOL isInternalTestVersion = NO;
|
|||
}];
|
||||
}
|
||||
|
||||
- (void)startLongPollerIfNeeded
|
||||
- (void)startPollerIfNeeded
|
||||
{
|
||||
[self setUpLongPollerIfNeeded];
|
||||
[self.lokiLongPoller startIfNeeded];
|
||||
[self setUpPollerIfNeeded];
|
||||
[self.lokiPoller startIfNeeded];
|
||||
}
|
||||
|
||||
- (void)stopLongPollerIfNeeded
|
||||
- (void)stopPollerIfNeeded
|
||||
{
|
||||
[self.lokiLongPoller stopIfNeeded];
|
||||
[self.lokiPoller stopIfNeeded];
|
||||
}
|
||||
|
||||
- (void)setUpDefaultPublicChatsIfNeeded
|
||||
|
@ -1713,7 +1713,7 @@ static BOOL isInternalTestVersion = NO;
|
|||
[SSKEnvironment.shared.messageSenderJobQueue clearAllJobs];
|
||||
[SSKEnvironment.shared.identityManager clearIdentityKey];
|
||||
[LKAPI clearRandomSnodePool];
|
||||
[self stopLongPollerIfNeeded];
|
||||
[self stopPollerIfNeeded];
|
||||
[self stopOpenGroupPollersIfNeeded];
|
||||
[self.lokiNewsFeedPoller stop];
|
||||
[self.lokiMessengerUpdatesFeedPoller stop];
|
||||
|
|
|
@ -155,7 +155,7 @@ final class LandingVC : BaseVC, LinkDeviceVCDelegate, DeviceLinkingModalDelegate
|
|||
TSAccountManager.sharedInstance().phoneNumberAwaitingVerification = keyPair.hexEncodedPublicKey
|
||||
TSAccountManager.sharedInstance().didRegister()
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.startLongPollerIfNeeded()
|
||||
appDelegate.startPollerIfNeeded()
|
||||
let deviceLinkingModal = DeviceLinkingModal(mode: .slave, delegate: self)
|
||||
deviceLinkingModal.modalPresentationStyle = .overFullScreen
|
||||
deviceLinkingModal.modalTransitionStyle = .crossDissolve
|
||||
|
@ -176,7 +176,7 @@ final class LandingVC : BaseVC, LinkDeviceVCDelegate, DeviceLinkingModalDelegate
|
|||
|
||||
func handleDeviceLinkingModalDismissed() {
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.stopLongPollerIfNeeded()
|
||||
appDelegate.stopPollerIfNeeded()
|
||||
TSAccountManager.sharedInstance().resetForReregistration()
|
||||
}
|
||||
|
||||
|
|
|
@ -681,7 +681,7 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
|
|||
[SSKEnvironment.shared.identityManager clearIdentityKey];
|
||||
[LKAPI clearRandomSnodePool];
|
||||
AppDelegate *appDelegate = (AppDelegate *)UIApplication.sharedApplication.delegate;
|
||||
[appDelegate stopLongPollerIfNeeded];
|
||||
[appDelegate stopPollerIfNeeded];
|
||||
[appDelegate stopOpenGroupPollersIfNeeded];
|
||||
[SSKEnvironment.shared.tsAccountManager resetForReregistration];
|
||||
UIViewController *rootViewController = [[OnboardingController new] initialViewController];
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
import PromiseKit
|
||||
|
||||
@objc(LKLongPoller)
|
||||
public final class LokiLongPoller : NSObject {
|
||||
@objc(LKPoller)
|
||||
public final class LokiPoller : NSObject {
|
||||
private let onMessagesReceived: ([SSKProtoEnvelope]) -> Void
|
||||
private let storage = OWSPrimaryStorage.shared()
|
||||
private var hasStarted = false
|
||||
private var hasStopped = false
|
||||
private var connections = Set<Promise<Void>>()
|
||||
private var usedSnodes = Set<LokiAPITarget>()
|
||||
|
||||
// MARK: Settings
|
||||
private let connectionCount = 3
|
||||
private let retryInterval: TimeInterval = 4
|
||||
|
||||
// MARK: Convenience
|
||||
private var userHexEncodedPublicKey: String { return getUserHexEncodedPublicKey() }
|
||||
private static let pollInterval: TimeInterval = 1
|
||||
private static let retryInterval: TimeInterval = 4
|
||||
|
||||
// MARK: Initialization
|
||||
@objc public init(onMessagesReceived: @escaping ([SSKProtoEnvelope]) -> Void) {
|
||||
|
@ -25,7 +21,7 @@ public final class LokiLongPoller : NSObject {
|
|||
// MARK: Public API
|
||||
@objc public func startIfNeeded() {
|
||||
guard !hasStarted else { return }
|
||||
print("[Loki] Started long polling.")
|
||||
print("[Loki] Started polling.")
|
||||
hasStarted = true
|
||||
hasStopped = false
|
||||
openConnections()
|
||||
|
@ -33,7 +29,7 @@ public final class LokiLongPoller : NSObject {
|
|||
|
||||
@objc public func stopIfNeeded() {
|
||||
guard !hasStopped else { return }
|
||||
print("[Loki] Stopped long polling.")
|
||||
print("[Loki] Stopped polling.")
|
||||
hasStarted = false
|
||||
hasStopped = true
|
||||
usedSnodes.removeAll()
|
||||
|
@ -42,49 +38,46 @@ public final class LokiLongPoller : NSObject {
|
|||
// MARK: Private API
|
||||
private func openConnections() {
|
||||
guard !hasStopped else { return }
|
||||
LokiAPI.getSwarm(for: userHexEncodedPublicKey).then { [weak self] _ -> Guarantee<[Result<Void>]> in
|
||||
guard let strongSelf = self else { return Guarantee.value([Result<Void>]()) }
|
||||
LokiAPI.getSwarm(for: getUserHexEncodedPublicKey()).then { [weak self] _ -> Promise<Void> in
|
||||
guard let strongSelf = self else { return Promise { $0.fulfill(()) } }
|
||||
strongSelf.usedSnodes.removeAll()
|
||||
let connections: [Promise<Void>] = (0..<strongSelf.connectionCount).map { _ in
|
||||
let (promise, seal) = Promise<Void>.pending()
|
||||
strongSelf.openConnectionToNextSnode(seal: seal)
|
||||
return promise
|
||||
}
|
||||
strongSelf.connections = Set(connections)
|
||||
return when(resolved: connections)
|
||||
let (promise, seal) = Promise<Void>.pending()
|
||||
strongSelf.pollNextSnode(seal: seal)
|
||||
return promise
|
||||
}.ensure { [weak self] in
|
||||
guard let strongSelf = self else { return }
|
||||
Timer.scheduledTimer(withTimeInterval: strongSelf.retryInterval, repeats: false) { _ in
|
||||
Timer.scheduledTimer(withTimeInterval: LokiPoller.retryInterval, repeats: false) { _ in
|
||||
guard let strongSelf = self else { return }
|
||||
strongSelf.openConnections()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func openConnectionToNextSnode(seal: Resolver<Void>) {
|
||||
private func pollNextSnode(seal: Resolver<Void>) {
|
||||
let userHexEncodedPublicKey = getUserHexEncodedPublicKey()
|
||||
let swarm = LokiAPI.swarmCache[userHexEncodedPublicKey] ?? []
|
||||
let userHexEncodedPublicKey = self.userHexEncodedPublicKey
|
||||
let unusedSnodes = Set(swarm).subtracting(usedSnodes)
|
||||
if !unusedSnodes.isEmpty {
|
||||
// randomElement() uses the system's default random generator, which is cryptographically secure
|
||||
let nextSnode = unusedSnodes.randomElement()!
|
||||
usedSnodes.insert(nextSnode)
|
||||
print("[Loki] Opening long polling connection to \(nextSnode).")
|
||||
longPoll(nextSnode, seal: seal).catch(on: LokiAPI.errorHandlingQueue) { [weak self] error in
|
||||
print("[Loki] Long polling connection to \(nextSnode) failed; dropping it and switching to next snode.")
|
||||
print("[Loki] Polling \(nextSnode).")
|
||||
poll(nextSnode, seal: seal).catch(on: LokiAPI.errorHandlingQueue) { [weak self] error in
|
||||
print("[Loki] Polling \(nextSnode) failed; dropping it and switching to next snode.")
|
||||
LokiAPI.dropIfNeeded(nextSnode, hexEncodedPublicKey: userHexEncodedPublicKey)
|
||||
self?.openConnectionToNextSnode(seal: seal)
|
||||
self?.pollNextSnode(seal: seal)
|
||||
}
|
||||
} else {
|
||||
seal.fulfill(())
|
||||
}
|
||||
}
|
||||
|
||||
private func longPoll(_ target: LokiAPITarget, seal: Resolver<Void>) -> Promise<Void> {
|
||||
return LokiAPI.getRawMessages(from: target, usingLongPolling: true).then(on: DispatchQueue.global()) { [weak self] rawResponse -> Promise<Void> in
|
||||
private func poll(_ target: LokiAPITarget, seal: Resolver<Void>) -> Promise<Void> {
|
||||
return LokiAPI.getRawMessages(from: target, usingLongPolling: false).then(on: DispatchQueue.global()) { [weak self] rawResponse -> Promise<Void> in
|
||||
guard let strongSelf = self, !strongSelf.hasStopped else { return Promise.value(()) }
|
||||
let messages = LokiAPI.parseRawMessagesResponse(rawResponse, from: target)
|
||||
strongSelf.onMessagesReceived(messages)
|
||||
return strongSelf.longPoll(target, seal: seal)
|
||||
return strongSelf.poll(target, seal: seal)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue