2222import org .apache .flink .api .common .functions .RichMapFunction ;
2323import org .apache .flink .api .common .typeinfo .BasicTypeInfo ;
2424import org .apache .flink .api .common .typeinfo .TypeInformation ;
25+ import org .apache .flink .api .common .typeutils .TypeSerializer ;
2526import org .apache .flink .api .common .typeutils .base .IntSerializer ;
2627import org .apache .flink .api .java .Utils ;
28+ import org .apache .flink .api .java .tuple .Tuple1 ;
2729import org .apache .flink .api .java .typeutils .TypeExtractor ;
30+ import org .apache .flink .api .java .typeutils .runtime .TupleSerializer ;
2831import org .apache .flink .configuration .Configuration ;
2932import org .apache .flink .core .testutils .OneShotLatch ;
3033import org .apache .flink .runtime .checkpoint .CheckpointMetaData ;
100103public class AsyncWaitOperatorTest extends TestLogger {
101104 private static final long TIMEOUT = 1000L ;
102105
103- @ Rule public Timeout timeoutRule = new Timeout (10 , TimeUnit .SECONDS );
106+ @ Rule public Timeout timeoutRule = new Timeout (100 , TimeUnit .SECONDS );
104107
105- private static class MyAsyncFunction extends RichAsyncFunction <Integer , Integer > {
108+ private abstract static class MyAbstractAsyncFunction <IN >
109+ extends RichAsyncFunction <IN , Integer > {
106110 private static final long serialVersionUID = 8522411971886428444L ;
107111
108112 private static final long TERMINATION_TIMEOUT = 5000L ;
@@ -115,7 +119,7 @@ private static class MyAsyncFunction extends RichAsyncFunction<Integer, Integer>
115119 public void open (Configuration parameters ) throws Exception {
116120 super .open (parameters );
117121
118- synchronized (MyAsyncFunction .class ) {
122+ synchronized (MyAbstractAsyncFunction .class ) {
119123 if (counter == 0 ) {
120124 executorService = Executors .newFixedThreadPool (THREAD_POOL_SIZE );
121125 }
@@ -132,7 +136,7 @@ public void close() throws Exception {
132136 }
133137
134138 private void freeExecutor () {
135- synchronized (MyAsyncFunction .class ) {
139+ synchronized (MyAbstractAsyncFunction .class ) {
136140 --counter ;
137141
138142 if (counter == 0 ) {
@@ -151,6 +155,10 @@ private void freeExecutor() {
151155 }
152156 }
153157 }
158+ }
159+
160+ private static class MyAsyncFunction extends MyAbstractAsyncFunction <Integer > {
161+ private static final long serialVersionUID = -1504699677704123889L ;
154162
155163 @ Override
156164 public void asyncInvoke (final Integer input , final ResultFuture <Integer > resultFuture )
@@ -183,7 +191,7 @@ public LazyAsyncFunction() {
183191 @ Override
184192 public void asyncInvoke (final Integer input , final ResultFuture <Integer > resultFuture )
185193 throws Exception {
186- this . executorService .submit (
194+ executorService .submit (
187195 new Runnable () {
188196 @ Override
189197 public void run () {
@@ -203,6 +211,23 @@ public static void countDown() {
203211 }
204212 }
205213
214+ private static class InputReusedAsyncFunction extends MyAbstractAsyncFunction <Tuple1 <Integer >> {
215+
216+ private static final long serialVersionUID = 8627909616410487720L ;
217+
218+ @ Override
219+ public void asyncInvoke (Tuple1 <Integer > input , ResultFuture <Integer > resultFuture )
220+ throws Exception {
221+ executorService .submit (
222+ new Runnable () {
223+ @ Override
224+ public void run () {
225+ resultFuture .complete (Collections .singletonList (input .f0 * 2 ));
226+ }
227+ });
228+ }
229+ }
230+
206231 /**
207232 * A special {@link LazyAsyncFunction} for timeout handling. Complete the result future with 3
208233 * times the input when the timeout occurred.
@@ -596,6 +621,67 @@ public void testStateSnapshotAndRestore() throws Exception {
596621 restoredTaskHarness .getOutput ());
597622 }
598623
624+ @ SuppressWarnings ("rawtypes" )
625+ @ Test
626+ public void testStateSnapshotAndRestoreWithObjectReused () throws Exception {
627+ TypeSerializer [] fieldSerializers = new TypeSerializer [] {IntSerializer .INSTANCE };
628+ TupleSerializer <Tuple1 > inputSerializer =
629+ new TupleSerializer <>(Tuple1 .class , fieldSerializers );
630+ AsyncWaitOperatorFactory <Tuple1 <Integer >, Integer > factory =
631+ new AsyncWaitOperatorFactory <>(
632+ new InputReusedAsyncFunction (),
633+ TIMEOUT ,
634+ 4 ,
635+ AsyncDataStream .OutputMode .ORDERED );
636+
637+ //noinspection unchecked
638+ final OneInputStreamOperatorTestHarness <Tuple1 <Integer >, Integer > testHarness =
639+ new OneInputStreamOperatorTestHarness (factory , inputSerializer );
640+ // enable object reuse
641+ testHarness .getExecutionConfig ().enableObjectReuse ();
642+
643+ final long initialTime = 0L ;
644+ Tuple1 <Integer > reusedTuple = new Tuple1 <>();
645+ StreamRecord <Tuple1 <Integer >> reusedRecord = new StreamRecord <>(reusedTuple , -1L );
646+
647+ testHarness .setup ();
648+ testHarness .open ();
649+
650+ synchronized (testHarness .getCheckpointLock ()) {
651+ reusedTuple .setFields (1 );
652+ reusedRecord .setTimestamp (initialTime + 1 );
653+ testHarness .processElement (reusedRecord );
654+
655+ reusedTuple .setFields (2 );
656+ reusedRecord .setTimestamp (initialTime + 2 );
657+ testHarness .processElement (reusedRecord );
658+
659+ reusedTuple .setFields (3 );
660+ reusedRecord .setTimestamp (initialTime + 3 );
661+ testHarness .processElement (reusedRecord );
662+
663+ reusedTuple .setFields (4 );
664+ reusedRecord .setTimestamp (initialTime + 4 );
665+ testHarness .processElement (reusedRecord );
666+ }
667+
668+ ConcurrentLinkedQueue <Object > expectedOutput = new ConcurrentLinkedQueue <>();
669+ expectedOutput .add (new StreamRecord <>(2 , initialTime + 1 ));
670+ expectedOutput .add (new StreamRecord <>(4 , initialTime + 2 ));
671+ expectedOutput .add (new StreamRecord <>(6 , initialTime + 3 ));
672+ expectedOutput .add (new StreamRecord <>(8 , initialTime + 4 ));
673+
674+ synchronized (testHarness .getCheckpointLock ()) {
675+ testHarness .endInput ();
676+ testHarness .close ();
677+ }
678+
679+ TestHarnessUtil .assertOutputEquals (
680+ "StateAndRestoredWithObjectReuse Test Output was not correct." ,
681+ expectedOutput ,
682+ testHarness .getOutput ());
683+ }
684+
599685 @ Test
600686 public void testAsyncTimeoutFailure () throws Exception {
601687 testAsyncTimeout (
0 commit comments