From 1be7e76205a479af7d9dd31794f6ca0cc3285993 Mon Sep 17 00:00:00 2001 From: William Chong Date: Wed, 6 May 2026 12:37:35 +0400 Subject: [PATCH 1/3] fix: validate projection engineVersion and V2 trackEmittedStreams combo Reject engineVersion values outside the documented set (0/1/2) and the V2 + trackEmittedStreams combination before sending the request. --- src/main/java/io/kurrent/dbclient/CreateProjection.java | 5 +++++ .../java/io/kurrent/dbclient/CreateProjectionOptions.java | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/io/kurrent/dbclient/CreateProjection.java b/src/main/java/io/kurrent/dbclient/CreateProjection.java index dd1b2b89..4fbf6da8 100644 --- a/src/main/java/io/kurrent/dbclient/CreateProjection.java +++ b/src/main/java/io/kurrent/dbclient/CreateProjection.java @@ -29,6 +29,11 @@ public CreateProjection(final GrpcClient client, final String projectionName, fi @SuppressWarnings("unchecked") public CompletableFuture execute() { + if (engineVersion == 2 && trackEmittedStreams) { + throw new IllegalArgumentException( + "trackEmittedStreams is not supported when engineVersion is 2 (V2)"); + } + return this.client.run(channel -> { Projectionmanagement.CreateReq.Options.Continuous.Builder continuousBuilder = Projectionmanagement.CreateReq.Options.Continuous.newBuilder() diff --git a/src/main/java/io/kurrent/dbclient/CreateProjectionOptions.java b/src/main/java/io/kurrent/dbclient/CreateProjectionOptions.java index 5d5a9247..1d3b2f0e 100644 --- a/src/main/java/io/kurrent/dbclient/CreateProjectionOptions.java +++ b/src/main/java/io/kurrent/dbclient/CreateProjectionOptions.java @@ -54,8 +54,14 @@ public CreateProjectionOptions emitEnabled(boolean value) { * The engine version is pinned at create time and cannot be changed via update. * V2 has limitations versus V1: {@code trackEmittedStreams} is rejected, * result streams are not emitted, and bi-state projections are not supported. + * + * @throws IllegalArgumentException if {@code value} is not {@code 0}, {@code 1}, or {@code 2}. */ public CreateProjectionOptions engineVersion(int value) { + if (value < 0 || value > 2) { + throw new IllegalArgumentException( + "engineVersion must be 0, 1, or 2 (got " + value + ")"); + } this.engineVersion = value; return this; } From 718b11787f7230c0ba57e0c1fd2abc19040aa931 Mon Sep 17 00:00:00 2001 From: William Chong Date: Wed, 6 May 2026 12:45:04 +0400 Subject: [PATCH 2/3] fix: deliver projection validation error via exceptional completion Match how server-side failures of the same condition surface; keep the public CompletableFuture API free of synchronous throws. --- src/main/java/io/kurrent/dbclient/CreateProjection.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/kurrent/dbclient/CreateProjection.java b/src/main/java/io/kurrent/dbclient/CreateProjection.java index 4fbf6da8..e316f53d 100644 --- a/src/main/java/io/kurrent/dbclient/CreateProjection.java +++ b/src/main/java/io/kurrent/dbclient/CreateProjection.java @@ -30,8 +30,10 @@ public CreateProjection(final GrpcClient client, final String projectionName, fi @SuppressWarnings("unchecked") public CompletableFuture execute() { if (engineVersion == 2 && trackEmittedStreams) { - throw new IllegalArgumentException( - "trackEmittedStreams is not supported when engineVersion is 2 (V2)"); + CompletableFuture failed = new CompletableFuture<>(); + failed.completeExceptionally(new IllegalArgumentException( + "trackEmittedStreams is not supported when engineVersion is 2 (V2)")); + return failed; } return this.client.run(channel -> { From e4934d7a85827cdafb06626d9d4af1f83c34ea30 Mon Sep 17 00:00:00 2001 From: William Chong Date: Wed, 6 May 2026 12:46:06 +0400 Subject: [PATCH 3/3] style: rename failed future variable to result for consistency --- src/main/java/io/kurrent/dbclient/CreateProjection.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/kurrent/dbclient/CreateProjection.java b/src/main/java/io/kurrent/dbclient/CreateProjection.java index e316f53d..d233fad9 100644 --- a/src/main/java/io/kurrent/dbclient/CreateProjection.java +++ b/src/main/java/io/kurrent/dbclient/CreateProjection.java @@ -30,10 +30,10 @@ public CreateProjection(final GrpcClient client, final String projectionName, fi @SuppressWarnings("unchecked") public CompletableFuture execute() { if (engineVersion == 2 && trackEmittedStreams) { - CompletableFuture failed = new CompletableFuture<>(); - failed.completeExceptionally(new IllegalArgumentException( + CompletableFuture result = new CompletableFuture<>(); + result.completeExceptionally(new IllegalArgumentException( "trackEmittedStreams is not supported when engineVersion is 2 (V2)")); - return failed; + return result; } return this.client.run(channel -> {