From 952ace7603c55aa9ab5f59d417b6d500e9e86fba Mon Sep 17 00:00:00 2001 From: Caio Zullo Date: Wed, 20 Mar 2024 12:44:45 +0200 Subject: [PATCH] Ensures all store operations run in the same scheduler Our Core Data store is thread-safe, so it can be safely used from any queue. However, we may want to perform store operations in a dedicated infra queue to avoid doing too much work in other queues. For example, the URLSessionHTTPClient sends results in its URLSession delegate queue. If we store the result received from the URLSessionHTTPClient in the same queue as we receive it, we may be doing too much work in the URLSession delegate queue - which could slow down the processing of other URLSessionHTTPClient results. To avoid this problem, we're now calling all store methods in a specific infra queue by using `receive(on: scheduler)` when performing a store operation after receiving results from another infra operation. --- EssentialApp/EssentialApp/SceneDelegate.swift | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/EssentialApp/EssentialApp/SceneDelegate.swift b/EssentialApp/EssentialApp/SceneDelegate.swift index 063967d0..32cefcbe 100644 --- a/EssentialApp/EssentialApp/SceneDelegate.swift +++ b/EssentialApp/EssentialApp/SceneDelegate.swift @@ -68,10 +68,12 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } func sceneWillResignActive(_ scene: UIScene) { - do { - try localFeedLoader.validateCache() - } catch { - logger.error("Failed to validate cache with error: \(error.localizedDescription)") + scheduler.schedule { [localFeedLoader, logger] in + do { + try localFeedLoader.validateCache() + } catch { + logger.error("Failed to validate cache with error: \(error.localizedDescription)") + } } } @@ -92,10 +94,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { private func makeRemoteFeedLoaderWithLocalFallback() -> AnyPublisher, Error> { makeRemoteFeedLoader() + .receive(on: scheduler) .caching(to: localFeedLoader) .fallback(to: localFeedLoader.loadPublisher) .map(makeFirstPage) - .subscribe(on: scheduler) .eraseToAnyPublisher() } @@ -106,6 +108,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { (cachedItems + newItems, newItems.last) } .map(makePage) + .receive(on: scheduler) .caching(to: localFeedLoader) .subscribe(on: scheduler) .eraseToAnyPublisher() @@ -139,8 +142,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { httpClient .getPublisher(url: url) .tryMap(FeedImageDataMapper.map) + .receive(on: scheduler) .caching(to: localImageLoader, using: url) - .subscribe(on: scheduler) .eraseToAnyPublisher() }) .subscribe(on: scheduler)