add linkedItemUpdates data service function

This commit is contained in:
Satindar Dhillon
2022-08-04 09:25:41 -07:00
parent fe577cbdd5
commit 7bb1f92def

View File

@ -8,7 +8,98 @@ struct InternalLinkedItemQueryResult {
let cursor: String?
}
struct InternalLinkedItemUpdatesQueryResult {
let items: [InternalLinkedItem]
let deletedItemIDs: [String]
let cursor: String?
}
private struct SyncItemEdge {
let itemID: String
let isDeletedItem: Bool
let item: InternalLinkedItem?
}
extension DataService {
// swiftlint:disable:next function_body_length
func linkedItemUpdates(
limit: Int,
cursor: String?,
since: Date?
) async throws -> InternalLinkedItemUpdatesQueryResult {
struct QuerySuccessResult {
let edges: [SyncItemEdge]
let cursor: String?
}
enum QueryResult {
case success(result: QuerySuccessResult)
case error(error: String)
}
let path = appEnvironment.graphqlPath
let headers = networker.defaultHeaders
let selection = Selection<QueryResult, Unions.UpdatesSinceResult> {
try $0.on(
updatesSinceError: .init {
QueryResult.error(error: try $0.errorCodes().description)
},
updatesSinceSuccess: .init {
QueryResult.success(
result: QuerySuccessResult(
edges: try $0.edges(selection: syncItemEdgeSelection.list),
cursor: try $0.pageInfo(selection: Selection.PageInfo {
try $0.endCursor()
})
)
)
}
)
}
let query = Selection.Query {
try $0.updatesSince(
after: OptionalArgument(cursor),
first: OptionalArgument(limit),
since: DateTime(from: since ?? Date(timeIntervalSinceReferenceDate: 0)),
selection: selection
)
}
return try await withCheckedThrowingContinuation { continuation in
send(query, to: path, headers: headers) { queryResult in
guard let payload = try? queryResult.get() else {
continuation.resume(throwing: ContentFetchError.network)
return
}
switch payload.data {
case let .success(result: result):
var items = [InternalLinkedItem]()
var deletedItemIDs = [String]()
for edge in result.edges {
if edge.isDeletedItem {
deletedItemIDs.append(edge.itemID)
} else if let item = edge.item {
items.append(item)
}
}
continuation.resume(
returning: InternalLinkedItemUpdatesQueryResult(
items: items,
deletedItemIDs: deletedItemIDs,
cursor: result.cursor
)
)
case let .error(error):
continuation.resume(throwing: ContentFetchError.unknown(description: error.description))
}
}
}
}
/// Performs GraphQL request to fetch `InternalLinkedItem`s and a cursor value
/// - Parameters:
/// - limit: max number of items to return
@ -152,6 +243,14 @@ private let libraryArticleSelection = Selection.Article {
)
}
private let syncItemEdgeSelection = Selection.SyncUpdatedItemEdge {
SyncItemEdge(
itemID: try $0.itemId(),
isDeletedItem: try $0.updateReason() == .deleted,
item: try $0.node(selection: searchItemSelection.nullable)
)
}
private let searchItemSelection = Selection.SearchItem {
InternalLinkedItem(
id: try $0.id(),