Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add docs and improve merging of records from WebSockets into cache. #1892

Merged
merged 2 commits into from
Aug 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Sources/Apollo/ApolloStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ public final class ApolloStore {
}
}

/// Merges a `RecordSet` into the normalized cache.
/// - Parameters:
/// - records: The records to be merged into the cache.
/// - identifier: [optional] A unique identifier for the request that kicked off this change,
/// to assist in de-duping cache hits for watchers.
/// - callbackQueue: The queue to call the completion block on. Defaults to `DispatchQueue.main`.
/// - completion: [optional] A completion block to be called after records are merged into the cache.
public func publish(records: RecordSet, identifier: UUID? = nil, callbackQueue: DispatchQueue = .main, completion: ((Result<Void, Error>) -> Void)? = nil) {
queue.async(flags: .barrier) {
do {
Expand Down
5 changes: 5 additions & 0 deletions Sources/Apollo/GraphQLResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public final class GraphQLResponse<Data: GraphQLSelectionSet> {
self.variables = operation.variables
}

/// Parses a response into a `GraphQLResult` and a `RecordSet`.
/// The result can be sent to a completion block for a request.
/// The `RecordSet` can be merged into a local cache.
/// - Parameter cacheKeyForObject: See `CacheKeyForObject`
/// - Returns: A `GraphQLResult` and a `RecordSet`.
public func parseResult(cacheKeyForObject: CacheKeyForObject? = nil) throws -> (GraphQLResult<Data>, RecordSet?) {
let errors: [GraphQLError]?

Expand Down
41 changes: 27 additions & 14 deletions Sources/ApolloWebSocket/WebSocketTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public class WebSocketTransport {
///
/// - Parameters:
/// - websocket: The websocket client to use for creating a websocket connection.
/// - store: [optional] The `ApolloStore` used as a local cache. Defaults to `nil`.
/// - clientName: The client name to use for this client. Defaults to `Self.defaultClientName`
/// - clientVersion: The client version to use for this client. Defaults to `Self.defaultClientVersion`.
/// - sendOperationIdentifiers: Whether or not to send operation identifiers with operations. Defaults to false.
Expand Down Expand Up @@ -362,24 +363,36 @@ extension WebSocketTransport: NetworkTransport {
return EmptyCancellable()
}

return WebSocketTask(self, operation) { [store] result in
return WebSocketTask(self, operation) { [weak store, contextIdentifier, callbackQueue] result in
switch result {
case .success(let jsonBody):
let response = GraphQLResponse(operation: operation, body: jsonBody)
if let store = store {
do {
let (_, records) = try response.parseResult(cacheKeyForObject: store.cacheKeyForObject)
if let records = records {
store.publish(records: records, identifier: nil)
do {
let response = GraphQLResponse(operation: operation, body: jsonBody)

if let store = store {
let (graphQLResult, parsedRecords) = try response.parseResult(cacheKeyForObject: store.cacheKeyForObject)
guard let records = parsedRecords else {
callCompletion(with: .success(graphQLResult))
return
}

store.publish(records: records,
identifier: contextIdentifier,
callbackQueue: callbackQueue) { result in
switch result {
case .success:
completionHandler(.success(graphQLResult))

case let .failure(error):
callCompletion(with: .failure(error))
}
}
} catch {
callCompletion(with: .failure(error))

} else {
let graphQLResult = try response.parseResultFast()
callCompletion(with: .success(graphQLResult))
}
}

do {
let graphQLResult = try response.parseResultFast()
callCompletion(with: .success(graphQLResult))

} catch {
callCompletion(with: .failure(error))
}
Expand Down