Skip to content

Commit acd2411

Browse files
committed
Improve schema OSGi whiteboard update performance by batching
Allow the ability to delay the update of the schema through a config option. By default this is 0, leaving the behaviour unchanged, and no penalty is paid. If the delay is set to a non zero value, it only updates the schema if no changes to the whiteboard have happened within that delay timeout. Also fixed up a couple of things with the whiteboard. Using policy=DYNAMIC is the normal approach, the component can activate and gets references added as appropriate. The "typesProviders" method was in error as the name didn't match the unbind. I believe that what was happenning before is that the component was being activated and deactivated each time a new reference was added. Now it's activated once and the whiteboard works correctly.
1 parent 583f855 commit acd2411

File tree

1 file changed

+64
-23
lines changed

1 file changed

+64
-23
lines changed

src/main/java/graphql/servlet/OsgiGraphQLHttpServlet.java

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,29 @@
11
package graphql.servlet;
22

3-
import graphql.execution.instrumentation.ChainedInstrumentation;
4-
import graphql.execution.instrumentation.Instrumentation;
5-
import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentation;
6-
import graphql.execution.preparsed.NoOpPreparsedDocumentProvider;
7-
import graphql.execution.preparsed.PreparsedDocumentProvider;
8-
import graphql.schema.GraphQLObjectType;
9-
import graphql.schema.GraphQLType;
10-
import org.osgi.service.component.annotations.Component;
11-
import org.osgi.service.component.annotations.Reference;
12-
import org.osgi.service.component.annotations.ReferenceCardinality;
13-
import org.osgi.service.component.annotations.ReferencePolicy;
14-
import org.osgi.service.component.annotations.ReferencePolicyOption;
3+
import static graphql.schema.GraphQLObjectType.newObject;
4+
import static graphql.schema.GraphQLSchema.newSchema;
155

166
import java.util.ArrayList;
177
import java.util.HashSet;
188
import java.util.List;
199
import java.util.Set;
10+
import java.util.concurrent.Executors;
11+
import java.util.concurrent.ScheduledExecutorService;
12+
import java.util.concurrent.ScheduledFuture;
13+
import java.util.concurrent.TimeUnit;
2014

21-
import static graphql.schema.GraphQLObjectType.newObject;
22-
import static graphql.schema.GraphQLSchema.newSchema;
15+
import org.osgi.service.component.annotations.Activate;
16+
import org.osgi.service.component.annotations.Component;
17+
import org.osgi.service.component.annotations.Deactivate;
18+
import org.osgi.service.component.annotations.Reference;
19+
import org.osgi.service.component.annotations.ReferenceCardinality;
20+
import org.osgi.service.component.annotations.ReferencePolicy;
21+
import org.osgi.service.component.annotations.ReferencePolicyOption;
22+
23+
import graphql.execution.preparsed.NoOpPreparsedDocumentProvider;
24+
import graphql.execution.preparsed.PreparsedDocumentProvider;
25+
import graphql.schema.GraphQLObjectType;
26+
import graphql.schema.GraphQLType;
2327

2428
@Component(
2529
service={javax.servlet.http.HttpServlet.class,javax.servlet.Servlet.class},
@@ -43,7 +47,27 @@ public class OsgiGraphQLHttpServlet extends AbstractGraphQLHttpServlet {
4347
private PreparsedDocumentProvider preparsedDocumentProvider = NoOpPreparsedDocumentProvider.INSTANCE;
4448

4549
private GraphQLSchemaProvider schemaProvider;
46-
50+
51+
private ScheduledExecutorService executor;
52+
private ScheduledFuture<?> updateFuture;
53+
private int schemaUpdateDelay;
54+
55+
@interface Config {
56+
int schema_update_delay() default 0;
57+
}
58+
59+
@Activate
60+
public void activate(Config config) {
61+
this.schemaUpdateDelay = config.schema_update_delay();
62+
if (schemaUpdateDelay!=0)
63+
executor = Executors.newSingleThreadScheduledExecutor();
64+
}
65+
66+
@Deactivate
67+
public void deactivate() {
68+
if (executor!=null) executor.shutdown();
69+
}
70+
4771
@Override
4872
protected GraphQLQueryInvoker getQueryInvoker() {
4973
return queryInvoker;
@@ -78,6 +102,23 @@ public OsgiGraphQLHttpServlet() {
78102
}
79103

80104
protected void updateSchema() {
105+
if (schemaUpdateDelay==0) {
106+
doUpdateSchema();
107+
}
108+
else {
109+
if (updateFuture!=null)
110+
updateFuture.cancel(true);
111+
112+
updateFuture = executor.schedule(new Runnable() {
113+
@Override
114+
public void run() {
115+
doUpdateSchema();
116+
}
117+
}, schemaUpdateDelay, TimeUnit.MILLISECONDS);
118+
}
119+
}
120+
121+
private void doUpdateSchema() {
81122
final GraphQLObjectType.Builder queryTypeBuilder = newObject().name("Query").description("Root query type");
82123

83124
for (GraphQLQueryProvider provider : queryProviders) {
@@ -108,7 +149,7 @@ protected void updateSchema() {
108149
this.schemaProvider = new DefaultGraphQLSchemaProvider(newSchema().query(queryTypeBuilder.build()).mutation(mutationType).build(types));
109150
}
110151

111-
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policyOption = ReferencePolicyOption.GREEDY)
152+
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
112153
public void bindProvider(GraphQLProvider provider) {
113154
if (provider instanceof GraphQLQueryProvider) {
114155
queryProviders.add((GraphQLQueryProvider) provider);
@@ -134,7 +175,7 @@ public void unbindProvider(GraphQLProvider provider) {
134175
updateSchema();
135176
}
136177

137-
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policyOption = ReferencePolicyOption.GREEDY)
178+
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
138179
public void bindQueryProvider(GraphQLQueryProvider queryProvider) {
139180
queryProviders.add(queryProvider);
140181
updateSchema();
@@ -144,7 +185,7 @@ public void unbindQueryProvider(GraphQLQueryProvider queryProvider) {
144185
updateSchema();
145186
}
146187

147-
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policyOption = ReferencePolicyOption.GREEDY)
188+
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
148189
public void bindMutationProvider(GraphQLMutationProvider mutationProvider) {
149190
mutationProviders.add(mutationProvider);
150191
updateSchema();
@@ -154,8 +195,8 @@ public void unbindMutationProvider(GraphQLMutationProvider mutationProvider) {
154195
updateSchema();
155196
}
156197

157-
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policyOption = ReferencePolicyOption.GREEDY)
158-
public void typesProviders(GraphQLTypesProvider typesProvider) {
198+
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
199+
public void bindTypesProvider(GraphQLTypesProvider typesProvider) {
159200
typesProviders.add(typesProvider);
160201
updateSchema();
161202
}
@@ -164,23 +205,23 @@ public void unbindTypesProvider(GraphQLTypesProvider typesProvider) {
164205
updateSchema();
165206
}
166207

167-
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policyOption = ReferencePolicyOption.GREEDY)
208+
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
168209
public void bindServletListener(GraphQLServletListener listener) {
169210
this.addListener(listener);
170211
}
171212
public void unbindServletListener(GraphQLServletListener listener) {
172213
this.removeListener(listener);
173214
}
174215

175-
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY)
216+
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
176217
public void setContextProvider(GraphQLContextBuilder contextBuilder) {
177218
this.contextBuilder = contextBuilder;
178219
}
179220
public void unsetContextProvider(GraphQLContextBuilder contextBuilder) {
180221
this.contextBuilder = new DefaultGraphQLContextBuilder();
181222
}
182223

183-
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY)
224+
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
184225
public void setRootObjectBuilder(GraphQLRootObjectBuilder rootObjectBuilder) {
185226
this.rootObjectBuilder = rootObjectBuilder;
186227
}

0 commit comments

Comments
 (0)