11package org .dataloader ;
22
33import org .dataloader .annotations .PublicApi ;
4+ import org .dataloader .instrumentation .ChainedDataLoaderInstrumentation ;
5+ import org .dataloader .instrumentation .DataLoaderInstrumentation ;
6+ import org .dataloader .instrumentation .DataLoaderInstrumentationHelper ;
47import org .dataloader .stats .Statistics ;
58
69import java .util .ArrayList ;
2124@ PublicApi
2225public class DataLoaderRegistry {
2326 protected final Map <String , DataLoader <?, ?>> dataLoaders = new ConcurrentHashMap <>();
27+ protected final DataLoaderInstrumentation instrumentation ;
28+
2429
2530 public DataLoaderRegistry () {
31+ instrumentation = null ;
2632 }
2733
2834 private DataLoaderRegistry (Builder builder ) {
29- this .dataLoaders .putAll (builder .dataLoaders );
35+ instrument (builder .instrumentation , builder .dataLoaders );
36+ this .instrumentation = builder .instrumentation ;
37+ }
38+
39+ private void instrument (DataLoaderInstrumentation registryInstrumentation , Map <String , DataLoader <?, ?>> incomingDataLoaders ) {
40+ this .dataLoaders .putAll (incomingDataLoaders );
41+ if (registryInstrumentation != null ) {
42+ this .dataLoaders .replaceAll ((k , existingDL ) -> instrumentDL (registryInstrumentation , existingDL ));
43+ }
44+ }
45+
46+ /**
47+ * Can be called to tweak a {@link DataLoader} so that it has the registry {@link DataLoaderInstrumentation} added as the first one.
48+ *
49+ * @param registryInstrumentation the common registry {@link DataLoaderInstrumentation}
50+ * @param existingDL the existing data loader
51+ * @return a new {@link DataLoader} or the same one if there is nothing to change
52+ */
53+ private static DataLoader <?, ?> instrumentDL (DataLoaderInstrumentation registryInstrumentation , DataLoader <?, ?> existingDL ) {
54+ if (registryInstrumentation == null ) {
55+ return existingDL ;
56+ }
57+ DataLoaderOptions options = existingDL .getOptions ();
58+ DataLoaderInstrumentation existingInstrumentation = options .getInstrumentation ();
59+ // if they have any instrumentations then add to it
60+ if (existingInstrumentation != null ) {
61+ if (existingInstrumentation == registryInstrumentation ) {
62+ // nothing to change
63+ return existingDL ;
64+ }
65+ if (existingInstrumentation == DataLoaderInstrumentationHelper .NOOP_INSTRUMENTATION ) {
66+ // replace it with the registry one
67+ return mkInstrumentedDataLoader (existingDL , options , registryInstrumentation );
68+ }
69+ if (existingInstrumentation instanceof ChainedDataLoaderInstrumentation ) {
70+ // avoids calling a chained inside a chained
71+ DataLoaderInstrumentation newInstrumentation = ((ChainedDataLoaderInstrumentation ) existingInstrumentation ).prepend (registryInstrumentation );
72+ return mkInstrumentedDataLoader (existingDL , options , newInstrumentation );
73+ } else {
74+ DataLoaderInstrumentation newInstrumentation = new ChainedDataLoaderInstrumentation ().add (registryInstrumentation ).add (existingInstrumentation );
75+ return mkInstrumentedDataLoader (existingDL , options , newInstrumentation );
76+ }
77+ } else {
78+ return mkInstrumentedDataLoader (existingDL , options , registryInstrumentation );
79+ }
80+ }
81+
82+ private static DataLoader <?, ?> mkInstrumentedDataLoader (DataLoader <?, ?> existingDL , DataLoaderOptions options , DataLoaderInstrumentation newInstrumentation ) {
83+ return existingDL .transform (builder -> {
84+ options .setInstrumentation (newInstrumentation );
85+ builder .options (options );
86+ });
3087 }
3188
89+ public DataLoaderInstrumentation getInstrumentation () {
90+ return instrumentation ;
91+ }
3292
3393 /**
3494 * This will register a new dataloader
3595 *
3696 * @param key the key to put the data loader under
3797 * @param dataLoader the data loader to register
38- *
3998 * @return this registry
4099 */
41100 public DataLoaderRegistry register (String key , DataLoader <?, ?> dataLoader ) {
42- dataLoaders .put (key , dataLoader );
101+ dataLoaders .put (key , instrumentDL ( instrumentation , dataLoader ) );
43102 return this ;
44103 }
45104
@@ -54,21 +113,22 @@ public DataLoaderRegistry register(String key, DataLoader<?, ?> dataLoader) {
54113 * @param mappingFunction the function to compute a data loader
55114 * @param <K> the type of keys
56115 * @param <V> the type of values
57- *
58116 * @return a data loader
59117 */
60118 @ SuppressWarnings ("unchecked" )
61119 public <K , V > DataLoader <K , V > computeIfAbsent (final String key ,
62120 final Function <String , DataLoader <?, ?>> mappingFunction ) {
63- return (DataLoader <K , V >) dataLoaders .computeIfAbsent (key , mappingFunction );
121+ return (DataLoader <K , V >) dataLoaders .computeIfAbsent (key , (k ) -> {
122+ DataLoader <?, ?> dl = mappingFunction .apply (k );
123+ return instrumentDL (instrumentation , dl );
124+ });
64125 }
65126
66127 /**
67128 * This will combine all the current data loaders in this registry and all the data loaders from the specified registry
68129 * and return a new combined registry
69130 *
70131 * @param registry the registry to combine into this registry
71- *
72132 * @return a new combined registry
73133 */
74134 public DataLoaderRegistry combine (DataLoaderRegistry registry ) {
@@ -97,7 +157,6 @@ public DataLoaderRegistry combine(DataLoaderRegistry registry) {
97157 * This will unregister a new dataloader
98158 *
99159 * @param key the key of the data loader to unregister
100- *
101160 * @return this registry
102161 */
103162 public DataLoaderRegistry unregister (String key ) {
@@ -111,7 +170,6 @@ public DataLoaderRegistry unregister(String key) {
111170 * @param key the key of the data loader
112171 * @param <K> the type of keys
113172 * @param <V> the type of values
114- *
115173 * @return a data loader or null if its not present
116174 */
117175 @ SuppressWarnings ("unchecked" )
@@ -182,13 +240,13 @@ public static Builder newRegistry() {
182240 public static class Builder {
183241
184242 private final Map <String , DataLoader <?, ?>> dataLoaders = new HashMap <>();
243+ private DataLoaderInstrumentation instrumentation ;
185244
186245 /**
187246 * This will register a new dataloader
188247 *
189248 * @param key the key to put the data loader under
190249 * @param dataLoader the data loader to register
191- *
192250 * @return this builder for a fluent pattern
193251 */
194252 public Builder register (String key , DataLoader <?, ?> dataLoader ) {
@@ -201,14 +259,18 @@ public Builder register(String key, DataLoader<?, ?> dataLoader) {
201259 * from a previous {@link DataLoaderRegistry}
202260 *
203261 * @param otherRegistry the previous {@link DataLoaderRegistry}
204- *
205262 * @return this builder for a fluent pattern
206263 */
207264 public Builder registerAll (DataLoaderRegistry otherRegistry ) {
208265 dataLoaders .putAll (otherRegistry .dataLoaders );
209266 return this ;
210267 }
211268
269+ public Builder instrumentation (DataLoaderInstrumentation instrumentation ) {
270+ this .instrumentation = instrumentation ;
271+ return this ;
272+ }
273+
212274 /**
213275 * @return the newly built {@link DataLoaderRegistry}
214276 */
0 commit comments