Skip to content

Commit 40b0ade

Browse files
committed
test(batch): drain after hangup
1 parent 0d8c268 commit 40b0ade

1 file changed

Lines changed: 58 additions & 16 deletions

File tree

src/test/java/io/weaviate/client6/v1/api/collections/batch/BatchContextTest.java

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.junit.After;
2222
import org.junit.AfterClass;
2323
import org.junit.Before;
24-
import org.junit.Ignore;
2524
import org.junit.Test;
2625

2726
import io.grpc.stub.StreamObserver;
@@ -40,10 +39,14 @@ public class BatchContextTest {
4039
Optional.of(ConsistencyLevel.ONE), Optional.of("john_doe"));
4140

4241
/**
43-
* Dedicated executor for emitting events
44-
* while the context is shutting down.
42+
* Dedicated executor for occasional asynchrony.
4543
*
46-
* @see BatchContext#close()
44+
* <p>
45+
* Most of the time the "server", the "user", the "test" processes
46+
* will run on the main thread, one at a time, when the logic permits.
47+
* In some cases it is useful to put at least one of those processes
48+
* onto a separate thread. E.g. when the batch is being drained, but
49+
* the main thread is blocked by {@link BatchContext#close}.
4750
*/
4851
private static final ExecutorService EXEC = Executors.newSingleThreadExecutor();
4952

@@ -141,7 +144,7 @@ public void test_drainOnClose() throws Exception {
141144
// Contrary the test above, we expect the objects to be sent
142145
// only after context.close(), as the half-empty batch will
143146
// be drained. Similarly, we want to ack everything as it arrives.
144-
Future<?> mockServer = EXEC.submit(() -> {
147+
Future<?> backgroundAcks = EXEC.submit(() -> {
145148
try {
146149
List<String> received = ack();
147150
Assertions.assertThat(tasks)
@@ -156,7 +159,7 @@ public void test_drainOnClose() throws Exception {
156159
});
157160

158161
context.close();
159-
mockServer.get(); // Wait for the "mock server" to process the data message.
162+
backgroundAcks.get(); // Wait for the "mock server" to process the data message.
160163

161164
Assertions.assertThat(tasks).extracting(TaskHandle::result)
162165
.allMatch(CompletableFuture::isDone)
@@ -172,8 +175,7 @@ public void test_backoff() throws Exception {
172175
server.emitEvent(new Event.Backoff(BATCH_SIZE / 2));
173176

174177
List<TaskHandle> tasks = new ArrayList<>();
175-
ExecutorService exec = Executors.newSingleThreadExecutor();
176-
Future<?> testUser = exec.submit(() -> {
178+
Future<?> backgroundAdd = EXEC.submit(() -> {
177179
try {
178180
for (int i = 0; i < BATCH_SIZE; i++) {
179181
tasks.add(context.add(WeaviateObject.of()));
@@ -189,7 +191,7 @@ public void test_backoff() throws Exception {
189191
Assertions.assertThat(received).hasSize(BATCH_SIZE / 2);
190192
server.emitEvent(new Event.Results(received, Collections.emptyMap()));
191193

192-
testUser.get(); // Finish populating batch context.
194+
backgroundAdd.get(); // Finish populating batch context.
193195

194196
// Since testUser will try and add BATCH_SIZE no. objects,
195197
// we should expect there to be exactly 2 batches.
@@ -222,7 +224,7 @@ public void test_backoffBacklog() throws Exception {
222224
server.emitEvent(new Event.Backoff(batchSizeNew));
223225

224226
// The next item will go on the backlog and the trigger a flush,
225-
// which will continue to send batches and re-populate the from
227+
// which will continue to send batches and re-populate from
226228
// the backlog as long as the batch is full, so we should expect
227229
// to see 2 batches of size BATCH_SIZE / 2 each.
228230
List<String> received;
@@ -320,25 +322,65 @@ public void test_reconnect_onStreamHangup() throws Exception {
320322
ack();
321323
}
322324

323-
@Ignore
324325
@Test
325326
public void test_reconnect_DrainAfterStreamHangup() throws Exception {
326327
server.expectMessage(WeaviateProtoBatch.BatchStreamRequest.MessageCase.START);
327328
server.emitEvent(Event.STARTED);
328329

330+
List<TaskHandle> tasks = new ArrayList<>();
331+
329332
// Trigger a flush.
330333
for (int i = 0; i < BATCH_SIZE; i++) {
331-
context.add(WeaviateObject.of());
334+
tasks.add(context.add(WeaviateObject.of()));
332335
}
333336

334-
// Expect a new batch to arrive. Hangup the stream before sending the Acks.
335-
server.expectMessage(WeaviateProtoBatch.BatchStreamRequest.MessageCase.DATA);
337+
// Expect a new batch to arrive. Ack the batch, and trigger another flush.
338+
ack();
339+
for (int i = 0; i < BATCH_SIZE; i++) {
340+
tasks.add(context.add(WeaviateObject.of()));
341+
}
342+
343+
// Ack the latest batch, but now Before sending back the results
344+
// for either one, hang up the stream.
345+
ack();
336346
server.hangup();
337347

348+
// On hangup, client should re-populate the batch from the WIP buffer.
349+
// Add one more item to trigger the flush.
350+
tasks.add(context.add(WeaviateObject.of()));
351+
338352
// The client should try to reconnect, because the context is still open.
353+
// Once the server starts accepting connections again, the client will
354+
// flush the 2 full batches and pause, waiting for the next event.
339355
server.expectMessage(WeaviateProtoBatch.BatchStreamRequest.MessageCase.START);
340356
server.emitEvent(Event.STARTED);
341357

358+
List<String> ids = ack();
359+
server.emitEvent(new Event.Results(ids, Collections.emptyMap()));
360+
361+
ids = ack();
362+
server.emitEvent(new Event.Results(ids, Collections.emptyMap()));
363+
364+
// There is now 1 item remaining in the batch.
365+
// On context close, the client will drain it.
366+
Future<?> backgroundAcks = EXEC.submit(() -> {
367+
try {
368+
List<String> id = ack();
369+
Assertions.assertThat(id).as("drained item").hasSize(1);
370+
Future<?> applied = server.emitEvent(new Event.Results(id, Collections.emptyMap()));
371+
// applied.get();
372+
} catch (Exception e) {
373+
throw new RuntimeException(e);
374+
}
375+
});
376+
377+
context.close();
378+
backgroundAcks.get();
379+
380+
Assertions.assertThat(tasks).extracting(TaskHandle::result)
381+
.allMatch(CompletableFuture::isDone)
382+
.extracting(CompletableFuture::get).extracting(TaskHandle.Result::error)
383+
.allMatch(Optional::isEmpty);
342384
}
343385

344386
@Test
@@ -429,12 +471,12 @@ WeaviateProtoBatch.BatchStreamRequest recv() throws InterruptedException {
429471
return requestQueue.take();
430472
}
431473

432-
void emitEvent(Event event) {
474+
Future<?> emitEvent(Event event) {
433475
if (event == Event.EOF) {
434476
assert Thread.currentThread() != TEST_THREAD : "test MUST NOT close/terminate the the stream";
435477
}
436478

437-
eventExecutor.execute(() -> {
479+
return eventExecutor.submit(() -> {
438480
System.out.println("emit " + event);
439481
if (event == Event.EOF) {
440482
eventStream.onCompleted();

0 commit comments

Comments
 (0)