Skip to content

Commit

Permalink
feat(client): only rebroadcast on deep equals
Browse files Browse the repository at this point in the history
  • Loading branch information
micimize committed Nov 6, 2020
1 parent 376bd4d commit ee64e99
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 2 deletions.
19 changes: 17 additions & 2 deletions packages/graphql/lib/src/core/query_manager.dart
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:meta/meta.dart';
import 'package:collection/collection.dart';

import 'package:gql_exec/gql_exec.dart';
import 'package:gql_link/gql_link.dart' show Link;
Expand All @@ -17,10 +18,14 @@ import 'package:graphql/src/scheduler/scheduler.dart';

import 'package:graphql/src/core/_query_write_handling.dart';

bool Function(dynamic a, dynamic b) _deepEquals =
const DeepCollectionEquality().equals;

class QueryManager {
QueryManager({
@required this.link,
@required this.cache,
this.alwaysRebroadcast = false,
}) {
scheduler = QueryScheduler(
queryManager: this,
Expand All @@ -30,6 +35,9 @@ class QueryManager {
final Link link;
final GraphQLCache cache;

/// Whether to skip deep equality checks in [maybeRebroadcastQueries]
final bool alwaysRebroadcast;

QueryScheduler scheduler;
int idCounter = 1;

Expand Down Expand Up @@ -384,11 +392,11 @@ class QueryManager {

for (ObservableQuery query in queries.values) {
if (query != exclude && query.isRebroadcastSafe) {
final dynamic cachedData = cache.readQuery(
final cachedData = cache.readQuery(
query.options.asRequest,
optimistic: true,
);
if (cachedData != null) {
if (_cachedDataHasChangedFor(query, cachedData)) {
query.addResult(
mapFetchResultToQueryResult(
Response(data: cachedData),
Expand All @@ -403,6 +411,13 @@ class QueryManager {
return true;
}

bool _cachedDataHasChangedFor(
ObservableQuery query,
Map<String, dynamic> cachedData,
) =>
cachedData != null &&
(alwaysRebroadcast || !_deepEquals(query.latestResult.data, cachedData));

void setQuery(ObservableQuery observableQuery) {
queries[observableQuery.queryId] = observableQuery;
}
Expand Down
6 changes: 6 additions & 0 deletions packages/graphql/lib/src/graphql_client.dart
Expand Up @@ -12,6 +12,10 @@ import 'package:graphql/src/core/fetch_more.dart';
/// The link is a [Link] over which GraphQL documents will be resolved into a [Response].
/// The cache is the [GraphQLCache] to use for caching results and optimistic updates.
///
/// The client automatically rebroadcasts watched queries when their underlying data
/// changes in the cache. To skip the data comparison check, `alwaysRebroadcast: true` can be passed.
/// **NOTE**: This flag was added ot accomodate the old default behavior.
/// It is marked `@experimental` because it may be deprecated in the future.
///
/// [ac]: https://www.apollographql.com/docs/react/v3.0-beta/api/core/ApolloClient/
/// [link]: https://github.com/gql-dart/gql/tree/master/links/gql_link
Expand All @@ -21,11 +25,13 @@ class GraphQLClient implements GraphQLDataProxy {
@required this.link,
@required this.cache,
this.defaultPolicies,
@experimental bool alwaysRebroadcast = false,
}) {
defaultPolicies ??= DefaultPolicies();
queryManager = QueryManager(
link: link,
cache: cache,
alwaysRebroadcast: alwaysRebroadcast ?? false,
);
}

Expand Down

0 comments on commit ee64e99

Please sign in to comment.