Skip to content

Commit

Permalink
feat(dedupe_link): Add shouldDedupe option (#429)
Browse files Browse the repository at this point in the history
  • Loading branch information
nhannah authored Nov 18, 2023
1 parent f137f62 commit 47f443a
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 3 deletions.
15 changes: 12 additions & 3 deletions links/gql_dedupe_link/lib/gql_dedupe_link.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,32 @@ import "package:gql_link/gql_link.dart";

/// A [Link] to deduplicate [Request]s
class DedupeLink extends Link {
final bool Function(Request request) _shouldDedupe;
final Map<Request, StreamSplitter<Response>> _inFlight = {};

static bool _defaultShouldDedupe(Request request) => true;

DedupeLink({
bool Function(Request request) shouldDedupe = _defaultShouldDedupe,
}) : _shouldDedupe = shouldDedupe;

@override
Stream<Response> request(
Request request, [
NextLink? forward,
]) {
if (_inFlight.containsKey(request)) {
final shouldDedupe = _shouldDedupe(request);

if (shouldDedupe && _inFlight.containsKey(request)) {
return _inFlight[request]!.split();
}

final splitter = StreamSplitter(forward!(request));

_inFlight[request] = splitter;
if (shouldDedupe) _inFlight[request] = splitter;

final closeSplitter = () {
_inFlight.remove(request);
if (shouldDedupe) _inFlight.remove(request);

splitter.close();
};
Expand Down
71 changes: 71 additions & 0 deletions links/gql_dedupe_link/test/gql_dedupe_link_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "dart:async";

import "package:gql/ast.dart";
import "package:gql/language.dart";
import "package:gql_dedupe_link/gql_dedupe_link.dart";
import "package:gql_exec/gql_exec.dart";
Expand Down Expand Up @@ -184,6 +185,76 @@ void main() {
expect(await return2, result1);
});

test(
"does not dedupe identical queries if shouldDedupe is false for request",
() async {
var count = 0;
final document = parseString(
"""
query withVar(\$i: Int) {
take(i: \$i)
}
""",
);

final req1 = Request(
operation: Operation(
document: document,
),
variables: const <String, dynamic>{"i": 12},
);

final mockLink = MockLink();

when(
mockLink.request(req1, null),
).thenAnswer((_) {
count++;
return Stream.fromIterable([
Response(
data: <String, dynamic>{"a": count},
response: <String, dynamic>{
"data": <String, dynamic>{"a": count}
},
)
]);
});

final link = Link.from([
DedupeLink(
shouldDedupe: (req) =>
req.operation.getOperationType() != OperationType.query,
),
mockLink,
]);

final stream1 = link.request(req1);
final stream2 = link.request(req1);

final return1 = stream1.first;
final return2 = stream2.first;

verify(
mockLink.request(req1, null),
).called(2);
expect(
await return1,
Response(
data: const <String, dynamic>{"a": 1},
response: const <String, dynamic>{
"data": <String, dynamic>{"a": 1}
},
));
expect(
await return2,
Response(
data: const <String, dynamic>{"a": 2},
response: const <String, dynamic>{
"data": <String, dynamic>{"a": 2}
},
));
});

test("does not dedup consequtive queries", () async {
final document = parseString(
"""
Expand Down

0 comments on commit 47f443a

Please sign in to comment.