1+ package org .dataloader .instrumentation ;
2+
3+ import org .dataloader .BatchLoaderEnvironment ;
4+ import org .dataloader .DataLoader ;
5+ import org .dataloader .DataLoaderFactory ;
6+ import org .dataloader .DataLoaderOptions ;
7+ import org .dataloader .DispatchResult ;
8+ import org .dataloader .fixtures .TestKit ;
9+ import org .dataloader .fixtures .parameterized .TestDataLoaderFactory ;
10+ import org .junit .jupiter .api .Test ;
11+ import org .junit .jupiter .params .ParameterizedTest ;
12+ import org .junit .jupiter .params .provider .MethodSource ;
13+
14+ import java .util .ArrayList ;
15+ import java .util .List ;
16+ import java .util .concurrent .CompletableFuture ;
17+
18+ import static org .awaitility .Awaitility .await ;
19+ import static org .dataloader .DataLoaderOptions .newOptions ;
20+ import static org .hamcrest .MatcherAssert .assertThat ;
21+ import static org .hamcrest .Matchers .equalTo ;
22+
23+ class ChainedDataLoaderInstrumentationTest {
24+
25+ static class CapturingInstrumentation implements DataLoaderInstrumentation {
26+ String name ;
27+ List <String > methods = new ArrayList <>();
28+
29+ public CapturingInstrumentation (String name ) {
30+ this .name = name ;
31+ }
32+
33+ @ Override
34+ public DataLoaderInstrumentationContext <DispatchResult <?>> beginDispatch (DataLoader <?, ?> dataLoader ) {
35+ methods .add (name + "_beginDispatch" );
36+ return new DataLoaderInstrumentationContext <>() {
37+ @ Override
38+ public void onDispatched () {
39+ methods .add (name + "_beginDispatch_onDispatched" );
40+ }
41+
42+ @ Override
43+ public void onCompleted (DispatchResult <?> result , Throwable t ) {
44+ methods .add (name + "_beginDispatch_onCompleted" );
45+ }
46+ };
47+ }
48+
49+ @ Override
50+ public DataLoaderInstrumentationContext <List <?>> beginBatchLoader (DataLoader <?, ?> dataLoader , List <?> keys , BatchLoaderEnvironment environment ) {
51+ methods .add (name + "_beginBatchLoader" );
52+ return new DataLoaderInstrumentationContext <>() {
53+ @ Override
54+ public void onDispatched () {
55+ methods .add (name + "_beginBatchLoader_onDispatched" );
56+ }
57+
58+ @ Override
59+ public void onCompleted (List <?> result , Throwable t ) {
60+ methods .add (name + "_beginBatchLoader_onCompleted" );
61+ }
62+ };
63+ }
64+ }
65+
66+
67+ static class CapturingInstrumentationReturnsNull extends CapturingInstrumentation {
68+
69+ public CapturingInstrumentationReturnsNull (String name ) {
70+ super (name );
71+ }
72+
73+ @ Override
74+ public DataLoaderInstrumentationContext <DispatchResult <?>> beginDispatch (DataLoader <?, ?> dataLoader ) {
75+ methods .add (name + "_beginDispatch" );
76+ return null ;
77+ }
78+
79+ @ Override
80+ public DataLoaderInstrumentationContext <List <?>> beginBatchLoader (DataLoader <?, ?> dataLoader , List <?> keys , BatchLoaderEnvironment environment ) {
81+ methods .add (name + "_beginBatchLoader" );
82+ return null ;
83+ }
84+ }
85+
86+ @ Test
87+ void canChainTogetherZeroInstrumentation () {
88+ // just to prove its useless but harmless
89+ ChainedDataLoaderInstrumentation chainedItn = new ChainedDataLoaderInstrumentation ();
90+
91+ DataLoaderOptions options = newOptions ().setInstrumentation (chainedItn );
92+
93+ DataLoader <String , String > dl = DataLoaderFactory .newDataLoader (TestKit .keysAsValues (), options );
94+
95+ dl .load ("A" );
96+ dl .load ("B" );
97+
98+ CompletableFuture <List <String >> dispatch = dl .dispatch ();
99+
100+ await ().until (dispatch ::isDone );
101+ assertThat (dispatch .join (), equalTo (List .of ("A" , "B" )));
102+ }
103+
104+ @ Test
105+ void canChainTogetherOneInstrumentation () {
106+ CapturingInstrumentation capturingA = new CapturingInstrumentation ("A" );
107+
108+ ChainedDataLoaderInstrumentation chainedItn = new ChainedDataLoaderInstrumentation ()
109+ .add (capturingA );
110+
111+ DataLoaderOptions options = newOptions ().setInstrumentation (chainedItn );
112+
113+ DataLoader <String , String > dl = DataLoaderFactory .newDataLoader (TestKit .keysAsValues (), options );
114+
115+ dl .load ("A" );
116+ dl .load ("B" );
117+
118+ CompletableFuture <List <String >> dispatch = dl .dispatch ();
119+
120+ await ().until (dispatch ::isDone );
121+
122+ assertThat (capturingA .methods , equalTo (List .of ("A_beginDispatch" ,
123+ "A_beginBatchLoader" , "A_beginBatchLoader_onDispatched" , "A_beginBatchLoader_onCompleted" ,
124+ "A_beginDispatch_onDispatched" , "A_beginDispatch_onCompleted" )));
125+ }
126+
127+
128+ @ ParameterizedTest
129+ @ MethodSource ("org.dataloader.fixtures.parameterized.TestDataLoaderFactories#get" )
130+ public void canChainTogetherManyInstrumentationsWithDifferentBatchLoaders (TestDataLoaderFactory factory ) {
131+ CapturingInstrumentation capturingA = new CapturingInstrumentation ("A" );
132+ CapturingInstrumentation capturingB = new CapturingInstrumentation ("B" );
133+ CapturingInstrumentation capturingButReturnsNull = new CapturingInstrumentationReturnsNull ("NULL" );
134+
135+ ChainedDataLoaderInstrumentation chainedItn = new ChainedDataLoaderInstrumentation ()
136+ .add (capturingA )
137+ .add (capturingB )
138+ .add (capturingButReturnsNull );
139+
140+ DataLoaderOptions options = newOptions ().setInstrumentation (chainedItn );
141+
142+ DataLoader <String , String > dl = factory .idLoader (options );
143+
144+ dl .load ("A" );
145+ dl .load ("B" );
146+
147+ CompletableFuture <List <String >> dispatch = dl .dispatch ();
148+
149+ await ().until (dispatch ::isDone );
150+
151+ //
152+ // A_beginBatchLoader happens before A_beginDispatch_onDispatched because these are sync
153+ // and no async - a batch scheduler or async batch loader would change that
154+ //
155+ assertThat (capturingA .methods , equalTo (List .of ("A_beginDispatch" ,
156+ "A_beginBatchLoader" , "A_beginBatchLoader_onDispatched" , "A_beginBatchLoader_onCompleted" ,
157+ "A_beginDispatch_onDispatched" , "A_beginDispatch_onCompleted" )));
158+
159+ assertThat (capturingB .methods , equalTo (List .of ("B_beginDispatch" ,
160+ "B_beginBatchLoader" , "B_beginBatchLoader_onDispatched" , "B_beginBatchLoader_onCompleted" ,
161+ "B_beginDispatch_onDispatched" , "B_beginDispatch_onCompleted" )));
162+
163+ // it returned null on all its contexts - nothing to call back on
164+ assertThat (capturingButReturnsNull .methods , equalTo (List .of ("NULL_beginDispatch" , "NULL_beginBatchLoader" )));
165+ }
166+ }
0 commit comments