Break up link'n'sync long polls into shorter repeated requests
This commit is contained in:
parent
9f9e0fc668
commit
49ff87f3cc
@ -136,6 +136,7 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
|
||||
private let appContext: AppContext
|
||||
private let attachmentDownloadManager: AttachmentDownloadManager
|
||||
private let attachmentUploadManager: AttachmentUploadManager
|
||||
private let dateProvider: DateProvider
|
||||
private let db: any DB
|
||||
private let kvStore: KeyValueStore
|
||||
private let messageBackupManager: MessageBackupManager
|
||||
@ -147,6 +148,7 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
|
||||
appContext: AppContext,
|
||||
attachmentDownloadManager: AttachmentDownloadManager,
|
||||
attachmentUploadManager: AttachmentUploadManager,
|
||||
dateProvider: @escaping DateProvider,
|
||||
db: any DB,
|
||||
messageBackupManager: MessageBackupManager,
|
||||
messagePipelineSupervisor: MessagePipelineSupervisor,
|
||||
@ -156,6 +158,7 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
|
||||
self.appContext = appContext
|
||||
self.attachmentDownloadManager = attachmentDownloadManager
|
||||
self.attachmentUploadManager = attachmentUploadManager
|
||||
self.dateProvider = dateProvider
|
||||
self.db = db
|
||||
self.kvStore = KeyValueStore(collection: "LinkAndSyncManagerImpl")
|
||||
self.messageBackupManager = messageBackupManager
|
||||
@ -410,18 +413,37 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
|
||||
private func _waitForDeviceToLink(
|
||||
tokenId: DeviceProvisioningTokenId
|
||||
) async throws(PrimaryLinkNSyncError) -> Requests.WaitForDeviceToLinkResponse {
|
||||
let response: HTTPResponse
|
||||
do {
|
||||
Logger.info("Waiting for device to link")
|
||||
response = try await networkManager.asyncRequest(
|
||||
Requests.waitForDeviceToLink(tokenId: tokenId),
|
||||
canUseWebSocket: false
|
||||
)
|
||||
Logger.info("Device linked!")
|
||||
} catch {
|
||||
if error is CancellationError {
|
||||
throw .cancelled(linkedDeviceId: nil)
|
||||
Logger.info("Waiting for device to link")
|
||||
let startDate = dateProvider()
|
||||
var numNetworkErrors = 0
|
||||
var response: HTTPResponse?
|
||||
while dateProvider().timeIntervalSince(startDate) < Constants.waitForDeviceLinkTotalTimeout {
|
||||
do {
|
||||
response = try await networkManager.asyncRequest(
|
||||
Requests.waitForDeviceToLink(tokenId: tokenId),
|
||||
canUseWebSocket: false
|
||||
)
|
||||
if response?.responseStatusCode == Requests.WaitForDeviceToLinkResponseCodes.timeout.rawValue {
|
||||
// retry
|
||||
continue
|
||||
}
|
||||
Logger.info("Device linked!")
|
||||
break
|
||||
} catch {
|
||||
if error is CancellationError {
|
||||
throw .cancelled(linkedDeviceId: nil)
|
||||
}
|
||||
if error .isNetworkFailureOrTimeout {
|
||||
numNetworkErrors += 1
|
||||
if numNetworkErrors <= 3 {
|
||||
// retry
|
||||
continue
|
||||
}
|
||||
}
|
||||
throw .errorWaitingForLinkedDevice
|
||||
}
|
||||
}
|
||||
guard let response else {
|
||||
throw .errorWaitingForLinkedDevice
|
||||
}
|
||||
|
||||
@ -619,16 +641,35 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
|
||||
private func _waitForPrimaryToUploadBackup(
|
||||
auth: ChatServiceAuth
|
||||
) async throws(SecondaryLinkNSyncError) -> Requests.ExportAndUploadBackupResult {
|
||||
let response: HTTPResponse
|
||||
do {
|
||||
response = try await networkManager.asyncRequest(
|
||||
Requests.waitForLinkNSyncBackupUpload(auth: auth),
|
||||
canUseWebSocket: false
|
||||
)
|
||||
} catch {
|
||||
if error is CancellationError {
|
||||
throw SecondaryLinkNSyncError.cancelled
|
||||
let startDate = dateProvider()
|
||||
var numNetworkErrors = 0
|
||||
var response: HTTPResponse?
|
||||
while dateProvider().timeIntervalSince(startDate) < Constants.waitForBackupUploadTotalTimeout {
|
||||
do {
|
||||
response = try await networkManager.asyncRequest(
|
||||
Requests.waitForLinkNSyncBackupUpload(auth: auth),
|
||||
canUseWebSocket: false
|
||||
)
|
||||
if response?.responseStatusCode == Requests.WaitForLinkNSyncBackupUploadResponseCodes.timeout.rawValue {
|
||||
continue
|
||||
}
|
||||
break
|
||||
} catch {
|
||||
if error is CancellationError {
|
||||
throw SecondaryLinkNSyncError.cancelled
|
||||
}
|
||||
|
||||
if error .isNetworkFailureOrTimeout {
|
||||
numNetworkErrors += 1
|
||||
if numNetworkErrors <= 3 {
|
||||
// retry
|
||||
continue
|
||||
}
|
||||
}
|
||||
throw SecondaryLinkNSyncError.networkError
|
||||
}
|
||||
}
|
||||
guard let response else {
|
||||
throw SecondaryLinkNSyncError.networkError
|
||||
}
|
||||
|
||||
@ -724,8 +765,9 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
|
||||
|
||||
static let enabledOnPrimaryKey = "enabledOnPrimaryKey"
|
||||
|
||||
static let waitForDeviceLinkTimeoutSeconds: UInt32 = FeatureFlags.linkAndSyncTimeoutSeconds
|
||||
static let waitForBackupUploadTimeoutSeconds: UInt32 = FeatureFlags.linkAndSyncTimeoutSeconds
|
||||
static let longPollRequestTimeoutSeconds: UInt32 = 10
|
||||
static let waitForDeviceLinkTotalTimeout: TimeInterval = FeatureFlags.linkAndSyncTotalPrimaryTimeout
|
||||
static let waitForBackupUploadTotalTimeout: TimeInterval = FeatureFlags.linkAndSyncTotalSecondaryTimeout
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
@ -757,7 +799,7 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
|
||||
var urlComponents = URLComponents(string: "v1/devices/wait_for_linked_device/\(tokenId.id)")!
|
||||
urlComponents.queryItems = [URLQueryItem(
|
||||
name: "timeout",
|
||||
value: "\(LinkAndSyncManagerImpl.Constants.waitForDeviceLinkTimeoutSeconds)"
|
||||
value: "\(LinkAndSyncManagerImpl.Constants.longPollRequestTimeoutSeconds)"
|
||||
)]
|
||||
let request = TSRequest(
|
||||
url: urlComponents.url!,
|
||||
@ -767,7 +809,7 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
|
||||
request.shouldHaveAuthorizationHeaders = true
|
||||
request.applyRedactionStrategy(.redactURLForSuccessResponses())
|
||||
// The timeout is server side; apply wiggle room for our local clock.
|
||||
request.timeoutInterval = 30 + TimeInterval(Constants.waitForDeviceLinkTimeoutSeconds)
|
||||
request.timeoutInterval = 10 + TimeInterval(Constants.longPollRequestTimeoutSeconds)
|
||||
return request
|
||||
}
|
||||
|
||||
@ -834,7 +876,7 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
|
||||
var urlComponents = URLComponents(string: "v1/devices/transfer_archive")!
|
||||
urlComponents.queryItems = [URLQueryItem(
|
||||
name: "timeout",
|
||||
value: "\(Constants.waitForBackupUploadTimeoutSeconds)"
|
||||
value: "\(Constants.longPollRequestTimeoutSeconds)"
|
||||
)]
|
||||
let request = TSRequest(
|
||||
url: urlComponents.url!,
|
||||
@ -845,7 +887,7 @@ public class LinkAndSyncManagerImpl: LinkAndSyncManager {
|
||||
request.setAuth(auth)
|
||||
request.applyRedactionStrategy(.redactURLForSuccessResponses())
|
||||
// The timeout is server side; apply wiggle room for our local clock.
|
||||
request.timeoutInterval = 30 + TimeInterval(Constants.waitForBackupUploadTimeoutSeconds)
|
||||
request.timeoutInterval = 10 + TimeInterval(Constants.longPollRequestTimeoutSeconds)
|
||||
return request
|
||||
}
|
||||
}
|
||||
|
||||
@ -1225,6 +1225,7 @@ public class AppSetup {
|
||||
appContext: appContext,
|
||||
attachmentDownloadManager: attachmentDownloadManager,
|
||||
attachmentUploadManager: attachmentUploadManager,
|
||||
dateProvider: dateProvider,
|
||||
db: db,
|
||||
messageBackupManager: messageBackupManager,
|
||||
messagePipelineSupervisor: messagePipelineSupervisor,
|
||||
|
||||
@ -43,10 +43,13 @@ public enum FeatureFlags {
|
||||
public static let messageBackupRemoteExportAlpha = build.includes(.dev)
|
||||
public static let messageBackupFileAlphaRegistrationFlow = build.includes(.dev)
|
||||
public static let linkAndSync = build.includes(.beta)
|
||||
public static let linkAndSyncTimeoutSeconds: UInt32 = switch build {
|
||||
public static let linkAndSyncTotalPrimaryTimeout: TimeInterval = switch build {
|
||||
case .dev, .internal: 120
|
||||
case .beta, .production: 60
|
||||
}
|
||||
public static let linkAndSyncTotalSecondaryTimeout: TimeInterval = switch build {
|
||||
case .dev, .internal: 300
|
||||
case .beta: 150
|
||||
case .production: 60
|
||||
case .beta, .production: 120
|
||||
}
|
||||
public static let backupsMemorySamplerRatio: Float = build.includes(.internal) ? 0.1 : 0
|
||||
public static let messageBackupQuickRestoreFlow = false
|
||||
|
||||
Loading…
Reference in New Issue
Block a user