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