@@ -37,6 +37,9 @@ class DefaultTransferProcessRunnerTest {
3737 private static final String PATIENT_IDENTIFIER_2 = "patient-142391" ;
3838 private static final ConsentedPatient PATIENT_2 =
3939 new ConsentedPatient (PATIENT_IDENTIFIER_2 , "system" );
40+ private static final String PATIENT_IDENTIFIER_3 = "patient-293847" ;
41+ private static final ConsentedPatient PATIENT_3 =
42+ new ConsentedPatient (PATIENT_IDENTIFIER_3 , "system" );
4043
4144 private DefaultTransferProcessRunner runner ;
4245
@@ -168,9 +171,9 @@ void ttl() throws InterruptedException {
168171
169172 create (runner .statuses ())
170173 .assertNext (
171- r -> {
172- assertThat (r .size ()).isEqualTo (0 );
173- } )
174+ r ->
175+ assertThat (r .size ()).isEqualTo (0 )
176+ )
174177 .verifyComplete ();
175178 }
176179
@@ -180,7 +183,7 @@ void errorInDataSelectorSkipsBundleAndContinues() {
180183 new TransferProcessDefinition (
181184 "test" ,
182185 rawConfig ,
183- pids -> fromIterable (List .of (PATIENT , PATIENT_2 )),
186+ pids -> fromIterable (List .of (PATIENT , PATIENT_2 , PATIENT_3 )),
184187 errorOnSecond (new Bundle ()),
185188 b -> just (new TransportBundle (new Bundle (), "transferId" )),
186189 b -> just (new Result ()));
@@ -195,12 +198,12 @@ private static DataSelector errorOnSecond(Bundle bundle) {
195198 var first = new AtomicBoolean (true );
196199 return p ->
197200 first .getAndSet (false )
198- ? Flux .error ( new RuntimeException ( "Cannot select data" ))
199- : Flux .just ( bundle ). map ( b -> new ConsentedPatientBundle ( b , p ));
201+ ? Flux .just ( bundle ). map ( b -> new ConsentedPatientBundle ( b , p ))
202+ : Flux .error ( new RuntimeException ( "Cannot select data" ));
200203 }
201204
202205 private void completedWithErrors (TransferProcessStatus r ) {
203- assertThat (r .sentBundles ()).isEqualTo (1 );
206+ assertThat (r .sentBundles ()).isEqualTo (2 );
204207 assertThat (r .skippedBundles ()).isEqualTo (1 );
205208 assertThat (r .phase ()).isEqualTo (Phase .COMPLETED_WITH_ERROR );
206209 }
@@ -211,7 +214,7 @@ void errorInDeidentificatorSkipsBundleAndContinues() {
211214 new TransferProcessDefinition (
212215 "test" ,
213216 rawConfig ,
214- pids -> fromIterable (List .of (PATIENT , PATIENT_2 )),
217+ pids -> fromIterable (List .of (PATIENT , PATIENT_2 , PATIENT_3 )),
215218 p -> fromIterable (List .of (new ConsentedPatientBundle (new Bundle (), p ))),
216219 errorOnSecond (new TransportBundle (new Bundle (), "transferId" )),
217220 b -> just (new Result ()));
@@ -224,7 +227,7 @@ void errorInDeidentificatorSkipsBundleAndContinues() {
224227
225228 private static Deidentificator errorOnSecond (TransportBundle bundle ) {
226229 var first = new AtomicBoolean (true );
227- return b ->
230+ return p ->
228231 first .getAndSet (false )
229232 ? just (bundle )
230233 : Mono .error (new RuntimeException ("Cannot deidentify bundle" ));
@@ -236,7 +239,7 @@ void errorInBundleSenderSkipsBundleAndContinues() {
236239 new TransferProcessDefinition (
237240 "test" ,
238241 rawConfig ,
239- pids -> fromIterable (List .of (PATIENT , DefaultTransferProcessRunnerTest . PATIENT_2 )),
242+ pids -> fromIterable (List .of (PATIENT , PATIENT_2 , PATIENT_3 )),
240243 p -> fromIterable (List .of (new ConsentedPatientBundle (new Bundle (), p ))),
241244 b -> just (new TransportBundle (new Bundle (), "transferId" )),
242245 errorOnSecond (new Result ()));
@@ -249,12 +252,112 @@ void errorInBundleSenderSkipsBundleAndContinues() {
249252
250253 private static BundleSender errorOnSecond (Result result ) {
251254 var first = new AtomicBoolean (true );
252- return b ->
255+ return p ->
253256 first .getAndSet (false )
254257 ? just (result )
255258 : Mono .error (new RuntimeException ("Cannot send bundle" ));
256259 }
257260
261+ @ Test
262+ void errorInDataSelectorRecordsFailedPatient () {
263+ var process =
264+ new TransferProcessDefinition (
265+ "test" ,
266+ rawConfig ,
267+ pids -> fromIterable (List .of (PATIENT , PATIENT_2 , PATIENT_3 )),
268+ errorOnSecond (new Bundle ()),
269+ b -> just (new TransportBundle (new Bundle (), "transferId" )),
270+ b -> just (new Result ()));
271+
272+ var processId = runner .start (process , List .of ());
273+ waitForCompletion (processId );
274+
275+ create (runner .status (processId ))
276+ .assertNext (
277+ r -> {
278+ assertThat (r .phase ()).isEqualTo (Phase .COMPLETED_WITH_ERROR );
279+ assertThat (r .sentBundles ()).isEqualTo (2 );
280+ assertThat (r .failedPatients ()).hasSize (1 );
281+ assertThat (r .failedPatients ().getFirst ().patientId ()).isEqualTo (PATIENT_IDENTIFIER_2 );
282+ assertThat (r .failedPatients ().getFirst ().errorMessage ())
283+ .isEqualTo ("Cannot select data" );
284+ })
285+ .verifyComplete ();
286+ }
287+
288+ @ Test
289+ void errorInDeidentificatorRecordsFailedPatient () {
290+ var process =
291+ new TransferProcessDefinition (
292+ "test" ,
293+ rawConfig ,
294+ pids -> fromIterable (List .of (PATIENT , PATIENT_2 , PATIENT_3 )),
295+ p -> fromIterable (List .of (new ConsentedPatientBundle (new Bundle (), p ))),
296+ errorOnSecond (new TransportBundle (new Bundle (), "transferId" )),
297+ b -> just (new Result ()));
298+
299+ var processId = runner .start (process , List .of ());
300+ waitForCompletion (processId );
301+
302+ create (runner .status (processId ))
303+ .assertNext (
304+ r -> {
305+ assertThat (r .phase ()).isEqualTo (Phase .COMPLETED_WITH_ERROR );
306+ assertThat (r .sentBundles ()).isEqualTo (2 );
307+ assertThat (r .failedPatients ()).hasSize (1 );
308+ assertThat (r .failedPatients ().getFirst ().errorMessage ())
309+ .isEqualTo ("Cannot deidentify bundle" );
310+ })
311+ .verifyComplete ();
312+ }
313+
314+ @ Test
315+ void errorInBundleSenderRecordsFailedPatient () {
316+ var process =
317+ new TransferProcessDefinition (
318+ "test" ,
319+ rawConfig ,
320+ pids -> fromIterable (List .of (PATIENT , PATIENT_2 , PATIENT_3 )),
321+ p -> fromIterable (List .of (new ConsentedPatientBundle (new Bundle (), p ))),
322+ b -> just (new TransportBundle (new Bundle (), "transferId" )),
323+ errorOnSecond (new Result ()));
324+
325+ var processId = runner .start (process , List .of ());
326+ waitForCompletion (processId );
327+
328+ create (runner .status (processId ))
329+ .assertNext (
330+ r -> {
331+ assertThat (r .phase ()).isEqualTo (Phase .COMPLETED_WITH_ERROR );
332+ assertThat (r .sentBundles ()).isEqualTo (2 );
333+ assertThat (r .failedPatients ()).hasSize (1 );
334+ assertThat (r .failedPatients ().getFirst ().errorMessage ())
335+ .isEqualTo ("Cannot send bundle" );
336+ })
337+ .verifyComplete ();
338+ }
339+
340+ @ Test
341+ void successfulTransferHasNoFailedPatients () {
342+ var process =
343+ new TransferProcessDefinition (
344+ "test" ,
345+ rawConfig ,
346+ pids -> fromIterable (List .of (PATIENT )),
347+ p -> fromIterable (List .of (new ConsentedPatientBundle (new Bundle (), PATIENT ))),
348+ b -> just (new TransportBundle (new Bundle (), "transferId" )),
349+ b -> just (new Result ()));
350+
351+ var processId = runner .start (process , List .of ());
352+ create (runner .status (processId ))
353+ .assertNext (
354+ r -> {
355+ assertThat (r .phase ()).isEqualTo (Phase .COMPLETED );
356+ assertThat (r .failedPatients ()).isEmpty ();
357+ })
358+ .verifyComplete ();
359+ }
360+
258361 @ Test
259362 void logErrorIncludesExceptionWhenDebugEnabled () {
260363 var event = runWithLogLevel (Level .DEBUG );
0 commit comments