Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.google.api.services.storage.model.Bucket;
import com.google.api.services.storage.model.BucketAccessControl;
import com.google.api.services.storage.model.HmacKeyMetadata;
import com.google.api.services.storage.model.Notification;
import com.google.api.services.storage.model.ObjectAccessControl;
import com.google.api.services.storage.model.Policy;
import com.google.api.services.storage.model.StorageObject;
Expand Down Expand Up @@ -243,4 +244,20 @@ public ResultRetryAlgorithm<?> getForResumableUploadSessionWrite(
public ResultRetryAlgorithm<?> getForServiceAccountGet(String pb) {
return retryStrategy.getIdempotentHandler();
}

public ResultRetryAlgorithm<?> getForNotificationCreate(String bucket, Notification pb) {
return retryStrategy.getNonidempotentHandler();
}

public ResultRetryAlgorithm<?> getForNotificationGet(String bucket, String notificationId) {
return retryStrategy.getIdempotentHandler();
}

public ResultRetryAlgorithm<?> getForNotificationList(String bucket) {
return retryStrategy.getIdempotentHandler();
}

public ResultRetryAlgorithm<?> getForNotificationDelete(String bucket, String notificationId) {
return retryStrategy.getIdempotentHandler();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.google.cloud.storage;

import static com.google.cloud.RetryHelper.runWithRetries;
import static com.google.cloud.storage.SignedUrlEncodingHelper.Rfc3986UriEncode;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
Expand All @@ -36,7 +35,6 @@
import com.google.cloud.PageImpl.NextPageFetcher;
import com.google.cloud.Policy;
import com.google.cloud.ReadChannel;
import com.google.cloud.RetryHelper.RetryHelperException;
import com.google.cloud.WriteChannel;
import com.google.cloud.storage.Acl.Entity;
import com.google.cloud.storage.HmacKey.HmacKeyMetadata;
Expand Down Expand Up @@ -1483,96 +1481,46 @@ public Notification createNotification(
final String bucket, final NotificationInfo notificationInfo) {
final com.google.api.services.storage.model.Notification notificationPb =
codecs.notificationInfo().encode(notificationInfo);
try {
return codecs
.notificationInfo()
.decode(
runWithRetries(
new Callable<com.google.api.services.storage.model.Notification>() {
@Override
public com.google.api.services.storage.model.Notification call() {
return storageRpc.createNotification(bucket, notificationPb);
}
},
getOptions().getRetrySettings(),
EXCEPTION_HANDLER,
getOptions().getClock()))
.asNotification(this);
} catch (RetryHelperException e) {
throw StorageException.translateAndThrow(e);
}
ResultRetryAlgorithm<?> algorithm =
retryAlgorithmManager.getForNotificationCreate(bucket, notificationPb);
return run(
algorithm,
() -> storageRpc.createNotification(bucket, notificationPb),
n -> codecs.notificationInfo().decode(n).asNotification(this));
}

@Override
public Notification getNotification(final String bucket, final String notificationId) {
try {
com.google.api.services.storage.model.Notification answer =
runWithRetries(
new Callable<com.google.api.services.storage.model.Notification>() {
@Override
public com.google.api.services.storage.model.Notification call() {
return storageRpc.getNotification(bucket, notificationId);
}
},
getOptions().getRetrySettings(),
EXCEPTION_HANDLER,
getOptions().getClock());
return answer == null ? null : codecs.notificationInfo().decode(answer).asNotification(this);
} catch (RetryHelperException e) {
throw StorageException.translateAndThrow(e);
}
ResultRetryAlgorithm<?> algorithm =
retryAlgorithmManager.getForNotificationGet(bucket, notificationId);
return run(
algorithm,
() -> storageRpc.getNotification(bucket, notificationId),
n -> codecs.notificationInfo().decode(n).asNotification(this));
}

@Override
public List<Notification> listNotifications(final String bucket) {
try {
List<com.google.api.services.storage.model.Notification> answer =
runWithRetries(
new Callable<List<com.google.api.services.storage.model.Notification>>() {
@Override
public List<com.google.api.services.storage.model.Notification> call() {
return storageRpc.listNotifications(bucket);
}
},
getOptions().getRetrySettings(),
EXCEPTION_HANDLER,
getOptions().getClock());
return answer == null
? ImmutableList.<Notification>of()
: Lists.transform(
answer,
new com.google.common.base.Function<
com.google.api.services.storage.model.Notification, Notification>() {
@Override
public Notification apply(
com.google.api.services.storage.model.Notification notificationPb) {
return codecs
.notificationInfo()
.decode(notificationPb)
.asNotification(getOptions().getService());
}
});
} catch (RetryHelperException e) {
throw StorageException.translateAndThrow(e);
}
ResultRetryAlgorithm<?> algorithm = retryAlgorithmManager.getForNotificationList(bucket);
List<Notification> result =
run(
algorithm,
() -> storageRpc.listNotifications(bucket),
(answer) ->
answer.stream()
.map(n -> codecs.notificationInfo().decode(n).asNotification(this))
.collect(ImmutableList.toImmutableList()));
return result == null ? ImmutableList.of() : result;
}

@Override
public boolean deleteNotification(final String bucket, final String notificationId) {
try {
return runWithRetries(
new Callable<Boolean>() {
@Override
public Boolean call() {
return storageRpc.deleteNotification(bucket, notificationId);
}
},
getOptions().getRetrySettings(),
EXCEPTION_HANDLER,
getOptions().getClock());
} catch (RetryHelperException e) {
throw StorageException.translateAndThrow(e);
}
ResultRetryAlgorithm<?> algorithm =
retryAlgorithmManager.getForNotificationDelete(bucket, notificationId);
return run(
algorithm,
() -> storageRpc.deleteNotification(bucket, notificationId),
Function.identity());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,18 @@
import com.google.cloud.storage.HmacKey;
import com.google.cloud.storage.HmacKey.HmacKeyMetadata;
import com.google.cloud.storage.HmacKey.HmacKeyState;
import com.google.cloud.storage.NotificationInfo;
import com.google.cloud.storage.NotificationInfo.PayloadFormat;
import com.google.cloud.storage.ServiceAccount;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.Storage.BlobTargetOption;
import com.google.cloud.storage.Storage.ComposeRequest;
import com.google.cloud.storage.conformance.retry.Functions.CtxFunction;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.pubsub.v1.TopicName;
import java.util.HashSet;
import java.util.Map;

/**
* Define a set of {@link CtxFunction} which are used in mappings as well as general setup/tear down
Expand Down Expand Up @@ -173,6 +178,28 @@ static final class ResourceSetup {
return s.withHmacKey(hmacKey1).with(hmacKey1.getMetadata());
});

static final CtxFunction pubsubTopic =
(ctx, c) -> {
String projectId = c.getProjectId();
TopicName name = TopicName.of(projectId, c.getTopicName());
return ctx.map(s -> s.with(name));
};

static final CtxFunction notification =
(ctx, c) ->
ctx.map(
state -> {
PayloadFormat format = PayloadFormat.JSON_API_V1;
Map<String, String> attributes = ImmutableMap.of("label1", "value1");
NotificationInfo notificationInfo =
NotificationInfo.newBuilder(state.getTopicName().toString())
.setCustomAttributes(attributes)
.setPayloadFormat(format)
.build();
return state.with(
ctx.getStorage().createNotification(c.getBucketName(), notificationInfo));
});

private static final CtxFunction processResources =
(ctx, c) -> {
HashSet<Resource> resources = newHashSet(c.getMethod().getResourcesList());
Expand All @@ -192,6 +219,11 @@ static final class ResourceSetup {
resources.remove(Resource.HMAC_KEY);
}

if (resources.contains(Resource.NOTIFICATION)) {
f = f.andThen(pubsubTopic).andThen(notification);
resources.remove(Resource.NOTIFICATION);
}

if (!resources.isEmpty()) {
throw new IllegalStateException(
String.format("Unhandled Method Resource [%s]", Joiner.on(", ").join(resources)));
Expand All @@ -204,6 +236,10 @@ static final class ResourceSetup {
(ctx, c) -> ctx.map(s -> s.with(Acl.of(User.ofAllUsers(), Role.READER)));

static final CtxFunction defaultSetup = processResources.andThen(allUsersReaderAcl);

static final CtxFunction pubsubTopicSetup = defaultSetup.andThen(pubsubTopic);

static final CtxFunction notificationSetup = pubsubTopicSetup.andThen(notification);
}

static final class ResourceTeardown {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ public static Collection<Object[]> testCases() throws IOException {
.setHost(TEST_BENCH.getBaseUri().replaceAll("https?://", ""))
.setTestAllowFilter(
RetryTestCaseResolver.includeAll()
.and(RetryTestCaseResolver.specificMappings(246, 247, 248, 249))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to remove this predicate before merging

// .and(RetryTestCaseResolver.specificMappings(44, 45))
.and(
(m, trc) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package com.google.cloud.storage.conformance.retry;

import static com.google.cloud.storage.conformance.retry.CtxFunctions.ResourceSetup.defaultSetup;
import static com.google.cloud.storage.conformance.retry.CtxFunctions.ResourceSetup.notificationSetup;
import static com.google.cloud.storage.conformance.retry.CtxFunctions.ResourceSetup.pubsubTopicSetup;
import static com.google.cloud.storage.conformance.retry.CtxFunctions.ResourceSetup.serviceAccount;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.not;
Expand All @@ -36,6 +38,8 @@
import com.google.cloud.storage.HmacKey.HmacKeyMetadata;
import com.google.cloud.storage.HmacKey.HmacKeyState;
import com.google.cloud.storage.HttpMethod;
import com.google.cloud.storage.NotificationInfo;
import com.google.cloud.storage.NotificationInfo.PayloadFormat;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.Storage.BlobGetOption;
import com.google.cloud.storage.Storage.BlobSourceOption;
Expand All @@ -55,6 +59,7 @@
import com.google.cloud.storage.conformance.retry.RpcMethod.storage.buckets;
import com.google.cloud.storage.conformance.retry.RpcMethod.storage.default_object_acl;
import com.google.cloud.storage.conformance.retry.RpcMethod.storage.hmacKey;
import com.google.cloud.storage.conformance.retry.RpcMethod.storage.notifications;
import com.google.cloud.storage.conformance.retry.RpcMethod.storage.object_acl;
import com.google.cloud.storage.conformance.retry.RpcMethod.storage.objects;
import com.google.cloud.storage.conformance.retry.RpcMethod.storage.serviceaccount;
Expand Down Expand Up @@ -89,6 +94,8 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.OptionalInt;
import java.util.Set;
Expand Down Expand Up @@ -897,13 +904,80 @@ private static void create(ArrayList<RpcMethodMapping> a) {

static final class Notification {

private static void delete(ArrayList<RpcMethodMapping> a) {}
private static void delete(ArrayList<RpcMethodMapping> a) {
a.add(
RpcMethodMapping.newBuilder(248, notifications.delete)
.withSetup(notificationSetup)
.withTest(
(ctx, c) ->
ctx.map(
state -> {
boolean success =
ctx.getStorage()
.deleteNotification(
state.getBucket().getName(),
state.getNotification().getNotificationId());
assertTrue(success);
return state.with(success);
}))
.build());
}

private static void get(ArrayList<RpcMethodMapping> a) {}
private static void get(ArrayList<RpcMethodMapping> a) {
a.add(
RpcMethodMapping.newBuilder(246, notifications.get)
.withSetup(notificationSetup)
.withTest(
(ctx, c) ->
ctx.map(
state -> {
com.google.cloud.storage.Notification notification =
ctx.getStorage()
.getNotification(
state.getBucket().getName(),
state.getNotification().getNotificationId());
return state.with(notification);
}))
.build());
}

private static void insert(ArrayList<RpcMethodMapping> a) {}
private static void insert(ArrayList<RpcMethodMapping> a) {
a.add(
RpcMethodMapping.newBuilder(247, notifications.insert)
.withSetup(pubsubTopicSetup)
.withTest(
(ctx, c) ->
ctx.map(
state -> {
PayloadFormat format = PayloadFormat.JSON_API_V1;
Map<String, String> attributes = ImmutableMap.of("label1", "value1");
NotificationInfo info =
NotificationInfo.newBuilder(state.getTopicName().toString())
.setPayloadFormat(format)
.setCustomAttributes(attributes)
.build();
com.google.cloud.storage.Notification notification =
ctx.getStorage()
.createNotification(state.getBucket().getName(), info);
return state.with(notification);
}))
.build());
}

private static void list(ArrayList<RpcMethodMapping> a) {}
private static void list(ArrayList<RpcMethodMapping> a) {
a.add(
RpcMethodMapping.newBuilder(249, notifications.list)
.withSetup(pubsubTopicSetup)
.withTest(
(ctx, c) ->
ctx.map(
state -> {
List<com.google.cloud.storage.Notification> notifications =
ctx.getStorage().listNotifications(state.getBucket().getName());
return state.with(notifications);
}))
.build());
}
}

static final class ObjectAcl {
Expand Down
Loading