Change the article fetch strategy so that we only fetch 200 at a time and continue fetching until we have them all
This commit is contained in:
parent
cc269a8089
commit
0d5b3ea48b
@ -571,19 +571,24 @@ final class ReaderAPICaller: NSObject {
|
|||||||
self.requestAuthorizationToken(endpoint: baseURL) { (result) in
|
self.requestAuthorizationToken(endpoint: baseURL) { (result) in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let token):
|
case .success(let token):
|
||||||
// Do POST asking for data about all the new articles
|
|
||||||
var request = URLRequest(url: baseURL.appendingPathComponent(ReaderAPIEndpoints.contents.rawValue), credentials: self.credentials)
|
var request = URLRequest(url: baseURL.appendingPathComponent(ReaderAPIEndpoints.contents.rawValue), credentials: self.credentials)
|
||||||
self.addVariantHeaders(&request)
|
self.addVariantHeaders(&request)
|
||||||
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
||||||
request.httpMethod = "POST"
|
request.httpMethod = "POST"
|
||||||
|
|
||||||
// Get ids from above into hex representation of value
|
let chunkedArticleIds = articleIDs.chunked(into: 200)
|
||||||
let idsToFetch = articleIDs.map({ (reference) -> String in
|
let group = DispatchGroup()
|
||||||
return "i=tag:google.com,2005:reader/item/\(reference)"
|
var groupEntries = [ReaderAPIEntry]()
|
||||||
|
var groupError: Error? = nil
|
||||||
|
|
||||||
|
for articleIDChunk in chunkedArticleIds {
|
||||||
|
let itemFetchParameters = articleIDChunk.map({ articleID -> String in
|
||||||
|
return "i=tag:google.com,2005:reader/item/\(articleID)"
|
||||||
}).joined(separator:"&")
|
}).joined(separator:"&")
|
||||||
|
|
||||||
let postData = "T=\(token)&output=json&\(idsToFetch)".data(using: String.Encoding.utf8)
|
let postData = "T=\(token)&output=json&\(itemFetchParameters)".data(using: String.Encoding.utf8)
|
||||||
|
|
||||||
|
group.enter()
|
||||||
self.transport.send(request: request, method: HTTPMethod.post, data: postData!, resultType: ReaderAPIEntryWrapper.self, completion: { (result) in
|
self.transport.send(request: request, method: HTTPMethod.post, data: postData!, resultType: ReaderAPIEntryWrapper.self, completion: { (result) in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let (_, entryWrapper)):
|
case .success(let (_, entryWrapper)):
|
||||||
@ -591,13 +596,22 @@ final class ReaderAPICaller: NSObject {
|
|||||||
completion(.failure(ReaderAPIAccountDelegateError.invalidResponse))
|
completion(.failure(ReaderAPIAccountDelegateError.invalidResponse))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
groupEntries.append(contentsOf: entryWrapper.entries)
|
||||||
completion(.success((entryWrapper.entries)))
|
group.leave()
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
groupError = error
|
||||||
|
group.leave()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
group.notify(queue: DispatchQueue.main) {
|
||||||
|
if let error = groupError {
|
||||||
|
completion(.failure(error))
|
||||||
|
} else {
|
||||||
|
completion(.success(groupEntries))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
@ -619,7 +633,7 @@ final class ReaderAPICaller: NSObject {
|
|||||||
.appendingPathComponent(ReaderAPIEndpoints.itemIds.rawValue)
|
.appendingPathComponent(ReaderAPIEndpoints.itemIds.rawValue)
|
||||||
.appendingQueryItems([
|
.appendingQueryItems([
|
||||||
URLQueryItem(name: "s", value: webFeedID),
|
URLQueryItem(name: "s", value: webFeedID),
|
||||||
URLQueryItem(name: "ot", value: String(since.timeIntervalSince1970)),
|
URLQueryItem(name: "ot", value: String(Int(since.timeIntervalSince1970))),
|
||||||
URLQueryItem(name: "output", value: "json")
|
URLQueryItem(name: "output", value: "json")
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -683,11 +697,11 @@ final class ReaderAPICaller: NSObject {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
let sinceString = since.timeIntervalSince1970
|
let sinceTimeInterval = since.timeIntervalSince1970
|
||||||
let url = baseURL
|
let url = baseURL
|
||||||
.appendingPathComponent(ReaderAPIEndpoints.itemIds.rawValue)
|
.appendingPathComponent(ReaderAPIEndpoints.itemIds.rawValue)
|
||||||
.appendingQueryItems([
|
.appendingQueryItems([
|
||||||
URLQueryItem(name: "ot", value: String(sinceString)),
|
URLQueryItem(name: "ot", value: String(Int(sinceTimeInterval))),
|
||||||
URLQueryItem(name: "n", value: "1000"),
|
URLQueryItem(name: "n", value: "1000"),
|
||||||
URLQueryItem(name: "output", value: "json"),
|
URLQueryItem(name: "output", value: "json"),
|
||||||
URLQueryItem(name: "s", value: ReaderStreams.readingList.rawValue)
|
URLQueryItem(name: "s", value: ReaderStreams.readingList.rawValue)
|
||||||
@ -698,66 +712,74 @@ final class ReaderAPICaller: NSObject {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let conditionalGet = accountMetadata?.conditionalGetInfo[ConditionalGetKeys.unreadEntries]
|
var request = URLRequest(url: callURL, credentials: credentials)
|
||||||
var request = URLRequest(url: callURL, credentials: credentials, conditionalGet: conditionalGet)
|
|
||||||
addVariantHeaders(&request)
|
addVariantHeaders(&request)
|
||||||
|
|
||||||
self.transport.send(request: request, resultType: ReaderAPIReferenceWrapper.self) { result in
|
self.transport.send(request: request, resultType: ReaderAPIReferenceWrapper.self) { result in
|
||||||
|
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let (_, entries)):
|
case .success(let (response, entries)):
|
||||||
|
|
||||||
guard let entriesItemRefs = entries?.itemRefs else {
|
guard let entriesItemRefs = entries?.itemRefs, entriesItemRefs.count > 0 else {
|
||||||
completion(.failure(ReaderAPIAccountDelegateError.invalidResponse))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard entriesItemRefs.count > 0 else {
|
|
||||||
completion(.success((nil, nil, nil)))
|
completion(.success((nil, nil, nil)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This needs to be moved when we fix paging for item ids
|
||||||
|
let dateInfo = HTTPDateInfo(urlResponse: response)
|
||||||
|
self.accountMetadata?.lastArticleFetchStartTime = dateInfo?.date
|
||||||
|
self.accountMetadata?.lastArticleFetchEndTime = Date()
|
||||||
|
|
||||||
self.requestAuthorizationToken(endpoint: baseURL) { (result) in
|
self.requestAuthorizationToken(endpoint: baseURL) { (result) in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let token):
|
case .success(let token):
|
||||||
// Do POST asking for data about all the new articles
|
|
||||||
var request = URLRequest(url: baseURL.appendingPathComponent(ReaderAPIEndpoints.contents.rawValue), credentials: self.credentials)
|
var request = URLRequest(url: baseURL.appendingPathComponent(ReaderAPIEndpoints.contents.rawValue), credentials: self.credentials)
|
||||||
self.addVariantHeaders(&request)
|
self.addVariantHeaders(&request)
|
||||||
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
||||||
request.httpMethod = "POST"
|
request.httpMethod = "POST"
|
||||||
|
|
||||||
// Get ids from above into hex representation of value
|
let chunkedItemRefs = entriesItemRefs.chunked(into: 200)
|
||||||
let idsToFetch = entriesItemRefs.map({ (reference) -> String in
|
let group = DispatchGroup()
|
||||||
|
var groupEntries = [ReaderAPIEntry]()
|
||||||
|
var groupError: Error? = nil
|
||||||
|
|
||||||
|
for itemRefsChunk in chunkedItemRefs {
|
||||||
|
let itemFetchParameters = itemRefsChunk.map({ itemRef -> String in
|
||||||
if self.variant == .theOldReader {
|
if self.variant == .theOldReader {
|
||||||
return "i=tag:google.com,2005:reader/item/\(reference.itemId)"
|
return "i=tag:google.com,2005:reader/item/\(itemRef.itemId)"
|
||||||
} else {
|
} else {
|
||||||
let idValue = Int(reference.itemId)!
|
let idValue = Int(itemRef.itemId)!
|
||||||
let idHexString = String(idValue, radix: 16, uppercase: false)
|
let idHexString = String(idValue, radix: 16, uppercase: false)
|
||||||
return "i=tag:google.com,2005:reader/item/\(idHexString)"
|
return "i=tag:google.com,2005:reader/item/\(idHexString)"
|
||||||
}
|
}
|
||||||
}).joined(separator:"&")
|
}).joined(separator:"&")
|
||||||
|
|
||||||
let postData = "T=\(token)&output=json&\(idsToFetch)".data(using: String.Encoding.utf8)
|
let postData = "T=\(token)&output=json&\(itemFetchParameters)".data(using: String.Encoding.utf8)
|
||||||
|
|
||||||
|
group.enter()
|
||||||
self.transport.send(request: request, method: HTTPMethod.post, data: postData!, resultType: ReaderAPIEntryWrapper.self, completion: { (result) in
|
self.transport.send(request: request, method: HTTPMethod.post, data: postData!, resultType: ReaderAPIEntryWrapper.self, completion: { (result) in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let (response, entryWrapper)):
|
case .success(let (_, entryWrapper)):
|
||||||
guard let entryWrapper = entryWrapper else {
|
guard let entryWrapper = entryWrapper else {
|
||||||
completion(.failure(ReaderAPIAccountDelegateError.invalidResponse))
|
completion(.failure(ReaderAPIAccountDelegateError.invalidResponse))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
groupEntries.append(contentsOf: entryWrapper.entries)
|
||||||
let dateInfo = HTTPDateInfo(urlResponse: response)
|
group.leave()
|
||||||
self.accountMetadata?.lastArticleFetchStartTime = dateInfo?.date
|
|
||||||
self.accountMetadata?.lastArticleFetchEndTime = Date()
|
|
||||||
|
|
||||||
completion(.success((entryWrapper.entries, nil, nil)))
|
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
groupError = error
|
||||||
|
group.leave()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
group.notify(queue: DispatchQueue.main) {
|
||||||
|
if let error = groupError {
|
||||||
|
completion(.failure(error))
|
||||||
|
} else {
|
||||||
|
completion(.success((groupEntries, nil, nil)))
|
||||||
|
}
|
||||||
|
}
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
@ -917,7 +939,7 @@ final class ReaderAPICaller: NSObject {
|
|||||||
let url = baseURL
|
let url = baseURL
|
||||||
.appendingPathComponent(ReaderAPIEndpoints.itemIds.rawValue)
|
.appendingPathComponent(ReaderAPIEndpoints.itemIds.rawValue)
|
||||||
.appendingQueryItems([
|
.appendingQueryItems([
|
||||||
URLQueryItem(name: "s", value: ReaderState.starred),
|
URLQueryItem(name: "s", value: ReaderState.starred.rawValue),
|
||||||
URLQueryItem(name: "n", value: "1000"),
|
URLQueryItem(name: "n", value: "1000"),
|
||||||
URLQueryItem(name: "output", value: "json")
|
URLQueryItem(name: "output", value: "json")
|
||||||
])
|
])
|
||||||
@ -951,8 +973,6 @@ final class ReaderAPICaller: NSObject {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
|
Loading…
x
Reference in New Issue
Block a user