22import Foundation
33
44class EPCNetworkManager : EPCNetworkManaging {
5-
6- private let storageManager : EPCStorageManaging
5+
76 private let session : Session
87 private let operationQueue : OperationQueue
8+
9+ private var outputQueue = [ ( url: URL, body: NSDictionary) ] ( )
910
10- init ( storageManager: EPCStorageManaging , session: Session = Session . shared) {
11- self . storageManager = storageManager
11+ init ( session: Session = Session . shared) {
1212 self . session = session
1313
1414 operationQueue = OperationQueue ( )
1515 operationQueue. maxConcurrentOperationCount = 1
1616 }
17-
18- func httpPost ( url: URL , body: NSDictionary ) {
19- storageManager . createAndSavePost ( with : url, body: body)
17+
18+ func schedulePost ( url: URL , body: NSDictionary ) {
19+ outputQueue . append ( ( url : url, body: body) )
2020 }
2121
2222 func httpDownload( url: URL , completion: @escaping ( Data ? ) -> Void ) {
23- httpDownload ( url: url, maxAttempts : 5 , attemptDelay: 2 , completion: completion)
23+ httpDownload ( url: url, retriesRemaining : 5 , attemptDelay: 2 , completion: completion)
2424 }
2525
2626 /**
2727 * Download data over HTTP with capacity for retries
2828 * - Parameters:
2929 * - url: where to request data from
30- * - maxAttempts : maximum number of retries allowed for this download operation
30+ * - maxRetries : maximum number of retries allowed for this download operation
3131 * - attemptDelay: time between each retry
3232 * - completion: what to do with the downloaded data
3333 */
34- private func httpDownload( url: URL , maxAttempts : Int , attemptDelay: TimeInterval , completion: @escaping ( Data ? ) -> Void ) {
34+ private func httpDownload( url: URL , retriesRemaining : Int , attemptDelay: TimeInterval , completion: @escaping ( Data ? ) -> Void ) {
3535
36- guard maxAttempts > 0 else {
36+ if retriesRemaining < 0 {
3737 completion ( nil )
3838 return
3939 }
@@ -42,7 +42,7 @@ class EPCNetworkManager: EPCNetworkManaging {
4242
4343 let failureBlock = {
4444 dispatchOnMainQueueAfterDelayInSeconds ( attemptDelay) {
45- self . httpDownload ( url: url, maxAttempts : maxAttempts - 1 , attemptDelay: attemptDelay, completion: completion)
45+ self . httpDownload ( url: url, retriesRemaining : retriesRemaining - 1 , attemptDelay: attemptDelay, completion: completion)
4646 }
4747 }
4848
@@ -69,83 +69,32 @@ class EPCNetworkManager: EPCNetworkManaging {
6969 task? . resume ( )
7070 }
7171
72- func httpTryPost( _ completion : ( ( ) -> Void ) ? = nil ) {
72+ func httpTryPost( ) {
7373
7474 let operation = AsyncBlockOperation { ( operation) in
75-
76- self . storageManager. deleteStalePosts ( )
77- let postItems = self . storageManager. fetchPostsForPosting ( )
78-
79- self . postItems ( postItems) {
80- operation. finish ( )
81- }
82- }
83-
84- operationQueue. addOperation ( operation)
85- guard let completion = completion else {
86- return
87- }
88- let completionBlockOp = BlockOperation ( block: completion)
89- completionBlockOp. addDependency ( operation)
90- operationQueue. addOperation ( completion)
91- }
92-
93- private func postItems( _ items: [ EPCPost ] , completion: @escaping ( ) -> Void ) {
9475
95- let taskGroup = WMFTaskGroup ( )
96-
97- var completedIDs = Set < NSManagedObjectID > ( )
98- var failedIDs = Set < NSManagedObjectID > ( )
99-
100- for item in items {
101- let moid = item. objectID
102- guard let urlAndBody = storageManager. urlAndBodyOfPost ( item) else {
103- failedIDs. insert ( moid)
104- continue
105- }
106- taskGroup. enter ( )
107- let userAgent = item. userAgent ?? WikipediaAppUtils . versionedUserAgent ( )
108- submit ( url: urlAndBody. url, payload: urlAndBody. body, userAgent: userAgent) { ( error) in
109- if let error = error {
110- if error != . network {
111- failedIDs. insert ( moid)
112- }
113- } else {
114- completedIDs. insert ( moid)
76+ var queuedEvent : ( url: URL , body: NSDictionary ) ?
77+ while !self . outputQueue. isEmpty {
78+ queuedEvent = self . outputQueue. remove ( at: 0 )
79+ if let queuedEvent = queuedEvent {
80+ self . submit ( url: queuedEvent. url, payload: queuedEvent. body)
11581 }
116- taskGroup. leave ( )
11782 }
83+
84+ operation. finish ( )
11885 }
11986
120- taskGroup. waitInBackground {
121- if ( completedIDs. count == items. count) {
122- DDLogDebug ( " EPCNetworkManager: All records succeeded " )
123- } else {
124- DDLogDebug ( " EPCNetworkManager: Some records failed " )
125- }
126- self . storageManager. updatePosts ( completedIDs: completedIDs, failedIDs: failedIDs)
127- completion ( )
128- }
87+ operationQueue. addOperation ( operation)
12988 }
130-
131- private func submit( url: URL , payload: NSDictionary , userAgent: String , completion: @escaping ( EventLoggingError ? ) -> Void ) {
13289
133- var request = session . request ( with : url, method : . post , bodyParameters : payload , bodyEncoding : . json )
134- request. setValue ( userAgent , forHTTPHeaderField : " User-Agent " )
90+ private func submit ( url: URL , payload : Any ? = nil ) {
91+ let request = session . request ( with : url , method : . post , bodyParameters : payload , bodyEncoding : . json )
13592 let task = session. dataTask ( with: request, completionHandler: { ( _, response, error) in
136- guard error == nil ,
137- let httpResponse = response as? HTTPURLResponse ,
138- httpResponse. statusCode / 100 == 2 else {
139- if let error = error as NSError ? , error. domain == NSURLErrorDomain {
140- completion ( EventLoggingError . network)
141- } else {
142- completion ( EventLoggingError . generic)
143- }
144- return
93+ if error != nil {
94+ DDLogError ( " EPCNetworkManager: An error occurred sending the request " )
14595 }
146- completion ( nil )
14796 } )
14897 task? . resume ( )
14998 }
150-
99+
151100}
0 commit comments