Skip to content

Commit 2bc5bf5

Browse files
committed
Avoid no-op field fetch adapter allocation
The default field-fetching bridge still has to support legacy beginFieldFetch implementations, but the inherited no-op path should not allocate a per-field adapter. Return the canonical field-fetching no-op when the legacy hook returns the canonical no-op context, while still adapting real legacy contexts.
1 parent db82feb commit 2bc5bf5

2 files changed

Lines changed: 75 additions & 0 deletions

File tree

src/main/java/graphql/execution/instrumentation/Instrumentation.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ default InstrumentationContext<Object> beginFieldFetch(InstrumentationFieldFetch
241241
@Nullable
242242
default FieldFetchingInstrumentationContext beginFieldFetching(InstrumentationFieldFetchParameters parameters, InstrumentationState state) {
243243
InstrumentationContext<Object> ctx = beginFieldFetch(parameters, state);
244+
if (ctx == noOp()) {
245+
return FieldFetchingInstrumentationContext.NOOP;
246+
}
244247
return FieldFetchingInstrumentationContext.adapter(ctx);
245248
}
246249

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package graphql.execution.instrumentation
2+
3+
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters
4+
import spock.lang.Specification
5+
6+
class FieldFetchingInstrumentationContextTest extends Specification {
7+
8+
def "default begin field fetching does not allocate an adapter for inherited no-op"() {
9+
given:
10+
def instrumentation = new Instrumentation() {}
11+
12+
when:
13+
def context = instrumentation.beginFieldFetching(null, null)
14+
15+
then:
16+
context.is(FieldFetchingInstrumentationContext.NOOP)
17+
}
18+
19+
def "simple performant instrumentation begin field fetching does not allocate an adapter for inherited no-op"() {
20+
when:
21+
def context = SimplePerformantInstrumentation.INSTANCE.beginFieldFetching(null, null)
22+
23+
then:
24+
context.is(FieldFetchingInstrumentationContext.NOOP)
25+
}
26+
27+
def "default begin field fetching does not allocate an adapter when deprecated override returns no-op"() {
28+
given:
29+
def instrumentation = new Instrumentation() {
30+
@Override
31+
InstrumentationContext<Object> beginFieldFetch(InstrumentationFieldFetchParameters parameters, InstrumentationState state) {
32+
return SimpleInstrumentationContext.noOp()
33+
}
34+
}
35+
36+
when:
37+
def context = instrumentation.beginFieldFetching(null, null)
38+
39+
then:
40+
context.is(FieldFetchingInstrumentationContext.NOOP)
41+
}
42+
43+
def "default begin field fetching still adapts deprecated begin field fetch overrides"() {
44+
given:
45+
def events = []
46+
def instrumentation = new Instrumentation() {
47+
@Override
48+
InstrumentationContext<Object> beginFieldFetch(InstrumentationFieldFetchParameters parameters, InstrumentationState state) {
49+
return new InstrumentationContext<Object>() {
50+
@Override
51+
void onDispatched() {
52+
events.add("dispatched")
53+
}
54+
55+
@Override
56+
void onCompleted(Object result, Throwable t) {
57+
events.add(result)
58+
}
59+
}
60+
}
61+
}
62+
63+
when:
64+
def context = instrumentation.beginFieldFetching(null, null)
65+
context.onDispatched()
66+
context.onFetchedValue("ignored")
67+
context.onCompleted("completed", null)
68+
69+
then:
70+
events == ["dispatched", "completed"]
71+
}
72+
}

0 commit comments

Comments
 (0)