-
Notifications
You must be signed in to change notification settings - Fork 467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create DynamoDB tables on On-Demand billing mode by default. #854
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,17 +29,31 @@ public interface LeaseRefresher { | |
|
||
/** | ||
* Creates the table that will store leases. Succeeds if table already exists. | ||
* | ||
* Deprecated. Use createLeaseTableIfNotExists(). | ||
* | ||
* @param readCapacity | ||
* @param writeCapacity | ||
* | ||
* @return true if we created a new table (table didn't exist before) | ||
* | ||
* @throws ProvisionedThroughputException if we cannot create the lease table due to per-AWS-account capacity | ||
* restrictions. | ||
* @throws DependencyException if DynamoDB createTable fails in an unexpected way | ||
*/ | ||
@Deprecated | ||
boolean createLeaseTableIfNotExists(Long readCapacity, Long writeCapacity) | ||
throws ProvisionedThroughputException, DependencyException; | ||
|
||
/** | ||
* Creates the table that will store leases. Succeeds if table already exists. | ||
* | ||
* @return true if we created a new table (table didn't exist before) | ||
* | ||
* @throws ProvisionedThroughputException if we cannot create the lease table due to per-AWS-account capacity | ||
* restrictions. | ||
* @throws DependencyException if DynamoDB createTable fails in an unexpected way | ||
*/ | ||
boolean createLeaseTableIfNotExists(Long readCapacity, Long writeCapacity) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a public interface customers might be using; let's not mess with these signatures. We can make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ya, kept this and marked as deprecated. |
||
boolean createLeaseTableIfNotExists() | ||
throws ProvisionedThroughputException, DependencyException; | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -211,10 +211,9 @@ public void run() { | |
@Override | ||
public void initialize() throws ProvisionedThroughputException, DependencyException, IllegalStateException { | ||
final boolean newTableCreated = | ||
leaseRefresher.createLeaseTableIfNotExists(initialLeaseTableReadCapacity, initialLeaseTableWriteCapacity); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be a unit test in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no |
||
leaseRefresher.createLeaseTableIfNotExists(); | ||
if (newTableCreated) { | ||
log.info("Created new lease table for coordinator with initial read capacity of {} and write capacity of {}.", | ||
initialLeaseTableReadCapacity, initialLeaseTableWriteCapacity); | ||
log.info("Created new lease table for coordinator with pay per request billing mode."); | ||
} | ||
// Need to wait for table in active state. | ||
final long secondsBetweenPolls = 10L; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -130,7 +130,7 @@ public DynamoDBLeaseRefresher(final String table, final DynamoDbAsyncClient dyna | |
public DynamoDBLeaseRefresher(final String table, final DynamoDbAsyncClient dynamoDBClient, | ||
final LeaseSerializer serializer, final boolean consistentReads, | ||
@NonNull final TableCreatorCallback tableCreatorCallback, Duration dynamoDbRequestTimeout) { | ||
this(table, dynamoDBClient, serializer, consistentReads, tableCreatorCallback, dynamoDbRequestTimeout, BillingMode.PROVISIONED); | ||
this(table, dynamoDBClient, serializer, consistentReads, tableCreatorCallback, dynamoDbRequestTimeout, BillingMode.PAY_PER_REQUEST); | ||
} | ||
|
||
/** | ||
|
@@ -162,16 +162,7 @@ public DynamoDBLeaseRefresher(final String table, final DynamoDbAsyncClient dyna | |
@Override | ||
public boolean createLeaseTableIfNotExists(@NonNull final Long readCapacity, @NonNull final Long writeCapacity) | ||
throws ProvisionedThroughputException, DependencyException { | ||
try { | ||
if (tableStatus() != null) { | ||
return newTableCreated; | ||
} | ||
} catch (DependencyException de) { | ||
// | ||
// Something went wrong with DynamoDB | ||
// | ||
log.error("Failed to get table status for {}", table, de); | ||
} | ||
// DynamoDB is now created in PayPerRequest billing mode by default. Keeping this for backward compatibility. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leaving this up to your preference, but I personally don't think this comment is needed since it's mentioned the interface's javadoc. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ya, updated interface's javadoc to include this. |
||
ProvisionedThroughput throughput = ProvisionedThroughput.builder().readCapacityUnits(readCapacity) | ||
.writeCapacityUnits(writeCapacity).build(); | ||
final CreateTableRequest request; | ||
|
@@ -185,6 +176,34 @@ public boolean createLeaseTableIfNotExists(@NonNull final Long readCapacity, @No | |
.build(); | ||
} | ||
|
||
return createTableIfNotExists(request); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
public boolean createLeaseTableIfNotExists() | ||
throws ProvisionedThroughputException, DependencyException { | ||
final CreateTableRequest request = CreateTableRequest.builder().tableName(table).keySchema(serializer.getKeySchema()) | ||
.attributeDefinitions(serializer.getAttributeDefinitions()) | ||
.billingMode(billingMode).build(); | ||
|
||
return createTableIfNotExists(request); | ||
} | ||
|
||
private boolean createTableIfNotExists(CreateTableRequest request) | ||
throws ProvisionedThroughputException, DependencyException { | ||
try { | ||
if (tableStatus() != null) { | ||
return newTableCreated; | ||
} | ||
} catch (DependencyException de) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know this is the existing behavior but I'm wondering why we don't throw this exception here. Seems like it makes more sense to fail here if we're not able to pull the lease table's status and let the caller decide how to proceed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wondered the same while rewriting this function why the exception was consumed. I think it was done as CreateTable call will fail with |
||
// | ||
// Something went wrong with DynamoDB | ||
// | ||
log.error("Failed to get table status for {}", table, de); | ||
} | ||
|
||
final AWSExceptionManager exceptionManager = createExceptionManager(); | ||
exceptionManager.add(ResourceInUseException.class, t -> t); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,7 @@ | |
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.TimeoutException; | ||
|
||
import org.junit.Assert; | ||
import org.junit.Before; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
|
@@ -265,7 +266,40 @@ public void testLeaseTableExistsTimesOut() throws Exception { | |
} | ||
|
||
@Test | ||
public void testCreateLeaseTableTimesOut() throws Exception { | ||
public void testCreateLeaseTableProvisionedBillingModeIfNotExists() throws Exception { | ||
leaseRefresher = new DynamoDBLeaseRefresher(TABLE_NAME, dynamoDbClient, leaseSerializer, CONSISTENT_READS, | ||
tableCreatorCallback, LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT, BillingMode.PROVISIONED); | ||
|
||
when(dynamoDbClient.describeTable(any(DescribeTableRequest.class))).thenReturn(mockDescribeTableFuture); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we need to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, updated this as part of removing the |
||
when(mockDescribeTableFuture.get(anyLong(), any())) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, these came from the previous tests. Updated to use actual class objects. |
||
.thenThrow(ResourceNotFoundException.builder().message("Table doesn't exist").build()); | ||
|
||
when(dynamoDbClient.createTable(any(CreateTableRequest.class))).thenReturn(mockCreateTableFuture); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same with earlier comment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updated |
||
when(mockCreateTableFuture.get(anyLong(), any())).thenReturn(null); | ||
|
||
final boolean result = leaseRefresher.createLeaseTableIfNotExists(10L, 10L); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we verify interactions w/ the ddb client? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added, also for other dependencies. |
||
Assert.assertTrue(result); | ||
} | ||
|
||
@Test | ||
public void testCreateLeaseTableIfNotExists() throws Exception { | ||
when(dynamoDbClient.describeTable(any(DescribeTableRequest.class))).thenReturn(mockDescribeTableFuture); | ||
when(mockDescribeTableFuture.get(anyLong(), any())) | ||
.thenThrow(ResourceNotFoundException.builder().message("Table doesn't exist").build()); | ||
|
||
when(dynamoDbClient.createTable(any(CreateTableRequest.class))).thenReturn(mockCreateTableFuture); | ||
when(mockCreateTableFuture.get(anyLong(), any())).thenReturn(null); | ||
|
||
final boolean result = leaseRefresher.createLeaseTableIfNotExists(); | ||
|
||
Assert.assertTrue(result); | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We've only tested the cases where the table doesn't exist (i.e DescribeTable
CreateTable
As with the earlier comment, we should also be verifying interactions between dependencies. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For DescribeTable, I have kept the existing behavior and added a tests for all above. |
||
@Test | ||
public void testCreateLeaseTableProvisionedBillingModeTimesOut() throws Exception { | ||
leaseRefresher = new DynamoDBLeaseRefresher(TABLE_NAME, dynamoDbClient, leaseSerializer, CONSISTENT_READS, | ||
tableCreatorCallback, LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT, BillingMode.PROVISIONED); | ||
TimeoutException te = setRuleForDependencyTimeout(); | ||
|
||
when(dynamoDbClient.describeTable(any(DescribeTableRequest.class))).thenReturn(mockDescribeTableFuture); | ||
|
@@ -279,10 +313,7 @@ public void testCreateLeaseTableTimesOut() throws Exception { | |
} | ||
|
||
@Test | ||
public void testCreateLeaseTableBillingMode() throws Exception { | ||
leaseRefresher = new DynamoDBLeaseRefresher(TABLE_NAME, dynamoDbClient, leaseSerializer, CONSISTENT_READS, | ||
tableCreatorCallback, LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT, BillingMode.PAY_PER_REQUEST); | ||
|
||
public void testCreateLeaseTableTimesOut() throws Exception { | ||
TimeoutException te = setRuleForDependencyTimeout(); | ||
|
||
when(dynamoDbClient.describeTable(any(DescribeTableRequest.class))).thenReturn(mockDescribeTableFuture); | ||
|
@@ -292,7 +323,7 @@ public void testCreateLeaseTableBillingMode() throws Exception { | |
when(dynamoDbClient.createTable(any(CreateTableRequest.class))).thenReturn(mockCreateTableFuture); | ||
when(mockCreateTableFuture.get(anyLong(), any())).thenThrow(te); | ||
|
||
verifyCancel(mockCreateTableFuture, () -> leaseRefresher.createLeaseTableIfNotExists(10L, 10L)); | ||
verifyCancel(mockCreateTableFuture, () -> leaseRefresher.createLeaseTableIfNotExists()); | ||
} | ||
|
||
@FunctionalInterface | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use
@link
or javadoc annotation here to point people over to the new method, it makes it easier to find the correct method since it indexes in ides + links in documentation generatorsThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to
@link
.