diff --git a/java-storage/README.md b/java-storage/README.md index b0f5384ef7f2..9a461f646f62 100644 --- a/java-storage/README.md +++ b/java-storage/README.md @@ -319,6 +319,11 @@ Samples are in the [`samples/`](https://github.com/googleapis/google-cloud-java/ | Delete Folder Recursive | [source code](https://github.com/googleapis/google-cloud-java/blob/main/samples/snippets/src/main/java/com/example/storage/control/v2/DeleteFolderRecursive.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-cloud-java&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/control/v2/DeleteFolderRecursive.java) | | Get Folder | [source code](https://github.com/googleapis/google-cloud-java/blob/main/samples/snippets/src/main/java/com/example/storage/control/v2/GetFolder.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-cloud-java&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/control/v2/GetFolder.java) | | List Folders | [source code](https://github.com/googleapis/google-cloud-java/blob/main/samples/snippets/src/main/java/com/example/storage/control/v2/ListFolders.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-cloud-java&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/control/v2/ListFolders.java) | +| Rapid Cache Create | [source code](https://github.com/googleapis/google-cloud-java/blob/main/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheCreate.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-cloud-java&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheCreate.java) | +| Rapid Cache Disable | [source code](https://github.com/googleapis/google-cloud-java/blob/main/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheDisable.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-cloud-java&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheDisable.java) | +| Rapid Cache Get | [source code](https://github.com/googleapis/google-cloud-java/blob/main/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheGet.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-cloud-java&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheGet.java) | +| Rapid Cache List | [source code](https://github.com/googleapis/google-cloud-java/blob/main/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheList.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-cloud-java&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheList.java) | +| Rapid Cache Update | [source code](https://github.com/googleapis/google-cloud-java/blob/main/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheUpdate.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-cloud-java&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheUpdate.java) | | Rename Folder | [source code](https://github.com/googleapis/google-cloud-java/blob/main/samples/snippets/src/main/java/com/example/storage/control/v2/RenameFolder.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-cloud-java&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/control/v2/RenameFolder.java) | | Activate Hmac Key | [source code](https://github.com/googleapis/google-cloud-java/blob/main/samples/snippets/src/main/java/com/example/storage/hmac/ActivateHmacKey.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-cloud-java&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/hmac/ActivateHmacKey.java) | | Create Hmac Key | [source code](https://github.com/googleapis/google-cloud-java/blob/main/samples/snippets/src/main/java/com/example/storage/hmac/CreateHmacKey.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/google-cloud-java&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/hmac/CreateHmacKey.java) | diff --git a/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheCreate.java b/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheCreate.java new file mode 100644 index 000000000000..bf573a4d8b43 --- /dev/null +++ b/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheCreate.java @@ -0,0 +1,72 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.storage.control.v2; + +// [START storage_control_create_rapid_cache] + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.storage.control.v2.BucketName; +import com.google.storage.control.v2.CreateRapidCacheMetadata; +import com.google.storage.control.v2.CreateRapidCacheRequest; +import com.google.storage.control.v2.RapidCache; +import com.google.storage.control.v2.RapidCacheName; +import com.google.storage.control.v2.StorageControlClient; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public final class RapidCacheCreate { + + public static void rapidCacheCreate(String bucketName, String cacheId) + throws InterruptedException, ExecutionException, IOException { + // The ID of your GCS bucket + // String bucketName = "your-unique-bucket-name"; + + // The ID of the Rapid Cache. It must be the zone in which to create the cache, and the zone + // must be in the same region as the bucket. + // String cacheId = "us-central1-a"; + + try (StorageControlClient storageControl = StorageControlClient.create()) { + + // Rapid Cache Ultra requires a regional bucket with hierarchical namespace enabled. + RapidCache rapidCache = + RapidCache.newBuilder() + .setName(RapidCacheName.format("_", bucketName, cacheId)) + // The Rapid Cache ID is the zone in which the cache is created. + .setZone(cacheId) + .setCacheType("rapid-cache-ultra") + .build(); + + CreateRapidCacheRequest request = + CreateRapidCacheRequest.newBuilder() + // Set project to "_" to signify globally scoped bucket + .setParent(BucketName.format("_", bucketName)) + .setRapidCache(rapidCache) + .build(); + + // Start a long-running operation (LRO). + OperationFuture operation = + storageControl.createRapidCacheAsync(request); + + // Await the LRO's completion. + RapidCache createdRapidCache = operation.get(); + System.out.printf("Created Rapid Cache: %s%n", createdRapidCache.getName()); + System.out.printf("Cache type: %s%n", createdRapidCache.getCacheType()); + System.out.printf("State: %s%n", createdRapidCache.getState()); + } + } +} +// [END storage_control_create_rapid_cache] diff --git a/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheDisable.java b/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheDisable.java new file mode 100644 index 000000000000..727e4a5c4243 --- /dev/null +++ b/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheDisable.java @@ -0,0 +1,62 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.storage.control.v2; + +// [START storage_control_disable_rapid_cache] + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.storage.control.v2.DisableRapidCacheMetadata; +import com.google.storage.control.v2.DisableRapidCacheRequest; +import com.google.storage.control.v2.RapidCache; +import com.google.storage.control.v2.RapidCacheName; +import com.google.storage.control.v2.StorageControlClient; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public final class RapidCacheDisable { + + public static void rapidCacheDisable(String bucketName, String cacheId) + throws InterruptedException, ExecutionException, IOException { + // The ID of your GCS bucket + // String bucketName = "your-unique-bucket-name"; + + // The ID of the Rapid Cache + // String cacheId = "your-rapid-cache-id"; + + try (StorageControlClient storageControl = StorageControlClient.create()) { + + // Set project to "_" to signify globally scoped bucket + String rapidCacheName = RapidCacheName.format("_", bucketName, cacheId); + DisableRapidCacheRequest request = + DisableRapidCacheRequest.newBuilder().setName(rapidCacheName).build(); + + // Start a long-running operation (LRO). + OperationFuture operation = + storageControl.disableRapidCacheAsync(request); + + // Await the LRO's completion. The cache moves to the "disabled" state within seconds, but + // the operation only completes once the cache has been fully removed, which can take longer + // than the client's default polling timeout. If the wait times out, get() throws a + // CancellationException, but the cache is already disabled; use RapidCacheGet to check its + // state. + RapidCache disabledRapidCache = operation.get(); + System.out.printf("Disabled Rapid Cache: %s%n", disabledRapidCache.getName()); + System.out.printf("State: %s%n", disabledRapidCache.getState()); + } + } +} +// [END storage_control_disable_rapid_cache] diff --git a/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheGet.java b/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheGet.java new file mode 100644 index 000000000000..2e6a57557f25 --- /dev/null +++ b/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheGet.java @@ -0,0 +1,53 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.storage.control.v2; + +// [START storage_control_get_rapid_cache] + +import com.google.storage.control.v2.GetRapidCacheRequest; +import com.google.storage.control.v2.RapidCache; +import com.google.storage.control.v2.RapidCacheName; +import com.google.storage.control.v2.StorageControlClient; +import java.io.IOException; + +public final class RapidCacheGet { + + public static void rapidCacheGet(String bucketName, String cacheId) throws IOException { + // The ID of your GCS bucket + // String bucketName = "your-unique-bucket-name"; + + // The ID of the Rapid Cache + // String cacheId = "your-rapid-cache-id"; + + try (StorageControlClient storageControl = StorageControlClient.create()) { + + GetRapidCacheRequest request = + GetRapidCacheRequest.newBuilder() + // Set project to "_" to signify globally scoped bucket + .setName(RapidCacheName.format("_", bucketName, cacheId)) + .build(); + + RapidCache rapidCache = storageControl.getRapidCache(request); + + System.out.printf("Got Rapid Cache: %s%n", rapidCache.getName()); + System.out.printf("Zone: %s%n", rapidCache.getZone()); + System.out.printf("Cache type: %s%n", rapidCache.getCacheType()); + System.out.printf("State: %s%n", rapidCache.getState()); + } + } +} +// [END storage_control_get_rapid_cache] diff --git a/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheList.java b/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheList.java new file mode 100644 index 000000000000..a55b7a9202ad --- /dev/null +++ b/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheList.java @@ -0,0 +1,52 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.storage.control.v2; + +// [START storage_control_list_rapid_caches] + +import com.google.storage.control.v2.BucketName; +import com.google.storage.control.v2.ListRapidCachesRequest; +import com.google.storage.control.v2.RapidCache; +import com.google.storage.control.v2.StorageControlClient; +import com.google.storage.control.v2.StorageControlClient.ListRapidCachesPagedResponse; +import java.io.IOException; + +public final class RapidCacheList { + + public static void rapidCacheList(String bucketName) throws IOException { + // The ID of your GCS bucket + // String bucketName = "your-unique-bucket-name"; + + try (StorageControlClient storageControl = StorageControlClient.create()) { + + ListRapidCachesRequest request = + ListRapidCachesRequest.newBuilder() + // Set project to "_" to signify globally scoped bucket + .setParent(BucketName.format("_", bucketName)) + .build(); + + // The paged response handles pagination automatically. + ListRapidCachesPagedResponse response = storageControl.listRapidCaches(request); + for (RapidCache rapidCache : response.iterateAll()) { + System.out.println(rapidCache.getName()); + } + + System.out.printf("Listed Rapid Caches in bucket %s%n", bucketName); + } + } +} +// [END storage_control_list_rapid_caches] diff --git a/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheUpdate.java b/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheUpdate.java new file mode 100644 index 000000000000..22af896b191b --- /dev/null +++ b/java-storage/samples/snippets/src/main/java/com/example/storage/control/v2/RapidCacheUpdate.java @@ -0,0 +1,73 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.storage.control.v2; + +// [START storage_control_update_rapid_cache] + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.protobuf.Duration; +import com.google.protobuf.FieldMask; +import com.google.storage.control.v2.RapidCache; +import com.google.storage.control.v2.RapidCacheName; +import com.google.storage.control.v2.StorageControlClient; +import com.google.storage.control.v2.UpdateRapidCacheMetadata; +import com.google.storage.control.v2.UpdateRapidCacheRequest; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public final class RapidCacheUpdate { + + public static void rapidCacheUpdate(String bucketName, String cacheId, long ttlSeconds) + throws InterruptedException, ExecutionException, IOException { + // The ID of your GCS bucket + // String bucketName = "your-unique-bucket-name"; + + // The ID of the Rapid Cache + // String cacheId = "your-rapid-cache-id"; + + // The new time to live (TTL) for cache entries, in seconds. The TTL must be between 1 hour and + // 7 days. + // long ttlSeconds = 172800; // 2 days + + try (StorageControlClient storageControl = StorageControlClient.create()) { + + RapidCache pendingUpdate = + RapidCache.newBuilder() + // Set project to "_" to signify globally scoped bucket + .setName(RapidCacheName.format("_", bucketName, cacheId)) + .setTtl(Duration.newBuilder().setSeconds(ttlSeconds).build()) + .build(); + + UpdateRapidCacheRequest request = + UpdateRapidCacheRequest.newBuilder() + .setRapidCache(pendingUpdate) + // Only the fields listed in the update mask are changed. + .setUpdateMask(FieldMask.newBuilder().addPaths("ttl").build()) + .build(); + + // Start a long-running operation (LRO). + OperationFuture operation = + storageControl.updateRapidCacheAsync(request); + + // Await the LRO's completion. + RapidCache updatedRapidCache = operation.get(); + System.out.printf("Updated Rapid Cache: %s%n", updatedRapidCache.getName()); + System.out.printf("TTL: %d seconds%n", updatedRapidCache.getTtl().getSeconds()); + } + } +} +// [END storage_control_update_rapid_cache] diff --git a/java-storage/samples/snippets/src/test/java/com/example/storage/control/v2/ITRapidCacheTest.java b/java-storage/samples/snippets/src/test/java/com/example/storage/control/v2/ITRapidCacheTest.java new file mode 100644 index 000000000000..2e09c93df708 --- /dev/null +++ b/java-storage/samples/snippets/src/test/java/com/example/storage/control/v2/ITRapidCacheTest.java @@ -0,0 +1,175 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.storage.control.v2; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assume.assumeTrue; + +import com.example.storage.TestBase; +import com.google.cloud.storage.BucketInfo; +import com.google.cloud.storage.BucketInfo.HierarchicalNamespace; +import com.google.cloud.storage.BucketInfo.IamConfiguration; +import com.google.cloud.storage.StorageException; +import com.google.cloud.storage.it.runner.registry.Zone; +import com.google.cloud.storage.testing.RemoteStorageHelper; +import com.google.common.base.MoreObjects; +import com.google.common.base.Strings; +import com.google.storage.control.v2.RapidCacheName; +import com.google.storage.control.v2.StorageControlClient; +import java.util.concurrent.CancellationException; +import java.util.concurrent.TimeUnit; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public final class ITRapidCacheTest extends TestBase { + + private static final String CACHE_TYPE = "rapid-cache-ultra"; + // Wait for the bucket metadata to propagate before creating the Rapid Cache. + private static final long BUCKET_PROPAGATION_SECONDS = 20; + // Bucket deletion is rejected while the Rapid Cache is still being removed. + private static final long BUCKET_DELETE_TIMEOUT_SECONDS = 120; + private static final long BUCKET_DELETE_INTERVAL_SECONDS = 15; + + // The zone in which to create the Rapid Cache. Override with the RAPID_CACHE_ZONE environment + // variable. + private static final Zone ZONE = + Zone.parse( + MoreObjects.firstNonNull( + Strings.emptyToNull(System.getenv("RAPID_CACHE_ZONE")), "us-central1-a")); + + private String bucketName; + // The Rapid Cache ID must be the same as the zone. + private final String cacheId = ZONE.getZone(); + // Whether the Rapid Cache may exist and still needs to be disabled during teardown. + private boolean cacheActive; + private int outputOffset; + + @Before + public void setUp() throws InterruptedException { + assumeTrue( + "RapidCache sample tests skipped in CI due to very long operation times.", + Strings.isNullOrEmpty(System.getenv("JOB_TYPE"))); + // Rapid Cache Ultra requires a regional bucket with hierarchical namespace enabled, located in + // the same region as the cache zone. + String name = RemoteStorageHelper.generateBucketName(); + storage.create( + BucketInfo.newBuilder(name) + .setLocation(ZONE.getRegion()) + .setIamConfiguration( + // Hierarchical namespace buckets must use uniform bucket-level access. + IamConfiguration.newBuilder().setIsUniformBucketLevelAccessEnabled(true).build()) + .setHierarchicalNamespace(HierarchicalNamespace.newBuilder().setEnabled(true).build()) + .build()); + bucketName = name; + TimeUnit.SECONDS.sleep(BUCKET_PROPAGATION_SECONDS); + } + + @After + public void tearDown() throws InterruptedException { + if (bucketName == null) { + return; + } + if (cacheActive) { + disableQuietly(); + } + // Best-effort cleanup. A bucket with a Rapid Cache cannot be deleted until the cache has been + // fully removed, which can take a long time after it is disabled. Any leftover bucket is + // removed by the stale bucket cleanup. + long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(BUCKET_DELETE_TIMEOUT_SECONDS); + while (true) { + try { + storage.delete(bucketName); + return; + } catch (StorageException e) { + if (e.getCode() != 409 || System.nanoTime() > deadline) { + System.err.printf("Leaving bucket %s for cleanup: %s%n", bucketName, e.getMessage()); + return; + } + TimeUnit.SECONDS.sleep(BUCKET_DELETE_INTERVAL_SECONDS); + } + } + } + + @Test + public void createGetListUpdateDisable() throws Exception { + String cacheName = RapidCacheName.format("_", bucketName, cacheId); + + // Test create Rapid Cache + cacheActive = true; + RapidCacheCreate.rapidCacheCreate(bucketName, cacheId); + String out = newOutput(); + assertThat(out).contains("Created Rapid Cache: " + cacheName); + assertThat(out).contains("Cache type: " + CACHE_TYPE); + + // Test get Rapid Cache + RapidCacheGet.rapidCacheGet(bucketName, cacheId); + out = newOutput(); + assertThat(out).contains("Got Rapid Cache: " + cacheName); + assertThat(out).contains("Zone: " + ZONE.getZone()); + assertThat(out).contains("Cache type: " + CACHE_TYPE); + assertThat(out).contains("State: running"); + + // Test list Rapid Caches + RapidCacheList.rapidCacheList(bucketName); + assertThat(newOutput()).contains(cacheName); + + // Test update Rapid Cache + RapidCacheUpdate.rapidCacheUpdate(bucketName, cacheId, 172800); + out = newOutput(); + assertThat(out).contains("Updated Rapid Cache: " + cacheName); + assertThat(out).contains("TTL: 172800 seconds"); + + // Test disable Rapid Cache. The client's default LRO polling timeout is 5 minutes, whereas full + // cache removal can take over an hour, though the cache enters the "disabled" state within + // seconds. + try { + RapidCacheDisable.rapidCacheDisable(bucketName, cacheId); + cacheActive = false; + assertThat(newOutput()).contains("Disabled Rapid Cache: " + cacheName); + } catch (CancellationException e) { + // The client stopped polling the operation, which is still running on the server. + cacheActive = false; + newOutput(); + RapidCacheGet.rapidCacheGet(bucketName, cacheId); + assertThat(newOutput()).contains("State: disabled"); + } + } + + /** + * Used in teardown: starts disabling the Rapid Cache without waiting for the operation, ignoring + * errors (for example, if the cache was never created). + */ + private void disableQuietly() { + try (StorageControlClient storageControl = StorageControlClient.create()) { + storageControl + .disableRapidCacheAsync(RapidCacheName.format("_", bucketName, cacheId)) + .getInitialFuture() + .get(1, TimeUnit.MINUTES); + } catch (Exception e) { + System.err.printf("Failed to disable Rapid Cache in bucket %s: %s%n", bucketName, e); + } + } + + /** Returns the output captured since the previous call. */ + private String newOutput() { + String all = stdOut.getCapturedOutputAsUtf8String(); + String out = all.substring(outputOffset); + outputOffset = all.length(); + return out; + } +}