Skip to content

Commit

Permalink
Add support for batches to DNS (#940)
Browse files Browse the repository at this point in the history
  • Loading branch information
mziccard committed Apr 20, 2016
1 parent 5e0de55 commit e213176
Show file tree
Hide file tree
Showing 20 changed files with 3,942 additions and 153 deletions.
108 changes: 108 additions & 0 deletions gcloud-java-core/src/main/java/com/google/cloud/BatchResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* 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.google.cloud;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import java.util.LinkedList;
import java.util.List;

/**
* This class holds a single result of a batch call. The class is not thread-safe.
*
* @param <T> the type of the result
* @param <E> the type of the service-dependent exception thrown when a processing error occurs
*
*/
public abstract class BatchResult<T, E extends BaseServiceException> {

private T result;
private boolean completed = false;
private E error;
private final List<Callback<T, E>> toBeNotified = new LinkedList<>();

/**
* Returns {@code true} if the batch has been completed and the result is available; {@code false}
* otherwise.
*/
public boolean completed() {
return completed;
}

/**
* Returns the result of this call.
*
* @throws IllegalStateException if the batch has not been completed yet
* @throws E if an error occurred when processing the batch request
*/
public T get() throws E {
checkState(completed(), "Batch has not been completed yet");
if (error != null) {
throw error;
}
return result;
}

/**
* Adds a callback for the batch operation.
*
* @throws IllegalStateException if the batch has been completed already
*/
public void notify(Callback<T, E> callback) {
checkState(!completed, "The batch has been completed. All the calls to the notify()"
+ " method should be done prior to submitting the batch.");
toBeNotified.add(callback);
}

/**
* Sets an error and status as completed. Notifies all callbacks.
*/
protected void error(E error) {
this.error = checkNotNull(error);
this.completed = true;
for (Callback<T, E> callback : toBeNotified) {
callback.error(error);
}
}

/**
* Sets a result and status as completed. Notifies all callbacks.
*/
protected void success(T result) {
this.result = result;
this.completed = true;
for (Callback<T, E> callback : toBeNotified) {
callback.success(result);
}
}

/**
* An interface for the batch callbacks.
*/
public interface Callback<T, E> {
/**
* The method to be called when the batched operation succeeds.
*/
void success(T result);

/**
* The method to be called when the batched operation fails.
*/
void error(E exception);
}
}
113 changes: 113 additions & 0 deletions gcloud-java-core/src/test/java/com/google/cloud/BatchResultTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* 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.google.cloud;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;

public class BatchResultTest {

private BatchResult<Boolean, BaseServiceException> result;

@Before
public void setUp() {
result = new BatchResult<Boolean, BaseServiceException>() {};
}

@Test
public void testSuccess() {
assertFalse(result.completed());
try {
result.get();
fail("This was not completed yet.");
} catch (IllegalStateException ex) {
// expected
}
result.success(true);
assertTrue(result.get());
// test that null is allowed
result.success(null);
}

@Test
public void testError() {
assertFalse(result.completed());
try {
result.get();
fail("This was not completed yet.");
} catch (IllegalStateException ex) {
// expected
}
try {
result.error(null);
fail();
} catch (NullPointerException exc) {
// expected
}
BaseServiceException ex = new BaseServiceException(0, "message", "reason", false);
result.error(ex);
try {
result.get();
fail("This is a failed operation and should have thrown a DnsException.");
} catch (BaseServiceException real) {
assertSame(ex, real);
}
}

@Test
public void testNotifyError() {
final BaseServiceException ex = new BaseServiceException(0, "message", "reason", false);
assertFalse(result.completed());
BatchResult.Callback<Boolean, BaseServiceException> callback =
EasyMock.createStrictMock(BatchResult.Callback.class);
callback.error(ex);
EasyMock.replay(callback);
result.notify(callback);
result.error(ex);
try {
result.notify(callback);
fail("The batch has been completed.");
} catch (IllegalStateException exception) {
// expected
}
EasyMock.verify(callback);
}

@Test
public void testNotifySuccess() {
assertFalse(result.completed());
BatchResult.Callback<Boolean, BaseServiceException> callback =
EasyMock.createStrictMock(BatchResult.Callback.class);
callback.success(true);
EasyMock.replay(callback);
result.notify(callback);
result.success(true);
try {
result.notify(callback);
fail("The batch has been completed.");
} catch (IllegalStateException exception) {
// expected
}
EasyMock.verify(callback);
}
}
5 changes: 5 additions & 0 deletions gcloud-java-dns/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>gcloud-java-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ public ChangeRequest reload(Dns.ChangeRequestOption... options) {

/**
* Returns {@code true} if the change request has been completed. If the status is not {@link
* Status#DONE} already, the method makes an API call to Google Cloud DNS to update the change
* request first.
* ChangeRequestInfo.Status#DONE} already, the method makes an API call to Google Cloud DNS to
* update the change request first.
*
* @throws DnsException upon failure of the API call or if the associated zone was not found
*/
Expand Down
5 changes: 5 additions & 0 deletions gcloud-java-dns/src/main/java/com/google/cloud/dns/Dns.java
Original file line number Diff line number Diff line change
Expand Up @@ -503,4 +503,9 @@ ChangeRequest getChangeRequest(String zoneName, String changeRequestId,
* @see <a href="https://cloud.google.com/dns/api/v1/changes/list">Cloud DNS Chages: list</a>
*/
Page<ChangeRequest> listChangeRequests(String zoneName, ChangeRequestListOption... options);

/**
* Creates a new empty batch for grouping multiple service calls in one underlying RPC call.
*/
DnsBatch batch();
}
Loading

0 comments on commit e213176

Please sign in to comment.