From e3353e54bc812d8a1268fd82ce8a3720ce3cca0b Mon Sep 17 00:00:00 2001 From: micimize Date: Fri, 7 Jun 2019 19:16:59 -0500 Subject: [PATCH 1/5] feat(client): Introduce QueryResultSource for more informative result typing feat(client): More rigorous result source management feat(flutter): Return a MultiSourceResult from runMutation Breaks the eager and networked paths in the query manager into two subfunctions, and allows for accessing them granularly via `fetchQueryAsMultiSourceResult` --- .../lib/src/core/observable_query.dart | 24 +-- .../graphql/lib/src/core/query_manager.dart | 155 +++++++++++------- .../graphql/lib/src/core/query_result.dart | 65 +++++++- packages/graphql/lib/src/link/operation.dart | 4 +- .../lib/src/widgets/mutation.dart | 27 +-- packages/graphql_flutter/pubspec.yaml | 14 +- 6 files changed, 194 insertions(+), 95 deletions(-) diff --git a/packages/graphql/lib/src/core/observable_query.dart b/packages/graphql/lib/src/core/observable_query.dart index 4d450afd6..c6aff0f8d 100644 --- a/packages/graphql/lib/src/core/observable_query.dart +++ b/packages/graphql/lib/src/core/observable_query.dart @@ -39,7 +39,8 @@ class ObservableQuery { final Set> _onDataSubscriptions = >{}; - QueryResult previousResult; + /// The most recently seen result from this operation's stream + QueryResult latestResult; QueryLifecycle lifecycle = QueryLifecycle.UNEXECUTED; @@ -99,8 +100,10 @@ class ObservableQuery { } } - void fetchResults() { - queryManager.fetchQuery(queryId, options); + MultiSourceResult fetchResults() { + final allResults = + queryManager.fetchQueryAsMultiSourceResult(queryId, options); + latestResult ??= allResults.eagerResult; // if onData callbacks have been registered, // they are waited on by default @@ -111,28 +114,29 @@ class ObservableQuery { if (options.pollInterval != null && options.pollInterval > 0) { startPolling(options.pollInterval); } + + return allResults; } /// add a result to the stream, /// copying `loading` and `optimistic` - /// from the `previousResult` if they aren't set. + /// from the `latestResult` if they aren't set. void addResult(QueryResult result) { // don't overwrite results due to some async/optimism issue - if (previousResult != null && - previousResult.timestamp.isAfter(result.timestamp)) { + if (latestResult != null && + latestResult.timestamp.isAfter(result.timestamp)) { return; } - if (previousResult != null) { - result.loading ??= previousResult.loading; - result.optimistic ??= previousResult.optimistic; + if (latestResult != null) { + result.source ??= latestResult.source; } if (lifecycle == QueryLifecycle.PENDING && result.optimistic != true) { lifecycle = QueryLifecycle.COMPLETED; } - previousResult = result; + latestResult = result; controller.add(result); } diff --git a/packages/graphql/lib/src/core/query_manager.dart b/packages/graphql/lib/src/core/query_manager.dart index f0adca4c7..121bb3312 100644 --- a/packages/graphql/lib/src/core/query_manager.dart +++ b/packages/graphql/lib/src/core/query_manager.dart @@ -64,34 +64,46 @@ class QueryManager { String queryId, BaseOptions options, ) async { - // create a new operation to fetch - final Operation operation = Operation.fromOptions(options); + final allResults = fetchQueryAsMultiSourceResult(queryId, options); + return allResults.networkResult ?? allResults.eagerResult; + } - if (options.optimisticResult != null) { - addOptimisticQueryResult( - queryId, - cacheKey: operation.toKey(), - optimisticResult: options.optimisticResult, - ); - } + /// Wrap both the `eagerResult` and `networkResult` future in a `MultiSourceResult` + /// if the cache policy precludes a network request, `networkResult` will be `null` + MultiSourceResult fetchQueryAsMultiSourceResult( + String queryId, + BaseOptions options, + ) { + final eagerResult = _eagerlyResolveQuery( + queryId, + options, + ); + + // _eagerlyResolveQuery handles cacheOnly, + // so if we're loading + cacheFirst we continue to network + return MultiSourceResult( + eagerResult: eagerResult, + networkResult: + (shouldStopAtCache(options.fetchPolicy) && !eagerResult.loading) + ? null + : _resolveQueryOnNetwork(queryId, options), + ); + } + + /// Resolve the query on the network, + /// negotiating any necessary cache edits / optimistic cleanup + Future _resolveQueryOnNetwork( + String queryId, + BaseOptions options, + ) async { + // create a new operation to fetch + final Operation operation = Operation.fromOptions(options) + ..setContext(options.context); FetchResult fetchResult; QueryResult queryResult; try { - if (options.context != null) { - operation.setContext(options.context); - } - queryResult = _addEagerCacheResult( - queryId, - operation.toKey(), - options.fetchPolicy, - ); - - if (shouldStopAtCache(options.fetchPolicy) && queryResult != null) { - return queryResult; - } - // execute the operation through the provided link(s) fetchResult = await execute( link: link, @@ -143,6 +155,66 @@ class QueryManager { return queryResult; } + /// Add an eager cache response to the stream if possible, + /// based on `fetchPolicy` and `optimisticResults` + QueryResult _eagerlyResolveQuery( + String queryId, + BaseOptions options, + ) { + final String cacheKey = options.toKey(); + + QueryResult queryResult = QueryResult(loading: true); + + try { + if (options.optimisticResult != null) { + queryResult = _getOptimisticQueryResult( + queryId, + cacheKey: cacheKey, + optimisticResult: options.optimisticResult, + ); + } + + // if we haven't already resolved results optimistically, + // we attempt to resolve the from the cache + if (shouldRespondEagerlyFromCache(options.fetchPolicy) && + !queryResult.optimistic) { + final data = cache.read(cacheKey); + // we only push an eager query with data + if (queryResult.data != null) { + queryResult = QueryResult( + data: data, + source: QueryResultSource.Cache, + ); + } + + if (options.fetchPolicy == FetchPolicy.cacheOnly && + queryResult.loading) { + queryResult = QueryResult( + source: QueryResultSource.Cache, + errors: [ + GraphQLError( + message: + 'Could not find that operation in the cache. (FetchPolicy.cacheOnly)', + ), + ], + ); + } + } + } catch (error) { + queryResult.addError(_attemptToWrapError(error)); + } + + // If not a regular eager cache resolution, + // will either be loading, or optimistic. + // + // if there's an optimistic result, we add it regardless of fetchPolicy + // This is undefined-ish behavior/edge case, but still better than just + // ignoring a provided optimisticResult. + // Would probably be better to add it ignoring the cache in such cases + addQueryResult(queryId, queryResult); + return queryResult; + } + void refetchQuery(String queryId) { final WatchQueryOptions options = queries[queryId].options; fetchQuery(queryId, options); @@ -180,38 +252,8 @@ class QueryManager { } } - // TODO what should the relationship to optimism be here - // TODO we should switch to quiver Optionals - /// Add an eager cache response to the stream if possible based on `fetchPolicy` - QueryResult _addEagerCacheResult( - String queryId, String cacheKey, FetchPolicy fetchPolicy) { - if (shouldRespondEagerlyFromCache(fetchPolicy)) { - final dynamic cachedData = cache.read(cacheKey); - - if (cachedData != null) { - // we're rebroadcasting from cache, - // so don't override optimism - final QueryResult queryResult = QueryResult( - data: cachedData, - loading: false, - ); - - addQueryResult(queryId, queryResult); - - return queryResult; - } - - if (fetchPolicy == FetchPolicy.cacheOnly) { - throw Exception( - 'Could not find that operation in the cache. (${fetchPolicy.toString()})', - ); - } - } - return null; - } - - /// Add an optimstic result to the query specified by `queryId`, if it exists - void addOptimisticQueryResult( + /// Create an optimstic result for the query specified by `queryId`, if it exists + QueryResult _getOptimisticQueryResult( String queryId, { @required String cacheKey, @required Object optimisticResult, @@ -224,10 +266,9 @@ class QueryManager { final QueryResult queryResult = QueryResult( data: cache.read(cacheKey), - loading: false, - optimistic: true, + source: QueryResultSource.OptimisticResult, ); - addQueryResult(queryId, queryResult); + return queryResult; } /// Remove the optimistic patch for `cacheKey`, if any diff --git a/packages/graphql/lib/src/core/query_result.dart b/packages/graphql/lib/src/core/query_result.dart index 6fd825c50..97912fbf1 100644 --- a/packages/graphql/lib/src/core/query_result.dart +++ b/packages/graphql/lib/src/core/query_result.dart @@ -1,24 +1,58 @@ +import 'dart:async' show FutureOr; + import 'package:graphql/src/core/graphql_error.dart'; +/// The source of the result data contained +/// +/// Loading: No data has been specified from any source +/// Cache: A result has been eagerly resolved from the cache +/// OptimisticResults: An optimistic result has been specified +/// (may include eager results from the cache) +/// Network: The query has been resolved on the network +/// +/// Both Optimistic and Cache sources are considered "Eager" results +enum QueryResultSource { + Loading, + Cache, + OptimisticResult, + Network, +} + +final eagerSources = { + QueryResultSource.Cache, + QueryResultSource.OptimisticResult +}; + class QueryResult { QueryResult({ this.data, this.errors, - this.loading, - this.stale, - this.optimistic = false, - }) : timestamp = DateTime.now(); + bool loading, + bool optimistic, + QueryResultSource source, + }) : timestamp = DateTime.now(), + this.source = source ?? loading == true + ? QueryResultSource.Loading + : optimistic == true ? QueryResultSource.OptimisticResult : null; DateTime timestamp; + /// The source of the result data. + /// null when unexecuted + QueryResultSource source; + /// List or Map dynamic data; List errors; - bool loading; - // TODO not sure what this is for - bool stale; - bool optimistic; + /// Whether data has been specified from either the cache or network) + bool get loading => source == QueryResultSource.Loading; + + /// Whether an optimistic result has been specified + /// (may include eager results from the cache) + bool get optimistic => source == QueryResultSource.OptimisticResult; + + /// Whether the response includes any graphql errors bool get hasErrors { if (errors == null) { return false; @@ -35,3 +69,18 @@ class QueryResult { } } } + +class MultiSourceResult { + MultiSourceResult({ + this.eagerResult, + this.networkResult, + }) : assert( + eagerResult.source != QueryResultSource.Network, + 'An eager result cannot be gotten from the network', + ) { + eagerResult ??= QueryResult(loading: true); + } + + QueryResult eagerResult; + FutureOr networkResult; +} diff --git a/packages/graphql/lib/src/link/operation.dart b/packages/graphql/lib/src/link/operation.dart index a3fcaa448..77b1e369b 100644 --- a/packages/graphql/lib/src/link/operation.dart +++ b/packages/graphql/lib/src/link/operation.dart @@ -26,7 +26,9 @@ class Operation extends RawOperationData { /// Sets the context of an operation by merging the new context with the old one. void setContext(Map next) { - _context.addAll(next); + if (next != null) { + _context.addAll(next); + } } Map getContext() { diff --git a/packages/graphql_flutter/lib/src/widgets/mutation.dart b/packages/graphql_flutter/lib/src/widgets/mutation.dart index eaf0b9fb3..8a79b4d95 100644 --- a/packages/graphql_flutter/lib/src/widgets/mutation.dart +++ b/packages/graphql_flutter/lib/src/widgets/mutation.dart @@ -92,7 +92,7 @@ class MutationState extends State { /// created by the query manager String get _patchId => '${observableQuery.queryId}.update'; - /// apply the user's + /// apply the user's patch void _optimisticUpdate(QueryResult result) { final Cache cache = client.cache; final String patchId = _patchId; @@ -136,14 +136,18 @@ class MutationState extends State { Iterable get callbacks => [onCompleted, update].where(notNull); - void runMutation(Map variables, {Object optimisticResult}) { - observableQuery - ..variables = variables - ..options.optimisticResult = optimisticResult - ..onData(callbacks) // add callbacks to observable - ..addResult(QueryResult(loading: true)) - ..fetchResults(); - } + /// Run the mutation with the given `variables` and `optimisticResult`, + /// returning a [MultiSourceResult] for handling both the eager and network results + MultiSourceResult runMutation( + Map variables, { + Object optimisticResult, + }) => + (observableQuery + ..variables = variables + ..options.optimisticResult = optimisticResult + ..onData(callbacks) // add callbacks to observable + ) + .fetchResults(); @override void dispose() { @@ -158,10 +162,7 @@ class MutationState extends State { // toggling mutations at the same place in the tree, // such as is done in the example, won't result in bugs key: Key(observableQuery?.options?.toKey()), - initialData: QueryResult( - loading: false, - optimistic: false, - ), + initialData: observableQuery?.latestResult ?? QueryResult(), stream: observableQuery?.stream, builder: ( BuildContext buildContext, diff --git a/packages/graphql_flutter/pubspec.yaml b/packages/graphql_flutter/pubspec.yaml index 00d4d52c4..c17f97774 100644 --- a/packages/graphql_flutter/pubspec.yaml +++ b/packages/graphql_flutter/pubspec.yaml @@ -1,14 +1,16 @@ name: graphql_flutter -description: A GraphQL client for Flutter, bringing all the features from a modern +description: + A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package. version: 1.1.1-beta.6 authors: -- Eus Dima -- Zino Hofmann -- Michael Joseph Rosenthal + - Eus Dima + - Zino Hofmann + - Michael Joseph Rosenthal homepage: https://github.com/zino-app/graphql-flutter/tree/master/packages/graphql_flutter dependencies: - graphql: ^1.1.1-beta.6 + graphql: #^1.1.1-beta.6 + path: ../graphql flutter: sdk: flutter meta: ^1.1.6 @@ -22,4 +24,4 @@ dev_dependencies: sdk: flutter test: ^1.5.3 environment: - sdk: '>=2.2.0 <3.0.0' + sdk: ">=2.2.0 <3.0.0" From 13fd8f782c6fe1b0394c1f94358a0437cc85c5d7 Mon Sep 17 00:00:00 2001 From: micimize Date: Fri, 7 Jun 2019 19:52:09 -0500 Subject: [PATCH 2/5] feat(flutter): eagerly fetch query results introduce overridable eagerlyFetchResults to avoid loading result when eagerly responding from cache --- .../graphql/lib/src/core/observable_query.dart | 15 ++++++++++++++- packages/graphql/lib/src/core/query_options.dart | 8 ++++++-- .../graphql_flutter/lib/src/widgets/query.dart | 5 +---- packages/graphql_flutter/pubspec.yaml | 7 +++++-- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/packages/graphql/lib/src/core/observable_query.dart b/packages/graphql/lib/src/core/observable_query.dart index c6aff0f8d..29b0e96a5 100644 --- a/packages/graphql/lib/src/core/observable_query.dart +++ b/packages/graphql/lib/src/core/observable_query.dart @@ -26,11 +26,18 @@ class ObservableQuery { @required this.queryManager, @required this.options, }) : queryId = queryManager.generateQueryId().toString() { + if (options.eagerlyFetchResults) { + _lastestWasEagerlyFetched = true; + fetchResults(); + } controller = StreamController.broadcast( onListen: onListen, ); } + // set to true when eagerly fetched to prevent back-to-back queries + bool _lastestWasEagerlyFetched = false; + final String queryId; final QueryManager queryManager; @@ -95,6 +102,10 @@ class ObservableQuery { } void onListen() { + if (_lastestWasEagerlyFetched) { + _lastestWasEagerlyFetched = false; + return; + } if (options.fetchResults) { fetchResults(); } @@ -138,7 +149,9 @@ class ObservableQuery { latestResult = result; - controller.add(result); + if (!controller.isClosed) { + controller.add(result); + } } // most mutation behavior happens here diff --git a/packages/graphql/lib/src/core/query_options.dart b/packages/graphql/lib/src/core/query_options.dart index e4f8ee5d0..818957603 100644 --- a/packages/graphql/lib/src/core/query_options.dart +++ b/packages/graphql/lib/src/core/query_options.dart @@ -115,7 +115,8 @@ class WatchQueryOptions extends QueryOptions { ErrorPolicy errorPolicy = ErrorPolicy.none, Object optimisticResult, int pollInterval, - this.fetchResults, + this.fetchResults = false, + this.eagerlyFetchResults, Map context, }) : super( document: document, @@ -125,10 +126,13 @@ class WatchQueryOptions extends QueryOptions { pollInterval: pollInterval, context: context, optimisticResult: optimisticResult, - ); + ) { + this.eagerlyFetchResults ??= fetchResults; + } /// Whether or not to fetch result. bool fetchResults; + bool eagerlyFetchResults; /// Checks if the [WatchQueryOptions] in this class are equal to some given options. bool areEqualTo(WatchQueryOptions otherOptions) { diff --git a/packages/graphql_flutter/lib/src/widgets/query.dart b/packages/graphql_flutter/lib/src/widgets/query.dart index d35afe53f..da012aeb4 100644 --- a/packages/graphql_flutter/lib/src/widgets/query.dart +++ b/packages/graphql_flutter/lib/src/widgets/query.dart @@ -68,7 +68,6 @@ class QueryState extends State { void didUpdateWidget(Query oldWidget) { super.didUpdateWidget(oldWidget); - // TODO @micimize - investigate why/if this was causing issues if (!observableQuery.options.areEqualTo(_options)) { _initQuery(); } @@ -83,9 +82,7 @@ class QueryState extends State { @override Widget build(BuildContext context) { return StreamBuilder( - initialData: QueryResult( - loading: true, - ), + initialData: observableQuery?.latestResult ?? QueryResult(loading: true), stream: observableQuery.stream, builder: ( BuildContext buildContext, diff --git a/packages/graphql_flutter/pubspec.yaml b/packages/graphql_flutter/pubspec.yaml index c17f97774..3d0582b76 100644 --- a/packages/graphql_flutter/pubspec.yaml +++ b/packages/graphql_flutter/pubspec.yaml @@ -9,8 +9,7 @@ authors: - Michael Joseph Rosenthal homepage: https://github.com/zino-app/graphql-flutter/tree/master/packages/graphql_flutter dependencies: - graphql: #^1.1.1-beta.6 - path: ../graphql + graphql: ^1.1.1-beta.6 flutter: sdk: flutter meta: ^1.1.6 @@ -25,3 +24,7 @@ dev_dependencies: test: ^1.5.3 environment: sdk: ">=2.2.0 <3.0.0" + +# dependency_overrides: +# graphql: +# path: ../graphql From 9ab25d825451cdeae5a12b071c95e2012d3712b0 Mon Sep 17 00:00:00 2001 From: micimize Date: Sat, 8 Jun 2019 20:32:06 -0500 Subject: [PATCH 3/5] refactor(client): more types --- packages/graphql/lib/src/core/observable_query.dart | 2 +- packages/graphql/lib/src/core/query_manager.dart | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/graphql/lib/src/core/observable_query.dart b/packages/graphql/lib/src/core/observable_query.dart index 29b0e96a5..a01036066 100644 --- a/packages/graphql/lib/src/core/observable_query.dart +++ b/packages/graphql/lib/src/core/observable_query.dart @@ -112,7 +112,7 @@ class ObservableQuery { } MultiSourceResult fetchResults() { - final allResults = + final MultiSourceResult allResults = queryManager.fetchQueryAsMultiSourceResult(queryId, options); latestResult ??= allResults.eagerResult; diff --git a/packages/graphql/lib/src/core/query_manager.dart b/packages/graphql/lib/src/core/query_manager.dart index 121bb3312..aaf280b59 100644 --- a/packages/graphql/lib/src/core/query_manager.dart +++ b/packages/graphql/lib/src/core/query_manager.dart @@ -64,7 +64,8 @@ class QueryManager { String queryId, BaseOptions options, ) async { - final allResults = fetchQueryAsMultiSourceResult(queryId, options); + final MultiSourceResult allResults = + fetchQueryAsMultiSourceResult(queryId, options); return allResults.networkResult ?? allResults.eagerResult; } @@ -74,7 +75,7 @@ class QueryManager { String queryId, BaseOptions options, ) { - final eagerResult = _eagerlyResolveQuery( + final QueryResult eagerResult = _eagerlyResolveQuery( queryId, options, ); @@ -178,9 +179,9 @@ class QueryManager { // we attempt to resolve the from the cache if (shouldRespondEagerlyFromCache(options.fetchPolicy) && !queryResult.optimistic) { - final data = cache.read(cacheKey); + final dynamic data = cache.read(cacheKey); // we only push an eager query with data - if (queryResult.data != null) { + if (data != null) { queryResult = QueryResult( data: data, source: QueryResultSource.Cache, From e671a998154a8e15a0475f740e863ffa214bc650 Mon Sep 17 00:00:00 2001 From: micimize Date: Sat, 8 Jun 2019 20:56:37 -0500 Subject: [PATCH 4/5] refactor(client): prefer QueryResult(source) over loading/optimistic --- .../graphql/lib/src/core/query_manager.dart | 16 +-- .../graphql/lib/src/core/query_result.dart | 13 +- packages/graphql_flutter/flutter_01.log | 122 ++++++++++++++++++ 3 files changed, 137 insertions(+), 14 deletions(-) create mode 100644 packages/graphql_flutter/flutter_01.log diff --git a/packages/graphql/lib/src/core/query_manager.dart b/packages/graphql/lib/src/core/query_manager.dart index aaf280b59..964624fb1 100644 --- a/packages/graphql/lib/src/core/query_manager.dart +++ b/packages/graphql/lib/src/core/query_manager.dart @@ -132,14 +132,11 @@ class QueryManager { queryResult = mapFetchResultToQueryResult( fetchResult, options, - loading: false, - optimistic: false, + source: QueryResultSource.Network, ); } catch (error) { - queryResult ??= QueryResult( - loading: false, - optimistic: false, - ); + // we set the source to indicate where the source of failure + queryResult ??= QueryResult(source: QueryResultSource.Network); queryResult.addError(_attemptToWrapError(error)); } @@ -292,6 +289,7 @@ class QueryManager { mapFetchResultToQueryResult( FetchResult(data: cachedData), query.options, + source: QueryResultSource.Cache, ), ); } @@ -321,8 +319,7 @@ class QueryManager { QueryResult mapFetchResultToQueryResult( FetchResult fetchResult, BaseOptions options, { - bool loading, - bool optimistic = false, + @required QueryResultSource source, }) { List errors; dynamic data; @@ -354,8 +351,7 @@ class QueryManager { return QueryResult( data: data, errors: errors, - loading: loading, - optimistic: optimistic, + source: source, ); } diff --git a/packages/graphql/lib/src/core/query_result.dart b/packages/graphql/lib/src/core/query_result.dart index 97912fbf1..5b618d1b6 100644 --- a/packages/graphql/lib/src/core/query_result.dart +++ b/packages/graphql/lib/src/core/query_result.dart @@ -31,14 +31,19 @@ class QueryResult { bool optimistic, QueryResultSource source, }) : timestamp = DateTime.now(), - this.source = source ?? loading == true - ? QueryResultSource.Loading - : optimistic == true ? QueryResultSource.OptimisticResult : null; + this.source = source ?? + ((loading == true) + ? QueryResultSource.Loading + : (optimistic == true) + ? QueryResultSource.OptimisticResult + : null); DateTime timestamp; /// The source of the result data. - /// null when unexecuted + /// + /// null when unexecuted. + /// Will be set when encountering an error during any execution attempt QueryResultSource source; /// List or Map diff --git a/packages/graphql_flutter/flutter_01.log b/packages/graphql_flutter/flutter_01.log new file mode 100644 index 000000000..33c80668f --- /dev/null +++ b/packages/graphql_flutter/flutter_01.log @@ -0,0 +1,122 @@ +Flutter crash report; please file at https://github.com/flutter/flutter/issues. + +## command + +flutter packages get + +## exception + +YamlException: Error on line 13, column 3: Duplicate mapping key. + ╷ +13 │ graphql: + │ ^^^^^^^ + ╵ + +``` +#0 Loader._loadMapping (package:yaml/src/loader.dart:167:9) +#1 Loader._loadNode (package:yaml/src/loader.dart:86:16) +#2 Loader._loadMapping (package:yaml/src/loader.dart:165:19) +#3 Loader._loadNode (package:yaml/src/loader.dart:86:16) +#4 Loader._loadDocument (package:yaml/src/loader.dart:62:20) +#5 Loader.load (package:yaml/src/loader.dart:54:20) +#6 loadYamlDocument (package:yaml/yaml.dart:51:25) +#7 loadYamlNode (package:yaml/yaml.dart:42:5) +#8 loadYaml (package:yaml/yaml.dart:34:5) +#9 FlutterManifest.createFromString (package:flutter_tools/src/flutter_manifest.dart:38:28) +#10 FlutterManifest.createFromPath (package:flutter_tools/src/flutter_manifest.dart:32:12) +#11 FlutterProject._readManifest (package:flutter_tools/src/project.dart:163:54) +#12 FlutterProject.fromDirectory (package:flutter_tools/src/project.dart:44:38) +#13 FlutterProject.fromPath (package:flutter_tools/src/project.dart:59:50) +#14 PackagesGetCommand.usageValues (package:flutter_tools/src/commands/packages.dart:80:55) + +#15 FlutterCommand.verifyThenRunCommand (package:flutter_tools/src/runner/flutter_command.dart:484:63) + +#16 FlutterCommand.run. (package:flutter_tools/src/runner/flutter_command.dart:424:33) + +#17 AppContext.run. (package:flutter_tools/src/base/context.dart:153:29) + +#18 _rootRun (dart:async/zone.dart:1124:13) +#19 _CustomZone.run (dart:async/zone.dart:1021:19) +#20 _runZoned (dart:async/zone.dart:1516:10) +#21 runZoned (dart:async/zone.dart:1463:12) +#22 AppContext.run (package:flutter_tools/src/base/context.dart:152:18) + +#23 FlutterCommand.run (package:flutter_tools/src/runner/flutter_command.dart:415:20) +#24 CommandRunner.runCommand (package:args/command_runner.dart:196:27) + +#25 FlutterCommandRunner.runCommand. (package:flutter_tools/src/runner/flutter_command_runner.dart:396:21) + +#26 AppContext.run. (package:flutter_tools/src/base/context.dart:153:29) + +#27 _rootRun (dart:async/zone.dart:1124:13) +#28 _CustomZone.run (dart:async/zone.dart:1021:19) +#29 _runZoned (dart:async/zone.dart:1516:10) +#30 runZoned (dart:async/zone.dart:1463:12) +#31 AppContext.run (package:flutter_tools/src/base/context.dart:152:18) + +#32 FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:356:19) + +#33 CommandRunner.run. (package:args/command_runner.dart:111:29) +#34 new Future.sync (dart:async/future.dart:224:31) +#35 CommandRunner.run (package:args/command_runner.dart:111:11) +#36 FlutterCommandRunner.run (package:flutter_tools/src/runner/flutter_command_runner.dart:242:18) +#37 run. (package:flutter_tools/runner.dart:60:20) + +#38 AppContext.run. (package:flutter_tools/src/base/context.dart:153:29) + +#39 _rootRun (dart:async/zone.dart:1124:13) +#40 _CustomZone.run (dart:async/zone.dart:1021:19) +#41 _runZoned (dart:async/zone.dart:1516:10) +#42 runZoned (dart:async/zone.dart:1463:12) +#43 AppContext.run (package:flutter_tools/src/base/context.dart:152:18) + +#44 runInContext (package:flutter_tools/src/context_runner.dart:54:24) + +#45 run (package:flutter_tools/runner.dart:51:10) +#46 main (package:flutter_tools/executable.dart:62:9) + +#47 main (file:///Users/mjr/flutter/packages/flutter_tools/bin/flutter_tools.dart:8:3) +#48 _startIsolate. (dart:isolate-patch/isolate_patch.dart:298:32) +#49 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:171:12) +``` + +## flutter doctor + +``` +[✓] Flutter (Channel dev, v1.7.0, on Mac OS X 10.14.5 18F132, locale en-US) + • Flutter version 1.7.0 at /Users/mjr/flutter + • Framework revision f36a35d20a (8 days ago), 2019-05-31 15:27:56 -0400 + • Engine revision a32df2c928 + • Dart version 2.3.2 (build 2.3.2-dev.0.0 445a23a9bc) + +[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3) + • Android SDK at /Users/mjr/Library/Android/sdk + • Android NDK location not configured (optional; useful for native profiling support) + • Platform android-28, build-tools 28.0.3 + • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java + • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06) + • All Android licenses accepted. + +[✓] Xcode - develop for iOS and macOS (Xcode 10.2.1) + • Xcode at /Applications/Xcode.app/Contents/Developer + • Xcode 10.2.1, Build version 10E1001 + • CocoaPods version 1.6.1 + +[✓] iOS tools - develop for iOS devices + • ios-deploy 1.9.4 + +[✓] Android Studio (version 3.2) + • Android Studio at /Applications/Android Studio.app/Contents + • Flutter plugin version 28.0.1 + • Dart plugin version 173.4700 + • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06) + +[✓] VS Code (version 1.35.0) + • VS Code at /Applications/Visual Studio Code.app/Contents + • Flutter extension version 3.1.0 + +[✓] Connected device (1 available) + • Michael’s iPhone • 00008020-000858D10281002E • ios • iOS 12.2 + +• No issues found! +``` From 6b344a317fbd0be4a70df97614ed8a324d4cfd88 Mon Sep 17 00:00:00 2001 From: micimize Date: Mon, 10 Jun 2019 12:05:29 -0500 Subject: [PATCH 5/5] refactor(client): fix typos and make _eagerlyResolveQuery's name consistent --- .../lib/src/core/observable_query.dart | 8 +- .../graphql/lib/src/core/query_manager.dart | 6 +- packages/graphql_flutter/flutter_01.log | 122 ------------------ 3 files changed, 7 insertions(+), 129 deletions(-) delete mode 100644 packages/graphql_flutter/flutter_01.log diff --git a/packages/graphql/lib/src/core/observable_query.dart b/packages/graphql/lib/src/core/observable_query.dart index a01036066..e792e652a 100644 --- a/packages/graphql/lib/src/core/observable_query.dart +++ b/packages/graphql/lib/src/core/observable_query.dart @@ -27,7 +27,7 @@ class ObservableQuery { @required this.options, }) : queryId = queryManager.generateQueryId().toString() { if (options.eagerlyFetchResults) { - _lastestWasEagerlyFetched = true; + _latestWasEagerlyFetched = true; fetchResults(); } controller = StreamController.broadcast( @@ -36,7 +36,7 @@ class ObservableQuery { } // set to true when eagerly fetched to prevent back-to-back queries - bool _lastestWasEagerlyFetched = false; + bool _latestWasEagerlyFetched = false; final String queryId; final QueryManager queryManager; @@ -102,8 +102,8 @@ class ObservableQuery { } void onListen() { - if (_lastestWasEagerlyFetched) { - _lastestWasEagerlyFetched = false; + if (_latestWasEagerlyFetched) { + _latestWasEagerlyFetched = false; return; } if (options.fetchResults) { diff --git a/packages/graphql/lib/src/core/query_manager.dart b/packages/graphql/lib/src/core/query_manager.dart index 964624fb1..c006b0bd1 100644 --- a/packages/graphql/lib/src/core/query_manager.dart +++ b/packages/graphql/lib/src/core/query_manager.dart @@ -75,12 +75,12 @@ class QueryManager { String queryId, BaseOptions options, ) { - final QueryResult eagerResult = _eagerlyResolveQuery( + final QueryResult eagerResult = _resolveQueryEagerly( queryId, options, ); - // _eagerlyResolveQuery handles cacheOnly, + // _resolveQueryEagerly handles cacheOnly, // so if we're loading + cacheFirst we continue to network return MultiSourceResult( eagerResult: eagerResult, @@ -155,7 +155,7 @@ class QueryManager { /// Add an eager cache response to the stream if possible, /// based on `fetchPolicy` and `optimisticResults` - QueryResult _eagerlyResolveQuery( + QueryResult _resolveQueryEagerly( String queryId, BaseOptions options, ) { diff --git a/packages/graphql_flutter/flutter_01.log b/packages/graphql_flutter/flutter_01.log deleted file mode 100644 index 33c80668f..000000000 --- a/packages/graphql_flutter/flutter_01.log +++ /dev/null @@ -1,122 +0,0 @@ -Flutter crash report; please file at https://github.com/flutter/flutter/issues. - -## command - -flutter packages get - -## exception - -YamlException: Error on line 13, column 3: Duplicate mapping key. - ╷ -13 │ graphql: - │ ^^^^^^^ - ╵ - -``` -#0 Loader._loadMapping (package:yaml/src/loader.dart:167:9) -#1 Loader._loadNode (package:yaml/src/loader.dart:86:16) -#2 Loader._loadMapping (package:yaml/src/loader.dart:165:19) -#3 Loader._loadNode (package:yaml/src/loader.dart:86:16) -#4 Loader._loadDocument (package:yaml/src/loader.dart:62:20) -#5 Loader.load (package:yaml/src/loader.dart:54:20) -#6 loadYamlDocument (package:yaml/yaml.dart:51:25) -#7 loadYamlNode (package:yaml/yaml.dart:42:5) -#8 loadYaml (package:yaml/yaml.dart:34:5) -#9 FlutterManifest.createFromString (package:flutter_tools/src/flutter_manifest.dart:38:28) -#10 FlutterManifest.createFromPath (package:flutter_tools/src/flutter_manifest.dart:32:12) -#11 FlutterProject._readManifest (package:flutter_tools/src/project.dart:163:54) -#12 FlutterProject.fromDirectory (package:flutter_tools/src/project.dart:44:38) -#13 FlutterProject.fromPath (package:flutter_tools/src/project.dart:59:50) -#14 PackagesGetCommand.usageValues (package:flutter_tools/src/commands/packages.dart:80:55) - -#15 FlutterCommand.verifyThenRunCommand (package:flutter_tools/src/runner/flutter_command.dart:484:63) - -#16 FlutterCommand.run. (package:flutter_tools/src/runner/flutter_command.dart:424:33) - -#17 AppContext.run. (package:flutter_tools/src/base/context.dart:153:29) - -#18 _rootRun (dart:async/zone.dart:1124:13) -#19 _CustomZone.run (dart:async/zone.dart:1021:19) -#20 _runZoned (dart:async/zone.dart:1516:10) -#21 runZoned (dart:async/zone.dart:1463:12) -#22 AppContext.run (package:flutter_tools/src/base/context.dart:152:18) - -#23 FlutterCommand.run (package:flutter_tools/src/runner/flutter_command.dart:415:20) -#24 CommandRunner.runCommand (package:args/command_runner.dart:196:27) - -#25 FlutterCommandRunner.runCommand. (package:flutter_tools/src/runner/flutter_command_runner.dart:396:21) - -#26 AppContext.run. (package:flutter_tools/src/base/context.dart:153:29) - -#27 _rootRun (dart:async/zone.dart:1124:13) -#28 _CustomZone.run (dart:async/zone.dart:1021:19) -#29 _runZoned (dart:async/zone.dart:1516:10) -#30 runZoned (dart:async/zone.dart:1463:12) -#31 AppContext.run (package:flutter_tools/src/base/context.dart:152:18) - -#32 FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:356:19) - -#33 CommandRunner.run. (package:args/command_runner.dart:111:29) -#34 new Future.sync (dart:async/future.dart:224:31) -#35 CommandRunner.run (package:args/command_runner.dart:111:11) -#36 FlutterCommandRunner.run (package:flutter_tools/src/runner/flutter_command_runner.dart:242:18) -#37 run. (package:flutter_tools/runner.dart:60:20) - -#38 AppContext.run. (package:flutter_tools/src/base/context.dart:153:29) - -#39 _rootRun (dart:async/zone.dart:1124:13) -#40 _CustomZone.run (dart:async/zone.dart:1021:19) -#41 _runZoned (dart:async/zone.dart:1516:10) -#42 runZoned (dart:async/zone.dart:1463:12) -#43 AppContext.run (package:flutter_tools/src/base/context.dart:152:18) - -#44 runInContext (package:flutter_tools/src/context_runner.dart:54:24) - -#45 run (package:flutter_tools/runner.dart:51:10) -#46 main (package:flutter_tools/executable.dart:62:9) - -#47 main (file:///Users/mjr/flutter/packages/flutter_tools/bin/flutter_tools.dart:8:3) -#48 _startIsolate. (dart:isolate-patch/isolate_patch.dart:298:32) -#49 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:171:12) -``` - -## flutter doctor - -``` -[✓] Flutter (Channel dev, v1.7.0, on Mac OS X 10.14.5 18F132, locale en-US) - • Flutter version 1.7.0 at /Users/mjr/flutter - • Framework revision f36a35d20a (8 days ago), 2019-05-31 15:27:56 -0400 - • Engine revision a32df2c928 - • Dart version 2.3.2 (build 2.3.2-dev.0.0 445a23a9bc) - -[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3) - • Android SDK at /Users/mjr/Library/Android/sdk - • Android NDK location not configured (optional; useful for native profiling support) - • Platform android-28, build-tools 28.0.3 - • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java - • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06) - • All Android licenses accepted. - -[✓] Xcode - develop for iOS and macOS (Xcode 10.2.1) - • Xcode at /Applications/Xcode.app/Contents/Developer - • Xcode 10.2.1, Build version 10E1001 - • CocoaPods version 1.6.1 - -[✓] iOS tools - develop for iOS devices - • ios-deploy 1.9.4 - -[✓] Android Studio (version 3.2) - • Android Studio at /Applications/Android Studio.app/Contents - • Flutter plugin version 28.0.1 - • Dart plugin version 173.4700 - • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1136-b06) - -[✓] VS Code (version 1.35.0) - • VS Code at /Applications/Visual Studio Code.app/Contents - • Flutter extension version 3.1.0 - -[✓] Connected device (1 available) - • Michael’s iPhone • 00008020-000858D10281002E • ios • iOS 12.2 - -• No issues found! -```