Skip to content

Commit 453f62a

Browse files
committed
feat(batch): make default batch size and queue size configurable
1 parent 7e2ca54 commit 453f62a

2 files changed

Lines changed: 117 additions & 22 deletions

File tree

src/main/java/io/weaviate/client6/v1/api/collections/batch/BatchContext.java

Lines changed: 93 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import io.weaviate.client6.v1.api.collections.batch.Event.StreamHangup;
3838
import io.weaviate.client6.v1.api.collections.data.BatchReference;
3939
import io.weaviate.client6.v1.api.collections.data.InsertManyRequest;
40+
import io.weaviate.client6.v1.internal.ObjectBuilder;
4041
import io.weaviate.client6.v1.internal.orm.CollectionDescriptor;
4142

4243
/**
@@ -52,9 +53,7 @@
5253
* @param <PropertiesT> the shape of properties for inserted objects.
5354
*/
5455
public final class BatchContext<PropertiesT> implements Closeable {
55-
private final int DEFAULT_BATCH_SIZE = 1_000;
56-
private final int DEFAULT_QUEUE_SIZE = 100;
57-
private final int MAX_RECONNECT_RETRIES = 5;
56+
private final int maxReconnectRetries = 5;
5857

5958
private final CollectionDescriptor<PropertiesT> collectionDescriptor;
6059
private final CollectionHandleDefaults collectionHandleDefaults;
@@ -88,7 +87,7 @@ public final class BatchContext<PropertiesT> implements Closeable {
8887

8988
/**
9089
* Queue publishes insert tasks from the main thread to the "sender".
91-
* It has a maximum capacity of {@link #DEFAULT_QUEUE_SIZE}.
90+
* It has a maximum capacity of {@link #queueSize}.
9291
*
9392
* Send {@link TaskHandle#POISON} to gracefully shutdown the "sender"
9493
* thread. The same queue may be re-used with a different "sender",
@@ -156,13 +155,27 @@ public final class BatchContext<PropertiesT> implements Closeable {
156155
StreamFactory<Message, Event> streamFactory,
157156
int maxSizeBytes,
158157
CollectionDescriptor<PropertiesT> collectionDescriptor,
159-
CollectionHandleDefaults collectionHandleDefaults) {
158+
CollectionHandleDefaults collectionHandleDefaults,
159+
int batchSize,
160+
int queueSize,
161+
int maxReconnectRetries) {
160162
this.streamFactory = requireNonNull(streamFactory, "streamFactory is null");
161163
this.collectionDescriptor = requireNonNull(collectionDescriptor, "collectionDescriptor is null");
162164
this.collectionHandleDefaults = requireNonNull(collectionHandleDefaults, "collectionHandleDefaults is null");
163165

164-
this.queue = new ArrayBlockingQueue<>(DEFAULT_QUEUE_SIZE);
165-
this.batch = new Batch(DEFAULT_BATCH_SIZE, maxSizeBytes);
166+
this.queue = new ArrayBlockingQueue<>(queueSize);
167+
this.batch = new Batch(batchSize, maxSizeBytes);
168+
}
169+
170+
private BatchContext(Builder<PropertiesT> builder) {
171+
this(
172+
builder.streamFactory,
173+
builder.maxSizeBytes,
174+
builder.collectionDescriptor,
175+
builder.collectionHandleDefaults,
176+
builder.batchSize,
177+
builder.queueSize,
178+
builder.maxReconnectRetries);
166179
}
167180

168181
/** Add {@link WeaviateObject} to the batch. */
@@ -189,7 +202,6 @@ void start(State nextState) {
189202
workers = new CountDownLatch(2);
190203

191204
messages = streamFactory.createStream(new Recv());
192-
System.out.println("create stream");
193205

194206
// Start the stream and await Started message.
195207
messages.onNext(Message.start(collectionHandleDefaults.consistencyLevel()));
@@ -233,10 +245,15 @@ public TaskHandle retry(TaskHandle taskHandle) throws InterruptedException {
233245
*/
234246
@Override
235247
public void close() throws IOException {
248+
boolean closedBefore = closed;
236249
closed = true;
237250

238-
try {
251+
if (!closedBefore) {
239252
shutdown();
253+
}
254+
255+
try {
256+
closing.get();
240257
} catch (InterruptedException | ExecutionException e) {
241258
if (e instanceof InterruptedException ||
242259
e.getCause() instanceof InterruptedException) {
@@ -248,8 +265,8 @@ public void close() throws IOException {
248265
}
249266
}
250267

251-
private void shutdown() throws InterruptedException, ExecutionException {
252-
CompletableFuture<Void> gracefulShutdown = CompletableFuture.runAsync(() -> {
268+
private void shutdown() {
269+
CompletableFuture.runAsync(() -> {
253270
try {
254271
// Poison the queue -- this will signal "send" to drain the remaing
255272
// items in the batch and in the backlog and exit.
@@ -270,13 +287,7 @@ private void shutdown() throws InterruptedException, ExecutionException {
270287
} catch (Exception e) {
271288
closing.completeExceptionally(e);
272289
}
273-
274290
}, shutdownExec);
275-
276-
// Complete shutdown as soon as one of these futures are completed.
277-
// - gracefulShutdown completes if we managed to shutdown normally.
278-
// - closing may complete sooner if shutdownNow is called.
279-
CompletableFuture.anyOf(closing, gracefulShutdown).get();
280291
}
281292

282293
private void shutdownNow(Exception ex) {
@@ -333,6 +344,26 @@ void setState(State nextState) {
333344
}
334345
}
335346

347+
/** Returns true if the next batch can be sent. */
348+
boolean canSend() {
349+
lock.lock();
350+
try {
351+
return state.canSend();
352+
} finally {
353+
lock.unlock();
354+
}
355+
}
356+
357+
/** Returns true if the next batch can be assembled from the queued items. */
358+
boolean canPrepareNext() {
359+
lock.lock();
360+
try {
361+
return state.canPrepareNext();
362+
} finally {
363+
lock.unlock();
364+
}
365+
}
366+
336367
/**
337368
* onEvent delegates event handling to {@link #state}.
338369
*
@@ -458,7 +489,7 @@ private void flush() throws InterruptedException {
458489
private void awaitCanSend() throws InterruptedException {
459490
lock.lock();
460491
try {
461-
while (!state.canSend()) {
492+
while (!canSend()) {
462493
stateChanged.await();
463494
}
464495
} finally {
@@ -478,7 +509,7 @@ private void awaitCanSend() throws InterruptedException {
478509
private void awaitCanPrepareNext() throws InterruptedException {
479510
lock.lock();
480511
try {
481-
while (!state.canPrepareNext()) {
512+
while (!canPrepareNext()) {
482513
stateChanged.await();
483514
}
484515
} finally {
@@ -649,7 +680,7 @@ private final void onStreamClosed(Event event) {
649680
hangup.exception().printStackTrace();
650681
}
651682
if (!send.isDone()) {
652-
setState(new Reconnecting(MAX_RECONNECT_RETRIES));
683+
setState(new Reconnecting(maxReconnectRetries));
653684
}
654685
}
655686

@@ -870,4 +901,46 @@ void scheduleReconnect(int reconnectIntervalSeconds) {
870901
}
871902
}, reconnectIntervalSeconds, reconnectIntervalSeconds, TimeUnit.SECONDS);
872903
}
904+
905+
public static class Builder<PropertiesT> implements ObjectBuilder<BatchContext<PropertiesT>> {
906+
private final StreamFactory<Message, Event> streamFactory;
907+
private final int maxSizeBytes;
908+
private final CollectionDescriptor<PropertiesT> collectionDescriptor;
909+
private final CollectionHandleDefaults collectionHandleDefaults;
910+
911+
Builder(
912+
StreamFactory<Message, Event> streamFactory,
913+
int maxSizeBytes,
914+
CollectionDescriptor<PropertiesT> collectionDescriptor,
915+
CollectionHandleDefaults collectionHandleDefaults) {
916+
this.streamFactory = streamFactory;
917+
this.maxSizeBytes = maxSizeBytes;
918+
this.collectionDescriptor = collectionDescriptor;
919+
this.collectionHandleDefaults = collectionHandleDefaults;
920+
}
921+
922+
private int batchSize = 1_000;
923+
private int queueSize = 1_000;
924+
private int maxReconnectRetries = 5;
925+
926+
public Builder<PropertiesT> batchSize(int batchSize) {
927+
this.batchSize = batchSize;
928+
return this;
929+
}
930+
931+
public Builder<PropertiesT> queueSize(int queueSize) {
932+
this.queueSize = queueSize;
933+
return this;
934+
}
935+
936+
public Builder<PropertiesT> maxReconnectRetries(int maxReconnectRetries) {
937+
this.maxReconnectRetries = maxReconnectRetries;
938+
return this;
939+
}
940+
941+
@Override
942+
public BatchContext<PropertiesT> build() {
943+
return new BatchContext<>(this);
944+
}
945+
}
873946
}

src/main/java/io/weaviate/client6/v1/api/collections/batch/WeaviateBatchClient.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import static java.util.Objects.requireNonNull;
44

55
import java.util.OptionalInt;
6+
import java.util.function.Function;
67

78
import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults;
9+
import io.weaviate.client6.v1.internal.ObjectBuilder;
810
import io.weaviate.client6.v1.internal.TransportOptions;
911
import io.weaviate.client6.v1.internal.grpc.GrpcTransport;
1012
import io.weaviate.client6.v1.internal.orm.CollectionDescriptor;
@@ -30,18 +32,38 @@ public WeaviateBatchClient(WeaviateBatchClient<PropertiesT> c, CollectionHandleD
3032
this.grpcTransport = c.grpcTransport;
3133
}
3234

35+
public BatchContext<PropertiesT> start(
36+
Function<BatchContext.Builder<PropertiesT>, ObjectBuilder<BatchContext<PropertiesT>>> fn) {
37+
OptionalInt maxSizeBytes = grpcTransport.maxMessageSizeBytes();
38+
if (maxSizeBytes.isEmpty()) {
39+
throw new IllegalStateException("Server must have grpcMaxMessageSize configured to use server-side batching");
40+
}
41+
42+
StreamFactory<Message, Event> streamFactory = new TranslatingStreamFactory(grpcTransport::createStream);
43+
BatchContext.Builder<PropertiesT> builder = new BatchContext.Builder<>(
44+
streamFactory, maxSizeBytes.getAsInt(), collectionDescriptor, defaults);
45+
BatchContext<PropertiesT> context = fn.apply(builder).build();
46+
47+
if (isWeaviateCloudOnGoogleCloud(grpcTransport.host())) {
48+
context.scheduleReconnect(GCP_RECONNECT_INTERVAL_SECONDS);
49+
}
50+
51+
context.start();
52+
return context;
53+
}
54+
3355
public BatchContext<PropertiesT> start() {
3456
OptionalInt maxSizeBytes = grpcTransport.maxMessageSizeBytes();
3557
if (maxSizeBytes.isEmpty()) {
3658
throw new IllegalStateException("Server must have grpcMaxMessageSize configured to use server-side batching");
3759
}
3860

3961
StreamFactory<Message, Event> streamFactory = new TranslatingStreamFactory(grpcTransport::createStream);
40-
BatchContext<PropertiesT> context = new BatchContext<>(
62+
BatchContext<PropertiesT> context = new BatchContext.Builder<>(
4163
streamFactory,
4264
maxSizeBytes.getAsInt(),
4365
collectionDescriptor,
44-
defaults);
66+
defaults).build();
4567

4668
if (isWeaviateCloudOnGoogleCloud(grpcTransport.host())) {
4769
context.scheduleReconnect(GCP_RECONNECT_INTERVAL_SECONDS);

0 commit comments

Comments
 (0)