Retry delaying servers loading

This commit is contained in:
Djorkaeff Alexandre 2024-01-23 18:19:23 -03:00
parent 02a169205d
commit 045f2084cd
4 changed files with 107 additions and 46 deletions

View File

@ -25,51 +25,11 @@ protocol ServersLoading {
final class ServersLoader: NSObject {
@Dependency private var database: ServersDatabase
private let session: WCSession
private let session: WatchSessionProtocol
init(session: WCSession) {
init(session: WatchSessionProtocol = RetriableWatchSession()) {
self.session = session
super.init()
session.delegate = self
session.activate()
}
private func sendMessage(completionHandler: @escaping (Result<WatchMessage, ServersLoadingError>) -> Void) {
print("sendMessage")
guard session.activationState == .activated else {
completionHandler(.failure(.unactive))
return
}
guard !session.iOSDeviceNeedsUnlockAfterRebootForReachability else {
completionHandler(.failure(.locked))
return
}
guard session.isReachable else {
completionHandler(.failure(.unreachable))
return
}
session.sendMessage([:]) { dictionary in
do {
let data = try JSONSerialization.data(withJSONObject: dictionary)
let message = try JSONDecoder().decode(WatchMessage.self, from: data)
completionHandler(.success(message))
} catch {
completionHandler(.failure(.undecodable(error)))
}
}
}
}
// MARK: - WCSessionDelegate
extension ServersLoader: WCSessionDelegate {
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
}
}
@ -78,7 +38,7 @@ extension ServersLoader: WCSessionDelegate {
extension ServersLoader: ServersLoading {
func loadServers() -> AnyPublisher<Void, ServersLoadingError> {
Future<Void, ServersLoadingError> { [self] promise in
sendMessage { result in
session.sendMessage { result in
switch result {
case .success(let message):
for server in message.servers {

View File

@ -0,0 +1,98 @@
import WatchConnectivity
protocol WatchSessionProtocol {
func sendMessage(completionHandler: @escaping (Result<WatchMessage, ServersLoadingError>) -> Void)
}
/// Default WatchSession protocol implementation.
final class WatchSession: NSObject, WatchSessionProtocol, WCSessionDelegate {
private let session: WCSession
init(session: WCSession) {
self.session = session
super.init()
session.delegate = self
session.activate()
}
func sendMessage(completionHandler: @escaping (Result<WatchMessage, ServersLoadingError>) -> Void) {
guard session.activationState == .activated else {
completionHandler(.failure(.unactive))
return
}
guard !session.iOSDeviceNeedsUnlockAfterRebootForReachability else {
completionHandler(.failure(.locked))
return
}
guard session.isReachable else {
completionHandler(.failure(.unreachable))
return
}
session.sendMessage([:]) { dictionary in
do {
let data = try JSONSerialization.data(withJSONObject: dictionary)
let message = try JSONDecoder().decode(WatchMessage.self, from: data)
completionHandler(.success(message))
} catch {
completionHandler(.failure(.undecodable(error)))
}
}
}
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
}
}
/// Retry decorator for WatchSession protocol.
final class RetriableWatchSession: WatchSessionProtocol {
private let session: WatchSessionProtocol
private let retries: Int
init(session: WatchSessionProtocol = DelayableWatchSession(session: WatchSession(session: .default)), retries: Int = 3) {
self.session = session
self.retries = retries
}
func sendMessage(completionHandler: @escaping (Result<WatchMessage, ServersLoadingError>) -> Void) {
session.sendMessage { [weak self] result in
guard let self else {
return
}
switch result {
case .success(let message):
completionHandler(.success(message))
case .failure where retries > 0:
session.sendMessage(completionHandler: completionHandler)
case .failure(let error):
completionHandler(.failure(error))
}
}
}
}
/// Delay decorator for WatchSession protocol.
final class DelayableWatchSession: WatchSessionProtocol {
private let delay: TimeInterval
private let session: WatchSessionProtocol
init(delay: TimeInterval = 1, session: WatchSessionProtocol) {
self.delay = delay
self.session = session
}
func sendMessage(completionHandler: @escaping (Result<WatchMessage, ServersLoadingError>) -> Void) {
Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { [weak self] _ in
guard let self else {
return
}
self.session.sendMessage(completionHandler: completionHandler)
}
}
}

View File

@ -11,7 +11,7 @@ struct RocketChat_Watch_AppApp: App {
private func registerDependencies() {
Store.register(AppRouting.self, factory: router)
Store.register(ServersDatabase.self, factory: DefaultDatabase())
Store.register(ServersLoading.self, factory: ServersLoader(session: .default))
Store.register(ServersLoading.self, factory: ServersLoader())
Store.register(MessagesLoading.self, factory: MessagesLoader())
Store.register(RoomsLoading.self, factory: RoomsLoader())
}

View File

@ -113,6 +113,7 @@
1E76CBD825152C870067298C /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E680ED82512990700C9257A /* Request.swift */; };
1E76CBD925152C8C0067298C /* Push.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E2F61652512958900871711 /* Push.swift */; };
1E76CBDA25152C8E0067298C /* SendMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E598AE825151A63002BDFBD /* SendMessage.swift */; };
1E8979472B6063FC001D99F0 /* WatchSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8979462B6063FC001D99F0 /* WatchSession.swift */; };
1E9A71692B59B6E100477BA2 /* MessageSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E9A71682B59B6E100477BA2 /* MessageSender.swift */; };
1E9A716F2B59CBCA00477BA2 /* AttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E9A716E2B59CBCA00477BA2 /* AttachmentView.swift */; };
1E9A71712B59CC1300477BA2 /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E9A71702B59CC1300477BA2 /* Attachment.swift */; };
@ -404,6 +405,7 @@
1E6737FF24DC52660009E081 /* NotificationService-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NotificationService-Bridging-Header.h"; sourceTree = "<group>"; };
1E67380324DC529B0009E081 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = "<group>"; };
1E680ED82512990700C9257A /* Request.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = "<group>"; };
1E8979462B6063FC001D99F0 /* WatchSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchSession.swift; sourceTree = "<group>"; };
1E9A71682B59B6E100477BA2 /* MessageSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSender.swift; sourceTree = "<group>"; };
1E9A716E2B59CBCA00477BA2 /* AttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentView.swift; sourceTree = "<group>"; };
1E9A71702B59CC1300477BA2 /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
@ -865,6 +867,7 @@
1EDFD1052B58A66E002FEE5F /* CancelBag.swift */,
1EDFD1072B58AA77002FEE5F /* RoomsLoader.swift */,
1E9A71682B59B6E100477BA2 /* MessageSender.swift */,
1E8979462B6063FC001D99F0 /* WatchSession.swift */,
);
path = Loaders;
sourceTree = "<group>";
@ -1185,7 +1188,6 @@
};
1ED0388D2B507B4B00C007D4 = {
CreatedOnToolsVersion = 15.0;
DevelopmentTeam = S6UPZG7ZR3;
ProvisioningStyle = Automatic;
};
1EFEB5942493B6640072EDC0 = {
@ -1876,6 +1878,7 @@
1ED033CD2B55D671004F4930 /* RocketChatDatabase.swift in Sources */,
1E29A3122B5866090093C03C /* Room.swift in Sources */,
1E29A3032B585B070093C03C /* FailableDecodable.swift in Sources */,
1E8979472B6063FC001D99F0 /* WatchSession.swift in Sources */,
1E29A2FE2B585B070093C03C /* ReadRequest.swift in Sources */,
1E9A71692B59B6E100477BA2 /* MessageSender.swift in Sources */,
1E29A3072B585B070093C03C /* RocketChatError.swift in Sources */,
@ -2307,7 +2310,7 @@
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_ASSET_PATHS = "\"RocketChat Watch App/Preview Content\"";
DEVELOPMENT_TEAM = S6UPZG7ZR3;
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;