From fb8813996632abcfa3748960e8a920b69d691b4c Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 16 Feb 2026 18:41:37 +0100 Subject: [PATCH 1/6] fix(it): automatically pick up the latest container version --- .../java/io/weaviate/containers/Weaviate.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/it/java/io/weaviate/containers/Weaviate.java b/src/it/java/io/weaviate/containers/Weaviate.java index 0f463e96f..c12bf9f6e 100644 --- a/src/it/java/io/weaviate/containers/Weaviate.java +++ b/src/it/java/io/weaviate/containers/Weaviate.java @@ -26,7 +26,7 @@ public class Weaviate extends WeaviateContainer { public static final String DOCKER_IMAGE = "semitechnologies/weaviate"; - public static final String LATEST_VERSION = Version.V135.semver.toString(); + public static final String LATEST_VERSION = Version.latest().semver.toString(); public static final String VERSION; static { @@ -41,7 +41,8 @@ public enum Version { V132(1, 32, 24), V133(1, 33, 11), V134(1, 34, 7), - V135(1, 35, 2); + V135(1, 35, 2), + V136(1, 36, "0-rc.0"); public final SemanticVersion semver; @@ -49,9 +50,21 @@ private Version(int major, int minor, int patch) { this.semver = new SemanticVersion(major, minor, patch); } + private Version(int major, int minor, String patch) { + this.semver = new SemanticVersion(major, minor, patch); + } + public void orSkip() { ConcurrentTest.requireAtLeast(this); } + + public static Version latest() { + Version[] versions = Version.class.getEnumConstants(); + if (versions == null) { + throw new IllegalStateException("No versions are defined"); + } + return versions[versions.length - 1]; + } } /** From 2657af68053a7331338156458e51114eb58e209b Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 16 Feb 2026 18:42:31 +0100 Subject: [PATCH 2/6] feat(backup): support cancelRestore operation Deprecate WeaviateBackupClient#cancel method, as it is now ambiguous --- .../backup/CancelBackupRestoreRequest.java | 14 +++++++ .../v1/api/backup/WeaviateBackupClient.java | 37 +++++++++++++++++-- .../api/backup/WeaviateBackupClientAsync.java | 29 +++++++++++++-- 3 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 src/main/java/io/weaviate/client6/v1/api/backup/CancelBackupRestoreRequest.java diff --git a/src/main/java/io/weaviate/client6/v1/api/backup/CancelBackupRestoreRequest.java b/src/main/java/io/weaviate/client6/v1/api/backup/CancelBackupRestoreRequest.java new file mode 100644 index 000000000..98bb3234f --- /dev/null +++ b/src/main/java/io/weaviate/client6/v1/api/backup/CancelBackupRestoreRequest.java @@ -0,0 +1,14 @@ +package io.weaviate.client6.v1.api.backup; + +import java.util.Collections; + +import io.weaviate.client6.v1.internal.rest.Endpoint; +import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; + +public record CancelBackupRestoreRequest(String backupId, String backend) { + + public static Endpoint _ENDPOINT = SimpleEndpoint.sideEffect( + request -> "DELETE", + request -> "/backups/" + request.backend + "/" + request.backupId + "/restore", + request -> Collections.emptyMap()); +} diff --git a/src/main/java/io/weaviate/client6/v1/api/backup/WeaviateBackupClient.java b/src/main/java/io/weaviate/client6/v1/api/backup/WeaviateBackupClient.java index 90bf70b8a..ac33c3e21 100644 --- a/src/main/java/io/weaviate/client6/v1/api/backup/WeaviateBackupClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/backup/WeaviateBackupClient.java @@ -179,9 +179,6 @@ public List list(String backend, Function - * This method cannot be called cancel backup restore. - * * @param backupId Backup ID. * @param backend Backup storage backend. * @throws WeaviateApiException in case the server returned with an @@ -189,8 +186,42 @@ public List list(String backend, Function> list(String backend, } /** - * Cancel in-progress backup. - * - *

- * This method cannot be called cancel backup restore. + * Cancel in-progress backup creation. * * @param backupId Backup ID. * @param backend Backup storage backend. + * @deprecated This method forwards to {@link #cancelCreate}. Prefer using the + * latter, as it is less ambiguous. */ + @Deprecated public CompletableFuture cancel(String backupId, String backend) { + return cancelCreate(backupId, backend); + } + + /** + * Cancel in-progress backup creation. + * + * @param backupId Backup ID. + * @param backend Backup storage backend. + */ + public CompletableFuture cancelCreate(String backupId, String backend) { return this.restTransport.performRequestAsync(new CancelBackupRequest(backupId, backend), CancelBackupRequest._ENDPOINT); } + + /** + * Cancel in-progress backup restore. + * + * @param backupId Backup ID. + * @param backend Backup storage backend. + */ + public CompletableFuture cancelRestore(String backupId, String backend) { + return this.restTransport.performRequestAsync(new CancelBackupRestoreRequest(backupId, backend), + CancelBackupRestoreRequest._ENDPOINT); + } } From 9f60f135a13265250b417006442068d11a36dcf5 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 16 Feb 2026 19:11:59 +0100 Subject: [PATCH 3/6] chore(backup): update status descriptions --- src/it/java/io/weaviate/integration/BackupITest.java | 11 +++++------ .../weaviate/client6/v1/api/backup/BackupStatus.java | 9 +++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/it/java/io/weaviate/integration/BackupITest.java b/src/it/java/io/weaviate/integration/BackupITest.java index c540afaae..f82d30626 100644 --- a/src/it/java/io/weaviate/integration/BackupITest.java +++ b/src/it/java/io/weaviate/integration/BackupITest.java @@ -112,12 +112,11 @@ public void test_lifecycle() throws IOException, TimeoutException { // Act: delete data and restore backup #1 client.collections.delete(nsA); - client.backup.restore(backup_1, backend, restore -> restore.includeCollections(nsA)); + var restoreMe = client.backup.restore(backup_1, backend, restore -> restore.includeCollections(nsA)); + restoreMe.waitForCompletion(client); // Assert: object inserted in the beginning of the test is present - var restore_1 = client.backup.getRestoreStatus(backup_1, backend) - .orElseThrow().waitForCompletion(client); - Assertions.assertThat(restore_1).as("restore backup #1") + Assertions.assertThat(restoreMe).as("restore backup #1") .returns(BackupStatus.SUCCESS, Backup::status); Assertions.assertThat(collectionA.size()).as("after restore backup #1").isEqualTo(1); } @@ -215,10 +214,10 @@ public void test_lifecycle_async() throws ExecutionException, InterruptedExcepti // Act: delete data and restore backup #1 async.collections.delete(nsA).join(); - async.backup.restore(backup_1, backend, restore -> restore.includeCollections(nsA)).join(); + var restore_1 = async.backup.restore(backup_1, backend, restore -> restore.includeCollections(nsA)).join(); // Assert: object inserted in the beginning of the test is present - var restore_1 = async.backup.getRestoreStatus(backup_1, backend) + restore_1 = async.backup.getRestoreStatus(backup_1, backend) .thenCompose(bak -> bak.orElseThrow().waitForCompletion(async)) .join(); Assertions.assertThat(restore_1).as("restore backup #1") diff --git a/src/main/java/io/weaviate/client6/v1/api/backup/BackupStatus.java b/src/main/java/io/weaviate/client6/v1/api/backup/BackupStatus.java index 7247fade5..5e598d1f4 100644 --- a/src/main/java/io/weaviate/client6/v1/api/backup/BackupStatus.java +++ b/src/main/java/io/weaviate/client6/v1/api/backup/BackupStatus.java @@ -11,8 +11,8 @@ public enum BackupStatus { TRANSFERRING, /** * Cancellation has been claimed by a coordinator. - * Used as a distributed lock to prevent race conditions when multiple coordinators - * attempt to cancel the same restore. + * Used as a distributed lock to prevent race conditions when multiple + * coordinators attempt to cancel the same restore. */ @SerializedName("CANCELLING") CANCELLING, @@ -28,10 +28,7 @@ public enum BackupStatus { /** Backup creation / restoration failed. */ @SerializedName("FAILED") FAILED, - /** - * Backup creation canceled. - * This status is never returned for backup restorations. - */ + /** Backup creation canceled. */ @SerializedName("CANCELED") CANCELED; } From 9c63e905e3deda0929b1c9dab1aa11403397d248 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 16 Feb 2026 20:12:53 +0100 Subject: [PATCH 4/6] test: add utility for converting Runnable -> ThrowingRunnable --- src/it/java/io/weaviate/ConcurrentTest.java | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/it/java/io/weaviate/ConcurrentTest.java b/src/it/java/io/weaviate/ConcurrentTest.java index 6e783ff06..d519d0c7e 100644 --- a/src/it/java/io/weaviate/ConcurrentTest.java +++ b/src/it/java/io/weaviate/ConcurrentTest.java @@ -126,10 +126,37 @@ public static void requireAtLeast(Weaviate.Version required) { .isGreaterThanOrEqualTo(required.semver); } + @FunctionalInterface + public interface ThrowingRunnable { + void run() throws Exception; + } + + /** + * Run a block of code only if the server version is recent enough. + * + * @param required Minimal required version. + * @param r Runnable. + */ public static void requireAtLeast(Weaviate.Version required, Runnable r) { var actual = SemanticVersion.of(Weaviate.VERSION); if (actual.compareTo(required.semver) >= 0) { r.run(); } } + + /** + * Wraps a {@link ThrowingRunnable} as {@link Runnable} that + * re-throws all exceptions as {@link RuntimeException}. + * + * @param tr Runnable which may throw a checked exception. + */ + public static Runnable throwing(ThrowingRunnable tr) { + return () -> { + try { + tr.run(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }; + } } From c77568da48228cbc8e04321013aaef7d8b85a551 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 16 Feb 2026 20:13:41 +0100 Subject: [PATCH 5/6] test(backup): extend BackupITest to include restore cancellation --- .../io/weaviate/integration/BackupITest.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/it/java/io/weaviate/integration/BackupITest.java b/src/it/java/io/weaviate/integration/BackupITest.java index f82d30626..0f51ca724 100644 --- a/src/it/java/io/weaviate/integration/BackupITest.java +++ b/src/it/java/io/weaviate/integration/BackupITest.java @@ -14,6 +14,8 @@ import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.Test; +import com.sun.nio.sctp.IllegalUnbindException; + import io.weaviate.ConcurrentTest; import io.weaviate.client6.v1.api.WeaviateClient; import io.weaviate.client6.v1.api.backup.Backup; @@ -113,12 +115,21 @@ public void test_lifecycle() throws IOException, TimeoutException { // Act: delete data and restore backup #1 client.collections.delete(nsA); var restoreMe = client.backup.restore(backup_1, backend, restore -> restore.includeCollections(nsA)); - restoreMe.waitForCompletion(client); // Assert: object inserted in the beginning of the test is present + restoreMe = restoreMe.waitForCompletion(client); Assertions.assertThat(restoreMe).as("restore backup #1") .returns(BackupStatus.SUCCESS, Backup::status); Assertions.assertThat(collectionA.size()).as("after restore backup #1").isEqualTo(1); + + // Act: restore and cancel + requireAtLeast(Weaviate.Version.V136, throwing(() -> { + var restore_2 = client.backup.restore(backup_2, backend); + client.backup.cancelRestore(backup_2, backend); + var canceledRestore = restore_2.waitForStatus(client, BackupStatus.CANCELED); + Assertions.assertThat(canceledRestore).as("cancel backup restore #2") + .returns(BackupStatus.CANCELED, Backup::status); + })); } @Test @@ -214,13 +225,11 @@ public void test_lifecycle_async() throws ExecutionException, InterruptedExcepti // Act: delete data and restore backup #1 async.collections.delete(nsA).join(); - var restore_1 = async.backup.restore(backup_1, backend, restore -> restore.includeCollections(nsA)).join(); + var restoreMe = async.backup.restore(backup_1, backend, restore -> restore.includeCollections(nsA)).join(); // Assert: object inserted in the beginning of the test is present - restore_1 = async.backup.getRestoreStatus(backup_1, backend) - .thenCompose(bak -> bak.orElseThrow().waitForCompletion(async)) - .join(); - Assertions.assertThat(restore_1).as("restore backup #1") + restoreMe = restoreMe.waitForCompletion(async).join(); + Assertions.assertThat(restoreMe).as("restore backup #1") .returns(BackupStatus.SUCCESS, Backup::status); Assertions.assertThat(collectionA.size().join()).as("after restore backup #1").isEqualTo(1); } From 1b35b7fee5823ebd95b6afa5bfbae670f7fddf8a Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Mon, 16 Feb 2026 20:15:07 +0100 Subject: [PATCH 6/6] ci(test): add v1.36.0-rc.0 to the testing matrix --- .github/workflows/test.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index cdcf934fc..50fe6d1b1 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -78,7 +78,8 @@ jobs: strategy: fail-fast: false matrix: - WEAVIATE_VERSION: ["1.32.24", "1.33.11", "1.34.7", "1.35.2"] + WEAVIATE_VERSION: + ["1.32.24", "1.33.11", "1.34.7", "1.35.2", "1.36.0-rc.0"] steps: - uses: actions/checkout@v4