@@ -11,8 +11,9 @@ public actor WMFArticleSummaryDataController: WMFArticleSummaryDataControlling {
1111 public static var shared = WMFArticleSummaryDataController ( )
1212
1313 private var cache : [ WMFPage : WMFArticleSummary ] = [ : ]
14+ private var inFlightRequests : [ WMFPage : [ ( Result < WMFArticleSummary , Error > ) -> Void ] ] = [ : ]
1415
15- public init ( ) {
16+ private init ( ) {
1617 self . service = WMFDataEnvironment . current. basicService
1718 }
1819
@@ -24,14 +25,26 @@ public actor WMFArticleSummaryDataController: WMFArticleSummaryDataControlling {
2425 return
2526 }
2627
28+ // Check if there's already an in-flight request for this page
29+ if inFlightRequests [ wmfPage] != nil {
30+ // Queue this completion to be called when the in-flight request completes
31+ inFlightRequests [ wmfPage] ? . append ( completion)
32+ return
33+ }
34+
35+ // Initialize the in-flight request tracking with the first completion
36+ inFlightRequests [ wmfPage] = [ completion]
37+
2738 guard let service else {
28- completion ( . failure( WMFDataControllerError . basicServiceUnavailable) )
39+ let error = WMFDataControllerError . basicServiceUnavailable
40+ resolveInFlightRequests ( for: wmfPage, with: . failure( error) )
2941 return
3042 }
3143
3244 guard !title. isEmpty,
3345 let url = URL . wikimediaRestAPIURL ( project: project, additionalPathComponents: [ " page " , " summary " , title. spacesToUnderscores] ) else {
34- completion ( . failure( WMFDataControllerError . failureCreatingRequestURL) )
46+ let error = WMFDataControllerError . failureCreatingRequestURL
47+ resolveInFlightRequests ( for: wmfPage, with: . failure( error) )
3548 return
3649 }
3750
@@ -43,20 +56,32 @@ public actor WMFArticleSummaryDataController: WMFArticleSummaryDataControlling {
4356 Task { [ weak self] in
4457 guard let self else { return }
4558 await self . updateCache ( page: wmfPage, summary: summary)
59+ await self . resolveInFlightRequests ( for: wmfPage, with: result)
4660 }
4761
48- default :
49- break
62+ case . failure:
63+ Task { [ weak self] in
64+ guard let self else { return }
65+ await self . resolveInFlightRequests ( for: wmfPage, with: result)
66+ }
5067 }
51-
52- completion ( result)
5368 }
5469 }
5570
5671 private func updateCache( page: WMFPage , summary: WMFArticleSummary ) {
5772 cache [ page] = summary
5873 }
5974
75+ private func resolveInFlightRequests( for page: WMFPage , with result: Result < WMFArticleSummary , Error > ) {
76+ guard let completions = inFlightRequests [ page] else { return }
77+ inFlightRequests. removeValue ( forKey: page)
78+
79+ // Call all waiting completions with the result
80+ for completion in completions {
81+ completion ( result)
82+ }
83+ }
84+
6085 public func fetchArticleSummary( project: WMFProject , title: String ) async throws -> WMFArticleSummary {
6186 return try await withCheckedThrowingContinuation { continuation in
6287 fetchArticleSummary ( project: project, title: title) { result in
0 commit comments