From 1d6a53f0c37eaff68e02383c63db166249451543 Mon Sep 17 00:00:00 2001 From: BenWhitehead Date: Mon, 24 Jul 2023 17:42:09 -0400 Subject: [PATCH] docs: preliminary javadocs --- .../cloud/storage/BlobWriteSession.java | 43 +++++++++++++++++ .../cloud/storage/BlobWriteSessionConfig.java | 15 ++++++ .../storage/BlobWriteSessionConfigs.java | 19 ++++++++ .../DefaultBlobWriteSessionConfig.java | 30 +++++++++++- .../cloud/storage/GrpcStorageOptions.java | 13 ++++- .../com/google/cloud/storage/Storage.java | 48 ++++++++++++++++++- .../com/google/cloud/storage/StorageImpl.java | 9 ---- .../storage/it/ITBlobWriteSessionTest.java | 3 +- .../runner/registry/AbstractStorageProxy.java | 6 --- 9 files changed, 166 insertions(+), 20 deletions(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSession.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSession.java index a734791ba1..02ea23a6a7 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSession.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSession.java @@ -21,10 +21,53 @@ import java.io.IOException; import java.nio.channels.WritableByteChannel; +/** + * A session to write an object to Google Cloud Storage. + * + *

A session can only write a single version of an object. If writing multiple versions of an + * object a new session must be created each time. + * + *

Provides an api that allows writing to and retrieving the resulting {@link BlobInfo} after + * write finalization. + * + *

The underlying implementation is dictated based upon the specified {@link + * BlobWriteSessionConfig} provided at {@link StorageOptions} creation time. + * + * @see GrpcStorageOptions.Builder#setBlobWriteSessionConfig(BlobWriteSessionConfig) + * @see BlobWriteSessionConfig + * @see BlobWriteSessionConfigs + * @since 2.26.0 This new api is in preview and is subject to breaking changes. + */ @BetaApi public interface BlobWriteSession { + /** + * Open the {@link WritableByteChannel} for this session. + * + *

A session may only be {@code open}ed once. If multiple calls to open are made, an illegal + * state exception will be thrown + * + *

Upon calling {@link WritableByteChannel#close()} the object creation will be finalized, and + * {@link #getResult()}s future should resolve. + * + * @throws IOException When creating the {@link WritableByteChannel} if an unrecoverable + * underlying IOException occurs it can be rethrown + * @throws IllegalStateException if open is called more than once + * @since 2.26.0 This new api is in preview and is subject to breaking changes. + */ + @BetaApi WritableByteChannel open() throws IOException; + /** + * Return an {@link ApiFuture}{@code } which will represent the state of the object upon + * finalization and success response from Google Cloud Storage. + * + *

This future will not resolve until: 1. The object is successfully finalized and created in + * Google Cloud Storage 2. A terminal failure occurs, the terminal failure will become the + * exception result + * + * @since 2.26.0 This new api is in preview and is subject to breaking changes. + */ + @BetaApi ApiFuture getResult(); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSessionConfig.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSessionConfig.java index 19c6086549..de8622c754 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSessionConfig.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSessionConfig.java @@ -18,12 +18,27 @@ import com.google.api.core.InternalApi; import com.google.cloud.storage.Conversions.Decoder; +import com.google.cloud.storage.Storage.BlobWriteOption; import com.google.cloud.storage.UnifiedOpts.ObjectTargetOpt; import com.google.cloud.storage.UnifiedOpts.Opts; import com.google.storage.v2.WriteObjectResponse; import java.io.IOException; import java.time.Clock; +/** + * A sealed internal implementation only class which provides the means of configuring a {@link + * BlobWriteSession}. + * + *

A {@code BlobWriteSessionConfig} will be used to configure all {@link BlobWriteSession}s + * produced by an instance of {@link Storage}. + * + * @see BlobWriteSessionConfigs + * @see GrpcStorageOptions.Builder#setBlobWriteSessionConfig(BlobWriteSessionConfig) + * @see Storage#blobWriteSession(BlobInfo, BlobWriteOption...) + * @since 2.26.0 This new api is in preview and is subject to breaking changes. + */ +// When we have java modules, actually seal this to internal extension only +@InternalApi public abstract class BlobWriteSessionConfig { @InternalApi diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSessionConfigs.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSessionConfigs.java index 0faf6e69b9..cc5e691e6b 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSessionConfigs.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobWriteSessionConfigs.java @@ -17,12 +17,31 @@ package com.google.cloud.storage; import com.google.api.core.BetaApi; +import com.google.cloud.storage.GrpcStorageOptions.GrpcStorageDefaults; +import com.google.cloud.storage.Storage.BlobWriteOption; +/** + * Factory class to select and construct {@link BlobWriteSessionConfig}s. + * + * @see BlobWriteSessionConfig + * @see GrpcStorageOptions.Builder#setBlobWriteSessionConfig(BlobWriteSessionConfig) + * @see Storage#blobWriteSession(BlobInfo, BlobWriteOption...) + * @since 2.26.0 This new api is in preview and is subject to breaking changes. + */ @BetaApi public final class BlobWriteSessionConfigs { private BlobWriteSessionConfigs() {} + /** + * Factory to produce the default configuration for uploading an object to Cloud Storage. + * + *

Configuration of the chunk size can be performed via {@link + * DefaultBlobWriteSessionConfig#withChunkSize(int)}. + * + * @see GrpcStorageDefaults#getDefaultStorageWriterConfig() + * @since 2.26.0 This new api is in preview and is subject to breaking changes. + */ @BetaApi public static DefaultBlobWriteSessionConfig getDefault() { return new DefaultBlobWriteSessionConfig(ByteSizeConstants._16MiB); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/DefaultBlobWriteSessionConfig.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/DefaultBlobWriteSessionConfig.java index 49427a9ef4..2cc08a0d3f 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/DefaultBlobWriteSessionConfig.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/DefaultBlobWriteSessionConfig.java @@ -32,13 +32,23 @@ import javax.annotation.concurrent.Immutable; /** - * Configure a writer which is logically equivalent to the following: + * Default Configuration to represent uploading to Google Cloud Storage in a chunked manner. + * + *

Perform a resumable upload, uploading at most {@code chunkSize} bytes each PUT. + * + *

Configuration of chunk size can be performed via {@link + * DefaultBlobWriteSessionConfig#withChunkSize(int)}. + * + *

An instance of this class will provide a {@link BlobWriteSession} is logically equivalent to + * the following: * *

{@code
  * Storage storage = ...;
  * WriteChannel writeChannel = storage.writer(BlobInfo, BlobWriteOption);
  * writeChannel.setChunkSize(chunkSize);
  * }
+ * + * @since 2.26.0 This new api is in preview and is subject to breaking changes. */ @Immutable @BetaApi @@ -51,10 +61,28 @@ public final class DefaultBlobWriteSessionConfig extends BlobWriteSessionConfig this.chunkSize = chunkSize; } + /** + * The number of bytes each chunk can be. + * + *

Default: {@code 16777216 (16 MiB)} + * + * @see #withChunkSize(int) + * @since 2.26.0 This new api is in preview and is subject to breaking changes. + */ public int getChunkSize() { return chunkSize; } + /** + * Create a new instance with the {@code chunkSize} set to the specified value. + * + *

Default: {@code 16777216 (16 MiB)} + * + * @param chunkSize The number of bytes each chunk should be. Must be >= {@code 262144 (256 KiB)} + * @return The new instance + * @see #getChunkSize() + * @since 2.26.0 This new api is in preview and is subject to breaking changes. + */ @BetaApi public DefaultBlobWriteSessionConfig withChunkSize(int chunkSize) { Preconditions.checkArgument( diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageOptions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageOptions.java index 8728e59fec..8bb3115c52 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageOptions.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageOptions.java @@ -42,6 +42,7 @@ import com.google.cloud.Tuple; import com.google.cloud.grpc.GrpcTransportOptions; import com.google.cloud.spi.ServiceRpcFactory; +import com.google.cloud.storage.Storage.BlobWriteOption; import com.google.cloud.storage.TransportCompatibility.Transport; import com.google.cloud.storage.UnifiedOpts.Opts; import com.google.cloud.storage.UnifiedOpts.UserProject; @@ -511,9 +512,15 @@ public GrpcStorageOptions.Builder setGrpcInterceptorProvider( return this; } - /** @since 2.24.0 This new api is in preview and is subject to breaking changes. */ + /** + * @see BlobWriteSessionConfig + * @see BlobWriteSessionConfigs + * @see Storage#blobWriteSession(BlobInfo, BlobWriteOption...) + * @see GrpcStorageDefaults#getDefaultStorageWriterConfig() + * @since 2.26.0 This new api is in preview and is subject to breaking changes. + */ @BetaApi - public GrpcStorageOptions.Builder setStorageWriterConfig( + public GrpcStorageOptions.Builder setBlobWriteSessionConfig( @NonNull BlobWriteSessionConfig blobWriteSessionConfig) { requireNonNull(blobWriteSessionConfig, "blobWriteSessionConfig must be non null"); this.blobWriteSessionConfig = blobWriteSessionConfig; @@ -584,6 +591,8 @@ public GrpcInterceptorProvider grpcInterceptorProvider() { return INTERCEPTOR_PROVIDER; } + /** @since 2.26.0 This new api is in preview and is subject to breaking changes. */ + @BetaApi public BlobWriteSessionConfig getDefaultStorageWriterConfig() { return BlobWriteSessionConfigs.getDefault(); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 69aade09bf..0372957788 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -16,6 +16,8 @@ package com.google.cloud.storage; +import static com.google.cloud.storage.CrossTransportUtils.fmtMethodName; +import static com.google.cloud.storage.CrossTransportUtils.throwGrpcOnly; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static java.util.Objects.requireNonNull; @@ -4616,7 +4618,51 @@ List testIamPermissions( @Override default void close() throws Exception {} + /** + * Create a new {@link BlobWriteSession} for the specified {@code blobInfo} and {@code options}. + * + *

The returned {@code BlobWriteSession} can be used to write an individual version, a new + * session must be created each time you want to create a new version. + * + *

By default, any MD5 value in the provided {@code blobInfo} is ignored unless the option + * {@link BlobWriteOption#md5Match()} is included in {@code options}. + * + *

By default, any CRC32c value in the provided {@code blobInfo} is ignored unless the option + * {@link BlobWriteOption#crc32cMatch()} is included in {@code options}. + * + *

Example of creating an object using {@code BlobWriteSession}:

+ * + *
{@code
+   * String bucketName = "my-unique-bucket";
+   * String blobName = "my-blob-name";
+   * BlobId blobId = BlobId.of(bucketName, blobName);
+   * BlobInfo blobInfo = BlobInfo.newBuilder(blobId).build();
+   * ReadableByteChannel readableByteChannel = ...;
+   * BlobWriteSession blobWriteSession = storage.blobWriteSession(blobInfo, BlobWriteOption.doesNotExist());
+   *
+   * // open the channel for writing
+   * try (WritableByteChannel writableByteChannel = blobWriteSession.open()) {
+   *   // copy all bytes
+   *   ByteStreams.copy(readableByteChannel, writableByteChannel);
+   * } catch (IOException e) {
+   *   // handle IOException
+   * }
+   *
+   * // get the resulting object metadata
+   * ApiFuture resultFuture = blobWriteSession.getResult();
+   * BlobInfo gen1 = resultFuture.get();
+   * }
+ * + * @param blobInfo blob to create + * @param options blob write options + * @since 2.26.0 This new api is in preview and is subject to breaking changes. + * @see BlobWriteSessionConfig + * @see BlobWriteSessionConfigs + * @see GrpcStorageOptions.Builder#setBlobWriteSessionConfig(BlobWriteSessionConfig) + */ @BetaApi @TransportCompatibility({Transport.GRPC}) - BlobWriteSession blobWriteSession(BlobInfo info, BlobWriteOption... options); + default BlobWriteSession blobWriteSession(BlobInfo blobInfo, BlobWriteOption... options) { + return throwGrpcOnly(fmtMethodName("blobWriteSession", BlobInfo.class, BlobWriteOption.class)); + } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index 5e379e2c91..d4ad26015f 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -16,8 +16,6 @@ package com.google.cloud.storage; -import static com.google.cloud.storage.CrossTransportUtils.fmtMethodName; -import static com.google.cloud.storage.CrossTransportUtils.throwGrpcOnly; import static com.google.cloud.storage.SignedUrlEncodingHelper.Rfc3986UriEncode; import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Preconditions.checkArgument; @@ -26,7 +24,6 @@ import static java.util.concurrent.Executors.callable; import com.google.api.core.ApiFuture; -import com.google.api.core.BetaApi; import com.google.api.gax.paging.Page; import com.google.api.gax.retrying.ResultRetryAlgorithm; import com.google.api.services.storage.model.BucketAccessControl; @@ -1565,12 +1562,6 @@ public boolean deleteNotification(final String bucket, final String notification Function.identity()); } - @BetaApi - @Override - public BlobWriteSession blobWriteSession(BlobInfo info, BlobWriteOption... options) { - return throwGrpcOnly(fmtMethodName("blobWriteSession", BlobInfo.class, BlobWriteOption.class)); - } - @Override public HttpStorageOptions getOptions() { return (HttpStorageOptions) super.getOptions(); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteSessionTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteSessionTest.java index 986e5c85d6..aa73cd23ea 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteSessionTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteSessionTest.java @@ -61,7 +61,8 @@ public void overrideDefaultBufferSize() throws Exception { GrpcStorageOptions options = ((GrpcStorageOptions) storage.getOptions()) .toBuilder() - .setStorageWriterConfig(BlobWriteSessionConfigs.getDefault().withChunkSize(256 * 1024)) + .setBlobWriteSessionConfig( + BlobWriteSessionConfigs.getDefault().withChunkSize(256 * 1024)) .build(); try (Storage s = options.getService()) { doTest(s); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/AbstractStorageProxy.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/AbstractStorageProxy.java index f46039d3db..11440cb190 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/AbstractStorageProxy.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/AbstractStorageProxy.java @@ -25,7 +25,6 @@ import com.google.cloud.storage.Blob; import com.google.cloud.storage.BlobId; import com.google.cloud.storage.BlobInfo; -import com.google.cloud.storage.BlobWriteSession; import com.google.cloud.storage.Bucket; import com.google.cloud.storage.BucketInfo; import com.google.cloud.storage.CopyWriter; @@ -479,11 +478,6 @@ public boolean deleteNotification(String bucket, String notificationId) { return delegate.deleteNotification(bucket, notificationId); } - @Override - public BlobWriteSession blobWriteSession(BlobInfo info, BlobWriteOption... options) { - return delegate.blobWriteSession(info, options); - } - @Override public void close() throws Exception { delegate.close();