22
22
import org .apache .flink .connector .testframe .container .FlinkContainers ;
23
23
import org .apache .flink .connector .testframe .container .FlinkContainersSettings ;
24
24
import org .apache .flink .connector .testframe .container .TestcontainersSettings ;
25
+ import org .apache .flink .streaming .api .environment .ExecutionCheckpointingOptions ;
25
26
import org .apache .flink .test .resources .ResourceTestUtils ;
26
27
import org .apache .flink .test .util .SQLJobSubmission ;
27
28
28
29
import com .mongodb .client .MongoClient ;
29
30
import com .mongodb .client .MongoClients ;
31
+ import com .mongodb .client .MongoCollection ;
30
32
import com .mongodb .client .MongoDatabase ;
33
+ import com .mongodb .client .model .Filters ;
34
+ import com .mongodb .client .model .Updates ;
31
35
import org .bson .Document ;
32
36
import org .bson .types .ObjectId ;
33
37
import org .junit .jupiter .api .AfterAll ;
47
51
import java .nio .file .Paths ;
48
52
import java .time .Duration ;
49
53
import java .util .ArrayList ;
54
+ import java .util .Arrays ;
50
55
import java .util .List ;
51
56
import java .util .stream .Collectors ;
52
57
53
58
import static org .apache .flink .connector .mongodb .testutils .MongoTestUtil .MONGODB_HOSTNAME ;
54
59
import static org .apache .flink .connector .mongodb .testutils .MongoTestUtil .MONGO_4_0 ;
60
+ import static org .apache .flink .connector .mongodb .testutils .MongoTestUtil .MONGO_IMAGE_PREFIX ;
55
61
import static org .assertj .core .api .Assertions .assertThat ;
56
62
57
63
/** End-to-end test for the MongoDB connectors. */
@@ -65,11 +71,11 @@ class MongoE2ECase {
65
71
private static final Path SQL_CONNECTOR_MONGODB_JAR =
66
72
ResourceTestUtils .getResource (".*mongodb.jar" );
67
73
68
- private static final int TEST_ORDERS_COUNT = 5 ;
74
+ private static final int TEST_ORDERS_INITIAL_COUNT = 5 ;
69
75
70
76
@ Container
71
77
static final MongoDBContainer MONGO_CONTAINER =
72
- new MongoDBContainer (MONGO_4_0 )
78
+ new MongoDBContainer (MONGO_IMAGE_PREFIX + MONGO_4_0 )
73
79
.withLogConsumer (new Slf4jLogConsumer (LOG ))
74
80
.withNetwork (NETWORK )
75
81
.withNetworkAliases (MONGODB_HOSTNAME );
@@ -85,7 +91,12 @@ class MongoE2ECase {
85
91
public static final FlinkContainers FLINK =
86
92
FlinkContainers .builder ()
87
93
.withFlinkContainersSettings (
88
- FlinkContainersSettings .builder ().numTaskManagers (2 ).build ())
94
+ FlinkContainersSettings .builder ()
95
+ .setConfigOption (
96
+ ExecutionCheckpointingOptions .CHECKPOINTING_INTERVAL ,
97
+ Duration .ofSeconds (1 ))
98
+ .numTaskManagers (2 )
99
+ .build ())
89
100
.withTestcontainersSettings (TESTCONTAINERS_SETTINGS )
90
101
.build ();
91
102
@@ -107,12 +118,12 @@ static void teardown() {
107
118
public void testUpsertSink () throws Exception {
108
119
MongoDatabase db = mongoClient .getDatabase ("test_upsert" );
109
120
110
- List <Document > orders = mockOrders ();
121
+ List <Document > orders = generateOrders ();
111
122
db .getCollection ("orders" ).insertMany (orders );
112
123
113
124
executeSqlStatements (readSqlFile ("e2e_upsert.sql" ));
114
125
115
- List <Document > ordersBackup = readAllBackupOrders (db );
126
+ List <Document > ordersBackup = readAllBackupOrders (db , orders . size () );
116
127
117
128
assertThat (ordersBackup ).containsExactlyInAnyOrderElementsOf (orders );
118
129
}
@@ -121,43 +132,88 @@ public void testUpsertSink() throws Exception {
121
132
public void testAppendOnlySink () throws Exception {
122
133
MongoDatabase db = mongoClient .getDatabase ("test_append_only" );
123
134
124
- List <Document > orders = mockOrders ();
135
+ List <Document > orders = generateOrders ();
125
136
db .getCollection ("orders" ).insertMany (orders );
126
137
127
138
executeSqlStatements (readSqlFile ("e2e_append_only.sql" ));
128
139
129
- List <Document > ordersBackup = readAllBackupOrders (db );
140
+ List <Document > ordersBackup = readAllBackupOrders (db , orders . size () );
130
141
131
142
List <Document > expected = removeIdField (orders );
132
143
assertThat (removeIdField (ordersBackup )).containsExactlyInAnyOrderElementsOf (expected );
133
144
}
134
145
135
- private static List <Document > readAllBackupOrders (MongoDatabase db ) throws Exception {
136
- Deadline deadline = Deadline .fromNow (Duration .ofSeconds (20 ));
137
- List <Document > backupOrders ;
138
- do {
139
- Thread .sleep (1000 );
140
- backupOrders = db .getCollection ("orders_bak" ).find ().into (new ArrayList <>());
141
- } while (deadline .hasTimeLeft () && backupOrders .size () < TEST_ORDERS_COUNT );
146
+ @ Test
147
+ public void testUnboundedSink () throws Exception {
148
+ MongoDatabase db = mongoClient .getDatabase ("test_unbounded" );
149
+ MongoCollection <Document > coll = db .getCollection ("orders" );
150
+
151
+ List <Document > orders = generateOrders ();
152
+ coll .insertMany (orders );
153
+
154
+ executeSqlStatements (readSqlFile ("e2e_unbounded.sql" ));
155
+
156
+ // -- scan records --
157
+ List <Document > ordersBackup = readAllBackupOrders (db , orders .size ());
158
+ assertThat (ordersBackup ).containsExactlyInAnyOrderElementsOf (orders );
159
+
160
+ // -- stream records --
161
+ // insert 3 records
162
+ List <Document > newOrders =
163
+ Arrays .asList (generateOrder (6 ), generateOrder (7 ), generateOrder (8 ));
164
+ coll .insertMany (newOrders );
165
+ orders .addAll (newOrders );
166
+
167
+ // assert inserted
168
+ ordersBackup = readAllBackupOrders (db , orders .size ());
169
+ assertThat (ordersBackup ).containsExactlyInAnyOrderElementsOf (orders );
142
170
143
- return backupOrders ;
171
+ // update 1 record
172
+ Document updateOrder = orders .get (0 );
173
+ coll .updateOne (Filters .eq ("_id" , updateOrder .get ("_id" )), Updates .set ("quantity" , 1000L ));
174
+
175
+ // replace 1 record
176
+ Document replacement = Document .parse (orders .get (1 ).toJson ());
177
+ replacement .put ("quantity" , 1001L );
178
+ coll .replaceOne (Filters .eq ("_id" , replacement .remove ("_id" )), replacement );
179
+
180
+ // asert updated
181
+ ordersBackup = readAllBackupOrders (db , orders .size ());
182
+ assertThat (ordersBackup ).containsExactlyInAnyOrderElementsOf (orders );
183
+ }
184
+
185
+ private static List <Document > readAllBackupOrders (MongoDatabase db , int expectSize )
186
+ throws Exception {
187
+ Deadline deadline = Deadline .fromNow (Duration .ofSeconds (30 ));
188
+ MongoCollection <Document > coll = db .getCollection ("orders_bak" );
189
+ while (deadline .hasTimeLeft ()) {
190
+ if (coll .countDocuments () < expectSize ) {
191
+ Thread .sleep (1000L );
192
+ } else {
193
+ break ;
194
+ }
195
+ }
196
+ return coll .find ().into (new ArrayList <>());
144
197
}
145
198
146
199
private static List <Document > removeIdField (List <Document > documents ) {
147
200
return documents .stream ().peek (doc -> doc .remove ("_id" )).collect (Collectors .toList ());
148
201
}
149
202
150
- private static List <Document > mockOrders () {
203
+ private static List <Document > generateOrders () {
151
204
List <Document > orders = new ArrayList <>();
152
- for (int i = 1 ; i <= TEST_ORDERS_COUNT ; i ++) {
153
- orders .add (
154
- new Document ("_id" , new ObjectId ())
155
- .append ("code" , "ORDER_" + i )
156
- .append ("quantity" , i * 10L ));
205
+ for (int i = 1 ; i <= TEST_ORDERS_INITIAL_COUNT ; i ++) {
206
+ orders .add (generateOrder (i ));
157
207
}
158
208
return orders ;
159
209
}
160
210
211
+ private static Document generateOrder (int index ) {
212
+ return new Document ("_id" , new ObjectId ())
213
+ .append ("code" , "ORDER_" + index )
214
+ .append ("quantity" , index * 10L );
215
+ }
216
+
161
217
private static List <String > readSqlFile (final String resourceName ) throws Exception {
162
218
return Files .readAllLines (
163
219
Paths .get (MongoE2ECase .class .getResource ("/" + resourceName ).toURI ()));
0 commit comments