Expose the async nature of the ClientProxy startSync method

This commit is contained in:
Stefan Ceriu
2026-06-04 11:03:32 +03:00
parent da5360c8e8
commit e4a7322250
4 changed files with 43 additions and 36 deletions
@@ -41,8 +41,10 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
configureElementCallService() configureElementCallService()
configureNotificationManager() configureNotificationManager()
observeUserSessionChanges() observeUserSessionChanges()
startSync() Task {
Task { await appHooks.configure(with: userSession) } await startSync()
await appHooks.configure(with: userSession)
}
} }
} }
} }
@@ -185,8 +187,10 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
// When reporting a VoIP call through the CXProvider's `reportNewIncomingVoIPPushPayload` // When reporting a VoIP call through the CXProvider's `reportNewIncomingVoIPPushPayload`
// the UIApplication states don't change and syncing is neither started nor ran on // the UIApplication states don't change and syncing is neither started nor ran on
// a background task. Handle both manually here. // a background task. Handle both manually here.
self?.startSync() Task {
self?.scheduleDelayedSyncStop() await self?.startSync()
self?.scheduleDelayedSyncStop()
}
default: default:
break break
} }
@@ -1072,12 +1076,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
} }
} }
private func startSync() { private func startSync() async {
guard let userSession else { return } guard let userSession else { return }
analyticsService.signpost.startTransaction(.upToDateRoomList) analyticsService.signpost.startTransaction(.upToDateRoomList)
userSession.clientProxy.startSync() await userSession.clientProxy.startSync()
guard clientProxyObserver == nil else { guard clientProxyObserver == nil else {
return return
@@ -1180,7 +1184,9 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
private func applicationWillEnterForeground() { private func applicationWillEnterForeground() {
MXLog.info("Application will enter foreground") MXLog.info("Application will enter foreground")
endActiveBackgroundTask() endActiveBackgroundTask()
startSync() Task {
await startSync()
}
} }
@objc @objc
@@ -1207,7 +1213,9 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
return return
} }
self?.handleBackgroundAppRefresh(task) Task {
await self?.handleBackgroundAppRefresh(task)
}
} }
MXLog.info("Register background app refresh with result: \(result)") MXLog.info("Register background app refresh with result: \(result)")
@@ -1228,7 +1236,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
} }
private var backgroundRefreshSyncObserver: AnyCancellable? private var backgroundRefreshSyncObserver: AnyCancellable?
private func handleBackgroundAppRefresh(_ task: BGAppRefreshTask) { private func handleBackgroundAppRefresh(_ task: BGAppRefreshTask) async {
MXLog.info("Started background app refresh") MXLog.info("Started background app refresh")
// This is important for the app to keep refreshing in the background // This is important for the app to keep refreshing in the background
@@ -1255,7 +1263,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
return return
} }
startSync() await startSync()
// Be a good citizen, run for a max of 10 SS responses or 10 seconds // Be a good citizen, run for a max of 10 SS responses or 10 seconds
// An SS request will time out after 30 seconds if no new data is available // An SS request will time out after 30 seconds if no new data is available
@@ -2462,11 +2462,11 @@ class ClientProxyMock: ClientProxyProtocol, @unchecked Sendable {
var startSyncCalled: Bool { var startSyncCalled: Bool {
return startSyncCallsCount > 0 return startSyncCallsCount > 0
} }
var startSyncClosure: (() -> Void)? var startSyncClosure: (() async -> Void)?
func startSync() { func startSync() async {
startSyncCallsCountLock.withLock { startSyncUnderlyingCallsCount += 1 } startSyncCallsCountLock.withLock { startSyncUnderlyingCallsCount += 1 }
startSyncClosure?() await startSyncClosure?()
} }
//MARK: - stopSync //MARK: - stopSync
@@ -389,7 +389,7 @@ class ClientProxy: ClientProxyProtocol {
} }
} }
func startSync() { func startSync() async {
guard !hasEncounteredAuthError else { guard !hasEncounteredAuthError else {
MXLog.warning("Ignoring request, this client has an unknown token.") MXLog.warning("Ignoring request, this client has an unknown token.")
return return
@@ -400,23 +400,21 @@ class ClientProxy: ClientProxyProtocol {
return return
} }
MXLog.info("Starting sync") if appSettings.clientPausingAndResumingEnabled {
do {
Task { MXLog.info("Resuming client")
if appSettings.clientPausingAndResumingEnabled { try await client.resume()
do { } catch {
try await client.resume() MXLog.error("Failed resuming client with error: \(error)")
} catch {
MXLog.error("Failed resuming client with error: \(error)")
}
} }
await syncService.start()
// If we are using OAuth we want to cache the account management URL in volatile memory on the SDK side.
// To avoid the cache being invalidated while the app is backgrounded, we cache at every sync start.
await cacheAccountURL()
} }
MXLog.info("Starting sync")
await syncService.start()
// If we are using OAuth we want to cache the account management URL in volatile memory on the SDK side.
// To avoid the cache being invalidated while the app is backgrounded, we cache at every sync start.
await cacheAccountURL()
} }
/// A stored task for restarting the sync after a failure. This is stored so that we can cancel /// A stored task for restarting the sync after a failure. This is stored so that we can cancel
@@ -432,7 +430,7 @@ class ClientProxy: ClientProxyProtocol {
// Until the SDK can tell us the failure, we add a small // Until the SDK can tell us the failure, we add a small
// delay to avoid generating multi-gigabyte log files. // delay to avoid generating multi-gigabyte log files.
try await Task.sleep(for: .milliseconds(250)) try await Task.sleep(for: .milliseconds(250))
self?.startSync() await self?.startSync()
} catch { } catch {
MXLog.error("Restart cancelled.") MXLog.error("Restart cancelled.")
} }
@@ -445,8 +443,6 @@ class ClientProxy: ClientProxyProtocol {
} }
func stopSync(completion: (() -> Void)?) { func stopSync(completion: (() -> Void)?) {
MXLog.info("Stopping sync")
if restartTask != nil { if restartTask != nil {
MXLog.warning("Removing the sync service restart task.") MXLog.warning("Removing the sync service restart task.")
restartTask = nil restartTask = nil
@@ -461,17 +457,18 @@ class ClientProxy: ClientProxyProtocol {
completion?() completion?()
} }
MXLog.info("Stopping sync")
await syncService.stop() await syncService.stop()
MXLog.info("Sync stopped")
if appSettings.clientPausingAndResumingEnabled { if appSettings.clientPausingAndResumingEnabled {
do { do {
MXLog.info("Pausing client")
try await client.pause() try await client.pause()
} catch { } catch {
MXLog.error("Failed pausing client with error: \(error)") MXLog.error("Failed pausing client with error: \(error)")
} }
} }
MXLog.info("Sync stopped")
} }
} }
@@ -1032,7 +1029,9 @@ class ClientProxy: ClientProxyProtocol {
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [weak self] reachability in .sink { [weak self] reachability in
if reachability == .reachable { if reachability == .reachable {
self?.startSync() Task {
await self?.startSync()
}
} }
} }
.store(in: &cancellables) .store(in: &cancellables)
@@ -169,7 +169,7 @@ protocol ClientProxyProtocol: AnyObject {
func hasDevicesToVerifyAgainst() async -> Result<Bool, ClientProxyError> func hasDevicesToVerifyAgainst() async -> Result<Bool, ClientProxyError>
func startSync() func startSync() async
func stopSync() func stopSync()