Skip to content

Commit b88fa9f

Browse files
authored
feat(graphql): make timeout configurable in query options (zino-hofmann#1475)
1 parent 3628544 commit b88fa9f

File tree

5 files changed

+43
-3
lines changed

5 files changed

+43
-3
lines changed

packages/graphql/lib/src/core/_base_options.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ abstract class BaseOptions<TParsed extends Object?> {
2323
ErrorPolicy? errorPolicy,
2424
CacheRereadPolicy? cacheRereadPolicy,
2525
this.optimisticResult,
26+
this.queryRequestTimeout,
2627
}) : policies = Policies(
2728
fetch: fetchPolicy,
2829
error: errorPolicy,
@@ -60,6 +61,9 @@ abstract class BaseOptions<TParsed extends Object?> {
6061

6162
final ResultParserFn<TParsed> parserFn;
6263

64+
/// Override default query timeout
65+
final Duration? queryRequestTimeout;
66+
6367
// TODO consider inverting this relationship
6468
/// Resolve these options into a request
6569
Request get asRequest => Request(
@@ -80,6 +84,7 @@ abstract class BaseOptions<TParsed extends Object?> {
8084
policies,
8185
context,
8286
parserFn,
87+
queryRequestTimeout,
8388
];
8489

8590
OperationType get type {

packages/graphql/lib/src/core/mutation_options.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class MutationOptions<TParsed extends Object?> extends BaseOptions<TParsed> {
3030
this.update,
3131
this.onError,
3232
ResultParserFn<TParsed>? parserFn,
33+
Duration? queryRequestTimeout,
3334
}) : super(
3435
fetchPolicy: fetchPolicy,
3536
errorPolicy: errorPolicy,
@@ -40,6 +41,7 @@ class MutationOptions<TParsed extends Object?> extends BaseOptions<TParsed> {
4041
context: context,
4142
optimisticResult: optimisticResult,
4243
parserFn: parserFn,
44+
queryRequestTimeout: queryRequestTimeout,
4345
);
4446

4547
final OnMutationCompleted? onCompleted;
@@ -68,6 +70,7 @@ class MutationOptions<TParsed extends Object?> extends BaseOptions<TParsed> {
6870
update: update,
6971
onError: onError,
7072
parserFn: parserFn,
73+
queryRequestTimeout: queryRequestTimeout,
7174
);
7275

7376
WatchQueryOptions<TParsed> asWatchQueryOptions() =>
@@ -81,6 +84,7 @@ class MutationOptions<TParsed extends Object?> extends BaseOptions<TParsed> {
8184
fetchResults: false,
8285
context: context,
8386
parserFn: parserFn,
87+
queryRequestTimeout: queryRequestTimeout,
8488
);
8589
}
8690

packages/graphql/lib/src/core/query_manager.dart

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class QueryManager {
5353
final bool alwaysRebroadcast;
5454

5555
/// The timeout for resolving a query
56-
final Duration requestTimeout;
56+
final Duration? requestTimeout;
5757

5858
QueryScheduler? scheduler;
5959
static final _oneOffOpId = '0';
@@ -260,7 +260,16 @@ class QueryManager {
260260

261261
try {
262262
// execute the request through the provided link(s)
263-
response = await link.request(request).timeout(this.requestTimeout).first;
263+
Stream<Response> responseStream = link.request(request);
264+
265+
// Resolve the request timeout by first checking the options of this specific request,
266+
// then the manager level requestTimeout.
267+
// Only apply the timeout if it is non-null.
268+
final timeout = options.queryRequestTimeout ?? this.requestTimeout;
269+
if (timeout case final Duration timeout) {
270+
responseStream = responseStream.timeout(timeout);
271+
}
272+
response = await responseStream.first;
264273

265274
queryResult = mapFetchResultToQueryResult(
266275
response,

packages/graphql/lib/src/core/query_options.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class QueryOptions<TParsed extends Object?> extends BaseOptions<TParsed> {
2727
this.pollInterval,
2828
Context? context,
2929
ResultParserFn<TParsed>? parserFn,
30+
Duration? queryRequestTimeout,
3031
this.onComplete,
3132
this.onError,
3233
}) : super(
@@ -39,6 +40,7 @@ class QueryOptions<TParsed extends Object?> extends BaseOptions<TParsed> {
3940
context: context,
4041
optimisticResult: optimisticResult,
4142
parserFn: parserFn,
43+
queryRequestTimeout: queryRequestTimeout,
4244
);
4345

4446
final OnQueryComplete? onComplete;
@@ -68,6 +70,7 @@ class QueryOptions<TParsed extends Object?> extends BaseOptions<TParsed> {
6870
Duration? pollInterval,
6971
Context? context,
7072
ResultParserFn<TParsed>? parserFn,
73+
Duration? queryRequestTimeout,
7174
OnQueryComplete? onComplete,
7275
OnQueryError? onError,
7376
}) =>
@@ -82,6 +85,7 @@ class QueryOptions<TParsed extends Object?> extends BaseOptions<TParsed> {
8285
pollInterval: pollInterval ?? this.pollInterval,
8386
context: context ?? this.context,
8487
parserFn: parserFn ?? this.parserFn,
88+
queryRequestTimeout: queryRequestTimeout ?? this.queryRequestTimeout,
8589
onComplete: onComplete ?? this.onComplete,
8690
onError: onError ?? this.onError,
8791
);
@@ -95,6 +99,7 @@ class QueryOptions<TParsed extends Object?> extends BaseOptions<TParsed> {
9599
fetchPolicy: FetchPolicy.noCache,
96100
errorPolicy: errorPolicy,
97101
parserFn: parserFn,
102+
queryRequestTimeout: queryRequestTimeout,
98103
context: context,
99104
variables: {
100105
...variables,
@@ -115,6 +120,7 @@ class QueryOptions<TParsed extends Object?> extends BaseOptions<TParsed> {
115120
context: context,
116121
optimisticResult: optimisticResult,
117122
parserFn: parserFn,
123+
queryRequestTimeout: queryRequestTimeout,
118124
);
119125

120126
QueryOptions<TParsed> copyWithPolicies(Policies policies) => QueryOptions(
@@ -128,6 +134,7 @@ class QueryOptions<TParsed extends Object?> extends BaseOptions<TParsed> {
128134
pollInterval: pollInterval,
129135
context: context,
130136
parserFn: parserFn,
137+
queryRequestTimeout: queryRequestTimeout,
131138
);
132139
}
133140

@@ -144,6 +151,7 @@ class SubscriptionOptions<TParsed extends Object?>
144151
Object? optimisticResult,
145152
Context? context,
146153
ResultParserFn<TParsed>? parserFn,
154+
Duration? queryRequestTimeout,
147155
}) : super(
148156
fetchPolicy: fetchPolicy,
149157
errorPolicy: errorPolicy,
@@ -154,6 +162,7 @@ class SubscriptionOptions<TParsed extends Object?>
154162
context: context,
155163
optimisticResult: optimisticResult,
156164
parserFn: parserFn,
165+
queryRequestTimeout: queryRequestTimeout,
157166
);
158167
SubscriptionOptions<TParsed> copyWithPolicies(Policies policies) =>
159168
SubscriptionOptions(
@@ -166,6 +175,7 @@ class SubscriptionOptions<TParsed extends Object?>
166175
optimisticResult: optimisticResult,
167176
context: context,
168177
parserFn: parserFn,
178+
queryRequestTimeout: queryRequestTimeout,
169179
);
170180
}
171181

@@ -185,6 +195,7 @@ class WatchQueryOptions<TParsed extends Object?> extends QueryOptions<TParsed> {
185195
bool? eagerlyFetchResults,
186196
Context? context,
187197
ResultParserFn<TParsed>? parserFn,
198+
Duration? queryRequestTimeout,
188199
}) : eagerlyFetchResults = eagerlyFetchResults ?? fetchResults,
189200
super(
190201
document: document,
@@ -197,6 +208,7 @@ class WatchQueryOptions<TParsed extends Object?> extends QueryOptions<TParsed> {
197208
context: context,
198209
optimisticResult: optimisticResult,
199210
parserFn: parserFn,
211+
queryRequestTimeout: queryRequestTimeout,
200212
);
201213

202214
/// Whether or not to fetch results every time a new listener is added.
@@ -237,6 +249,7 @@ class WatchQueryOptions<TParsed extends Object?> extends QueryOptions<TParsed> {
237249
bool? eagerlyFetchResults,
238250
Context? context,
239251
ResultParserFn<TParsed>? parserFn,
252+
Duration? queryRequestTimeout,
240253
}) =>
241254
WatchQueryOptions<TParsed>(
242255
document: document ?? this.document,
@@ -253,6 +266,7 @@ class WatchQueryOptions<TParsed extends Object?> extends QueryOptions<TParsed> {
253266
carryForwardDataOnException ?? this.carryForwardDataOnException,
254267
context: context ?? this.context,
255268
parserFn: parserFn ?? this.parserFn,
269+
queryRequestTimeout: queryRequestTimeout ?? this.queryRequestTimeout,
256270
);
257271

258272
WatchQueryOptions<TParsed> copyWithFetchPolicy(
@@ -272,6 +286,7 @@ class WatchQueryOptions<TParsed extends Object?> extends QueryOptions<TParsed> {
272286
carryForwardDataOnException: carryForwardDataOnException,
273287
context: context,
274288
parserFn: parserFn,
289+
queryRequestTimeout: queryRequestTimeout,
275290
);
276291
WatchQueryOptions<TParsed> copyWithPolicies(
277292
Policies policies,
@@ -290,6 +305,7 @@ class WatchQueryOptions<TParsed extends Object?> extends QueryOptions<TParsed> {
290305
carryForwardDataOnException: carryForwardDataOnException,
291306
context: context,
292307
parserFn: parserFn,
308+
queryRequestTimeout: queryRequestTimeout,
293309
);
294310

295311
WatchQueryOptions<TParsed> copyWithPollInterval(Duration? pollInterval) =>
@@ -307,6 +323,7 @@ class WatchQueryOptions<TParsed extends Object?> extends QueryOptions<TParsed> {
307323
carryForwardDataOnException: carryForwardDataOnException,
308324
context: context,
309325
parserFn: parserFn,
326+
queryRequestTimeout: queryRequestTimeout,
310327
);
311328

312329
WatchQueryOptions<TParsed> copyWithVariables(
@@ -325,6 +342,7 @@ class WatchQueryOptions<TParsed extends Object?> extends QueryOptions<TParsed> {
325342
carryForwardDataOnException: carryForwardDataOnException,
326343
context: context,
327344
parserFn: parserFn,
345+
queryRequestTimeout: queryRequestTimeout,
328346
);
329347

330348
WatchQueryOptions<TParsed> copyWithOptimisticResult(
@@ -343,6 +361,7 @@ class WatchQueryOptions<TParsed extends Object?> extends QueryOptions<TParsed> {
343361
carryForwardDataOnException: carryForwardDataOnException,
344362
context: context,
345363
parserFn: parserFn,
364+
queryRequestTimeout: queryRequestTimeout,
346365
);
347366
}
348367

@@ -358,6 +377,7 @@ class FetchMoreOptions {
358377
this.document,
359378
this.variables = const {},
360379
required this.updateQuery,
380+
Duration? queryRequestTimeout,
361381
});
362382

363383
/// Automatically merge the results of [updateQuery] into `previousResultData`.
@@ -369,11 +389,13 @@ class FetchMoreOptions {
369389
DocumentNode? document,
370390
Map<String, dynamic> variables = const {},
371391
required UpdateQuery updateQuery,
392+
Duration? queryRequestTimeout,
372393
}) =>
373394
FetchMoreOptions(
374395
document: document,
375396
variables: variables,
376397
updateQuery: partialUpdater(updateQuery),
398+
queryRequestTimeout: queryRequestTimeout,
377399
);
378400

379401
final DocumentNode? document;

packages/graphql/lib/src/graphql_client.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class GraphQLClient implements GraphQLDataProxy {
2828
bool alwaysRebroadcast = false,
2929
DeepEqualsFn? deepEquals,
3030
bool deduplicatePollers = false,
31-
Duration queryRequestTimeout = const Duration(seconds: 5),
31+
Duration? queryRequestTimeout = const Duration(seconds: 5),
3232
}) : defaultPolicies = defaultPolicies ?? DefaultPolicies(),
3333
queryManager = QueryManager(
3434
link: link,

0 commit comments

Comments
 (0)