diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 544295dd0..5f5ff7bcf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,7 @@ jobs: GOPROXY: https://proxy.golang.org JDK_VER: ${{ matrix.java }} DAPR_CLI_VER: 1.15.0 - DAPR_RUNTIME_VER: 1.15.7 + DAPR_RUNTIME_VER: 1.16.0-rc.2 DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/v1.15.0/install/install.sh DAPR_CLI_REF: DAPR_REF: diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 0fac7f971..349c61b93 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -38,7 +38,7 @@ jobs: GOPROXY: https://proxy.golang.org JDK_VER: ${{ matrix.java }} DAPR_CLI_VER: 1.15.0 - DAPR_RUNTIME_VER: 1.15.7 + DAPR_RUNTIME_VER: 1.16.0-rc.2 DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/v1.15.0/install/install.sh DAPR_CLI_REF: DAPR_REF: diff --git a/daprdocs/content/en/java-sdk-docs/spring-boot/_index.md b/daprdocs/content/en/java-sdk-docs/spring-boot/_index.md index 3e108bfea..ee9f25a86 100644 --- a/daprdocs/content/en/java-sdk-docs/spring-boot/_index.md +++ b/daprdocs/content/en/java-sdk-docs/spring-boot/_index.md @@ -95,7 +95,7 @@ public class DaprTestContainersConfig { @ServiceConnection public DaprContainer daprContainer(Network daprNetwork, PostgreSQLContainer postgreSQLContainer){ - return new DaprContainer("daprio/daprd:1.15.7") + return new DaprContainer("daprio/daprd:1.16.0-rc.2") .withAppName("producer-app") .withNetwork(daprNetwork) .withComponent(new Component("kvstore", "state.postgresql", "v1", STATE_STORE_PROPERTIES)) @@ -250,7 +250,7 @@ Finally, because Dapr PubSub requires a bidirectional connection between your ap @ServiceConnection public DaprContainer daprContainer(Network daprNetwork, PostgreSQLContainer postgreSQLContainer, RabbitMQContainer rabbitMQContainer){ - return new DaprContainer("daprio/daprd:1.15.7") + return new DaprContainer("daprio/daprd:1.16.0-rc.2") .withAppName("producer-app") .withNetwork(daprNetwork) .withComponent(new Component("kvstore", "state.postgresql", "v1", STATE_STORE_PROPERTIES)) diff --git a/pom.xml b/pom.xml index 2bf1fc22b..bd6fbf7db 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ 1.69.0 3.25.5 protoc - https://raw.githubusercontent.com/dapr/dapr/v1.15.7/dapr/proto + https://raw.githubusercontent.com/dapr/dapr/v1.16.0-rc.2/dapr/proto 1.16.0-SNAPSHOT 0.16.0-SNAPSHOT 1.7.1 diff --git a/sdk-tests/src/test/java/io/dapr/it/testcontainers/jobs/DaprJobsIT.java b/sdk-tests/src/test/java/io/dapr/it/testcontainers/jobs/DaprJobsIT.java index b1cc13493..529744b18 100644 --- a/sdk-tests/src/test/java/io/dapr/it/testcontainers/jobs/DaprJobsIT.java +++ b/sdk-tests/src/test/java/io/dapr/it/testcontainers/jobs/DaprJobsIT.java @@ -93,7 +93,7 @@ public class DaprJobsIT { .withZone(ZoneOffset.UTC); Instant currentTime = Instant.now(); - daprPreviewClient.scheduleJob(new ScheduleJobRequest("Job", currentTime)).block(); + daprPreviewClient.scheduleJob(new ScheduleJobRequest("Job", currentTime).setOverwrite(true)).block(); GetJobResponse getJobResponse = daprPreviewClient.getJob(new GetJobRequest("Job")).block(); @@ -108,7 +108,7 @@ public class DaprJobsIT { Instant currentTime = Instant.now(); daprPreviewClient.scheduleJob(new ScheduleJobRequest("Job", JobSchedule.hourly()) - .setDueTime(currentTime)).block(); + .setDueTime(currentTime).setOverwrite(true)).block(); GetJobResponse getJobResponse = daprPreviewClient.getJob(new GetJobRequest("Job")).block(); @@ -129,6 +129,7 @@ public class DaprJobsIT { .setTtl(currentTime.plus(2, ChronoUnit.HOURS)) .setData("Job data".getBytes()) .setRepeat(3) + .setOverwrite(true) .setSchedule(JobSchedule.fromString(cronExpression))).block(); GetJobResponse getJobResponse = @@ -152,6 +153,7 @@ public class DaprJobsIT { .setTtl(currentTime.plus(2, ChronoUnit.HOURS)) .setData("Job data".getBytes()) .setRepeat(3) + .setOverwrite(true) .setSchedule(JobSchedule.fromString(cronExpression))).block(); daprPreviewClient.deleteJob(new DeleteJobRequest("Job")).block(); diff --git a/sdk/src/main/java/io/dapr/client/DaprClientImpl.java b/sdk/src/main/java/io/dapr/client/DaprClientImpl.java index 66c8772d6..5b78a59cb 100644 --- a/sdk/src/main/java/io/dapr/client/DaprClientImpl.java +++ b/sdk/src/main/java/io/dapr/client/DaprClientImpl.java @@ -1336,6 +1336,8 @@ public class DaprClientImpl extends AbstractDaprClient { scheduleJobRequestBuilder.setDueTime(iso8601Formatter.format(scheduleJobRequest.getDueTime())); } + scheduleJobRequestBuilder.setOverwrite(scheduleJobRequest.getOverwrite()); + Mono scheduleJobResponseMono = Mono.deferContextual(context -> this.createMono( it -> intercept(context, asyncStub) diff --git a/sdk/src/main/java/io/dapr/client/domain/ScheduleJobRequest.java b/sdk/src/main/java/io/dapr/client/domain/ScheduleJobRequest.java index 9f91e6142..6113bf649 100644 --- a/sdk/src/main/java/io/dapr/client/domain/ScheduleJobRequest.java +++ b/sdk/src/main/java/io/dapr/client/domain/ScheduleJobRequest.java @@ -25,6 +25,7 @@ public class ScheduleJobRequest { private Instant dueTime; private Integer repeats; private Instant ttl; + private boolean overwrite; /** * Constructor to create ScheduleJobRequest. @@ -165,4 +166,24 @@ public class ScheduleJobRequest { public Instant getTtl() { return ttl; } + + /** + * Gets the overwrite flag. + * + * @return The overwrite flag. + */ + public boolean getOverwrite() { + return overwrite; + } + + /** + * Sets the overwrite flag. + * + * @param overwrite The overwrite flag. + * @return This builder instance. + */ + public ScheduleJobRequest setOverwrite(boolean overwrite) { + this.overwrite = overwrite; + return this; + } } diff --git a/sdk/src/test/java/io/dapr/client/DaprPreviewClientGrpcTest.java b/sdk/src/test/java/io/dapr/client/DaprPreviewClientGrpcTest.java index 5cc49edfd..b2922bf97 100644 --- a/sdk/src/test/java/io/dapr/client/DaprPreviewClientGrpcTest.java +++ b/sdk/src/test/java/io/dapr/client/DaprPreviewClientGrpcTest.java @@ -817,6 +817,84 @@ public class DaprPreviewClientGrpcTest { assertEquals("Name in the request cannot be null or empty", exception.getMessage()); } + @Test + public void scheduleJobShouldThrowWhenNameAlreadyExists() { + AtomicInteger callCount = new AtomicInteger(0); + + doAnswer(invocation -> { + StreamObserver observer = invocation.getArgument(1); + if (callCount.incrementAndGet() == 1) { + // First call succeeds + observer.onCompleted(); + } else { + // Second call fails with ALREADY_EXISTS + observer.onError(newStatusRuntimeException("ALREADY_EXISTS", "Job with name 'testJob' already exists")); + } + return null; + }).when(daprStub).scheduleJobAlpha1(any(DaprProtos.ScheduleJobRequest.class), any()); + + // First call should succeed + ScheduleJobRequest firstRequest = new ScheduleJobRequest("testJob", Instant.now()); + assertDoesNotThrow(() -> previewClient.scheduleJob(firstRequest).block()); + + ArgumentCaptor captor = + ArgumentCaptor.forClass(DaprProtos.ScheduleJobRequest.class); + + verify(daprStub, times(1)).scheduleJobAlpha1(captor.capture(), Mockito.any()); + DaprProtos.ScheduleJobRequest actualScheduleJobRequest = captor.getValue(); + DaprProtos.Job job = actualScheduleJobRequest.getJob(); + assertEquals("testJob", job.getName()); + assertFalse(job.hasData()); + assertEquals(0, job.getRepeats()); + assertFalse(job.hasTtl()); + + // Second call with same name should fail + ScheduleJobRequest secondRequest = new ScheduleJobRequest("testJob", Instant.now()); + + assertThrowsDaprException( + ExecutionException.class, + "ALREADY_EXISTS", + "ALREADY_EXISTS: Job with name 'testJob' already exists", + () -> previewClient.scheduleJob(secondRequest).block()); + } + + @Test + public void scheduleJobShouldSucceedWhenNameAlreadyExistsWithOverwrite() { + doAnswer(invocation -> { + StreamObserver observer = invocation.getArgument(1); + observer.onCompleted(); // Simulate successful response for both calls + return null; + }).when(daprStub).scheduleJobAlpha1(any(DaprProtos.ScheduleJobRequest.class), any()); + + // First call should succeed + ScheduleJobRequest firstRequest = new ScheduleJobRequest("testJob", Instant.now()); + assertDoesNotThrow(() -> previewClient.scheduleJob(firstRequest).block()); + + // Second call with same name but overwrite=true should also succeed + ScheduleJobRequest secondRequest = new ScheduleJobRequest("testJob", Instant.now()) + .setOverwrite(true); + assertDoesNotThrow(() -> previewClient.scheduleJob(secondRequest).block()); + + // Verify that both calls were made successfully + ArgumentCaptor captor = + ArgumentCaptor.forClass(DaprProtos.ScheduleJobRequest.class); + verify(daprStub, times(2)).scheduleJobAlpha1(captor.capture(), any()); + + // Verify the first call doesn't have overwrite set + DaprProtos.ScheduleJobRequest firstActualRequest = captor.getAllValues().get(0); + assertFalse(firstActualRequest.getJob().getOverwrite()); + assertEquals("testJob", firstActualRequest.getJob().getName()); + + // Verify the second call has overwrite set to true + DaprProtos.ScheduleJobRequest secondActualRequest = captor.getAllValues().get(1); + assertTrue(secondActualRequest.getJob().getOverwrite()); + assertEquals("testJob", secondActualRequest.getJob().getName()); + } + + + + + @Test public void getJobShouldReturnResponseWhenAllFieldsArePresentInRequest() { DateTimeFormatter iso8601Formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") diff --git a/spring-boot-examples/kubernetes/README.md b/spring-boot-examples/kubernetes/README.md index 67bc1290a..106747e94 100644 --- a/spring-boot-examples/kubernetes/README.md +++ b/spring-boot-examples/kubernetes/README.md @@ -30,7 +30,7 @@ Once you have the cluster up and running you can install Dapr: helm repo add dapr https://dapr.github.io/helm-charts/ helm repo update helm upgrade --install dapr dapr/dapr \ ---version=1.15.7 \ +--version=1.16.0-rc.2 \ --namespace dapr-system \ --create-namespace \ --wait diff --git a/testcontainers-dapr/src/main/java/io/dapr/testcontainers/DaprContainerConstants.java b/testcontainers-dapr/src/main/java/io/dapr/testcontainers/DaprContainerConstants.java index 5db64d83f..acfc811d8 100644 --- a/testcontainers-dapr/src/main/java/io/dapr/testcontainers/DaprContainerConstants.java +++ b/testcontainers-dapr/src/main/java/io/dapr/testcontainers/DaprContainerConstants.java @@ -14,7 +14,7 @@ limitations under the License. package io.dapr.testcontainers; public interface DaprContainerConstants { - String DAPR_VERSION = "1.15.7"; + String DAPR_VERSION = "1.16.0-rc.2"; String DAPR_RUNTIME_IMAGE_TAG = "daprio/daprd:" + DAPR_VERSION; String DAPR_PLACEMENT_IMAGE_TAG = "daprio/placement:" + DAPR_VERSION; String DAPR_SCHEDULER_IMAGE_TAG = "daprio/scheduler:" + DAPR_VERSION;