Create DynamoDB tables on On-Demand billing mode by default. (#854)
* Create DynamoDB tables on On-Demand billing mode by default. This will enable KCL to create the DynamoDB tables - Lease and ShardProgress with the On-Demand billing mode instead of provisioned billing mode. * Keep previous table creation function for backward compatibility. * Added unit tests. * Added more unit tests.
This commit is contained in:
parent
2447513de3
commit
e81969af59
11 changed files with 294 additions and 29 deletions
|
|
@ -196,7 +196,7 @@ public class LeaseManagementConfig {
|
||||||
|
|
||||||
private Duration dynamoDbRequestTimeout = DEFAULT_REQUEST_TIMEOUT;
|
private Duration dynamoDbRequestTimeout = DEFAULT_REQUEST_TIMEOUT;
|
||||||
|
|
||||||
private BillingMode billingMode = BillingMode.PROVISIONED;
|
private BillingMode billingMode = BillingMode.PAY_PER_REQUEST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frequency (in millis) of the auditor job to scan for partial leases in the lease table.
|
* Frequency (in millis) of the auditor job to scan for partial leases in the lease table.
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,24 @@ public interface LeaseRefresher {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the table that will store leases. Succeeds if table already exists.
|
* Creates the table that will store leases. Succeeds if table already exists.
|
||||||
*
|
* Deprecated. Use {@link #createLeaseTableIfNotExists()}.
|
||||||
|
*
|
||||||
* @param readCapacity
|
* @param readCapacity
|
||||||
* @param writeCapacity
|
* @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. Table is now created in PayPerRequest billing mode by default.
|
||||||
|
* Succeeds if table already exists.
|
||||||
*
|
*
|
||||||
* @return true if we created a new table (table didn't exist before)
|
* @return true if we created a new table (table didn't exist before)
|
||||||
*
|
*
|
||||||
|
|
@ -39,7 +54,7 @@ public interface LeaseRefresher {
|
||||||
* restrictions.
|
* restrictions.
|
||||||
* @throws DependencyException if DynamoDB createTable fails in an unexpected way
|
* @throws DependencyException if DynamoDB createTable fails in an unexpected way
|
||||||
*/
|
*/
|
||||||
boolean createLeaseTableIfNotExists(Long readCapacity, Long writeCapacity)
|
boolean createLeaseTableIfNotExists()
|
||||||
throws ProvisionedThroughputException, DependencyException;
|
throws ProvisionedThroughputException, DependencyException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -211,10 +211,9 @@ public class DynamoDBLeaseCoordinator implements LeaseCoordinator {
|
||||||
@Override
|
@Override
|
||||||
public void initialize() throws ProvisionedThroughputException, DependencyException, IllegalStateException {
|
public void initialize() throws ProvisionedThroughputException, DependencyException, IllegalStateException {
|
||||||
final boolean newTableCreated =
|
final boolean newTableCreated =
|
||||||
leaseRefresher.createLeaseTableIfNotExists(initialLeaseTableReadCapacity, initialLeaseTableWriteCapacity);
|
leaseRefresher.createLeaseTableIfNotExists();
|
||||||
if (newTableCreated) {
|
if (newTableCreated) {
|
||||||
log.info("Created new lease table for coordinator with initial read capacity of {} and write capacity of {}.",
|
log.info("Created new lease table for coordinator with pay per request billing mode.");
|
||||||
initialLeaseTableReadCapacity, initialLeaseTableWriteCapacity);
|
|
||||||
}
|
}
|
||||||
// Need to wait for table in active state.
|
// Need to wait for table in active state.
|
||||||
final long secondsBetweenPolls = 10L;
|
final long secondsBetweenPolls = 10L;
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,7 @@ public class DynamoDBLeaseManagementFactory implements LeaseManagementFactory {
|
||||||
ignoreUnexpectedChildShards, shardSyncIntervalMillis, consistentReads, listShardsBackoffTimeMillis,
|
ignoreUnexpectedChildShards, shardSyncIntervalMillis, consistentReads, listShardsBackoffTimeMillis,
|
||||||
maxListShardsRetryAttempts, maxCacheMissesBeforeReload, listShardsCacheAllowedAgeInSeconds,
|
maxListShardsRetryAttempts, maxCacheMissesBeforeReload, listShardsCacheAllowedAgeInSeconds,
|
||||||
cacheMissWarningModulus, initialLeaseTableReadCapacity, initialLeaseTableWriteCapacity,
|
cacheMissWarningModulus, initialLeaseTableReadCapacity, initialLeaseTableWriteCapacity,
|
||||||
hierarchicalShardSyncer, tableCreatorCallback, dynamoDbRequestTimeout, BillingMode.PROVISIONED);
|
hierarchicalShardSyncer, tableCreatorCallback, dynamoDbRequestTimeout, BillingMode.PAY_PER_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ public class DynamoDBLeaseRefresher implements LeaseRefresher {
|
||||||
public DynamoDBLeaseRefresher(final String table, final DynamoDbAsyncClient dynamoDBClient,
|
public DynamoDBLeaseRefresher(final String table, final DynamoDbAsyncClient dynamoDBClient,
|
||||||
final LeaseSerializer serializer, final boolean consistentReads,
|
final LeaseSerializer serializer, final boolean consistentReads,
|
||||||
@NonNull final TableCreatorCallback tableCreatorCallback, Duration dynamoDbRequestTimeout) {
|
@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,6 @@ public class DynamoDBLeaseRefresher implements LeaseRefresher {
|
||||||
@Override
|
@Override
|
||||||
public boolean createLeaseTableIfNotExists(@NonNull final Long readCapacity, @NonNull final Long writeCapacity)
|
public boolean createLeaseTableIfNotExists(@NonNull final Long readCapacity, @NonNull final Long writeCapacity)
|
||||||
throws ProvisionedThroughputException, DependencyException {
|
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);
|
|
||||||
}
|
|
||||||
ProvisionedThroughput throughput = ProvisionedThroughput.builder().readCapacityUnits(readCapacity)
|
ProvisionedThroughput throughput = ProvisionedThroughput.builder().readCapacityUnits(readCapacity)
|
||||||
.writeCapacityUnits(writeCapacity).build();
|
.writeCapacityUnits(writeCapacity).build();
|
||||||
final CreateTableRequest request;
|
final CreateTableRequest request;
|
||||||
|
|
@ -185,6 +175,34 @@ public class DynamoDBLeaseRefresher implements LeaseRefresher {
|
||||||
.build();
|
.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) {
|
||||||
|
//
|
||||||
|
// Something went wrong with DynamoDB
|
||||||
|
//
|
||||||
|
log.error("Failed to get table status for {}", table, de);
|
||||||
|
}
|
||||||
|
|
||||||
final AWSExceptionManager exceptionManager = createExceptionManager();
|
final AWSExceptionManager exceptionManager = createExceptionManager();
|
||||||
exceptionManager.add(ResourceInUseException.class, t -> t);
|
exceptionManager.add(ResourceInUseException.class, t -> t);
|
||||||
|
|
|
||||||
|
|
@ -110,13 +110,22 @@ public class ExceptionThrowingLeaseRefresher implements LeaseRefresher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean createLeaseTableIfNotExists(Long readCapacity, Long writeCapacity)
|
public boolean createLeaseTableIfNotExists(Long readCapacity, Long writeCapacity)
|
||||||
throws ProvisionedThroughputException, DependencyException {
|
throws ProvisionedThroughputException, DependencyException {
|
||||||
throwExceptions("createLeaseTableIfNotExists",
|
throwExceptions("createLeaseTableIfNotExists",
|
||||||
ExceptionThrowingLeaseRefresherMethods.CREATELEASETABLEIFNOTEXISTS);
|
ExceptionThrowingLeaseRefresherMethods.CREATELEASETABLEIFNOTEXISTS);
|
||||||
|
|
||||||
return leaseRefresher.createLeaseTableIfNotExists(readCapacity, writeCapacity);
|
return leaseRefresher.createLeaseTableIfNotExists(readCapacity, writeCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean createLeaseTableIfNotExists()
|
||||||
|
throws ProvisionedThroughputException, DependencyException {
|
||||||
|
throwExceptions("createLeaseTableIfNotExists",
|
||||||
|
ExceptionThrowingLeaseRefresherMethods.CREATELEASETABLEIFNOTEXISTS);
|
||||||
|
|
||||||
|
return leaseRefresher.createLeaseTableIfNotExists();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean leaseTableExists() throws DependencyException {
|
public boolean leaseTableExists() throws DependencyException {
|
||||||
throwExceptions("leaseTableExists", ExceptionThrowingLeaseRefresherMethods.LEASETABLEEXISTS);
|
throwExceptions("leaseTableExists", ExceptionThrowingLeaseRefresherMethods.LEASETABLEEXISTS);
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,7 @@ public class LeaseCoordinatorExerciser {
|
||||||
LeaseRefresher leaseRefresher = new DynamoDBLeaseRefresher("nagl_ShardProgress", dynamoDBClient,
|
LeaseRefresher leaseRefresher = new DynamoDBLeaseRefresher("nagl_ShardProgress", dynamoDBClient,
|
||||||
new DynamoDBLeaseSerializer(), true, TableCreatorCallback.NOOP_TABLE_CREATOR_CALLBACK);
|
new DynamoDBLeaseSerializer(), true, TableCreatorCallback.NOOP_TABLE_CREATOR_CALLBACK);
|
||||||
|
|
||||||
if (leaseRefresher.createLeaseTableIfNotExists(INITIAL_LEASE_TABLE_READ_CAPACITY,
|
if (leaseRefresher.createLeaseTableIfNotExists()) {
|
||||||
INITIAL_LEASE_TABLE_WRITE_CAPACITY)) {
|
|
||||||
log.info("Waiting for newly created lease table");
|
log.info("Waiting for newly created lease table");
|
||||||
if (!leaseRefresher.waitUntilLeaseTableExists(10, 300)) {
|
if (!leaseRefresher.waitUntilLeaseTableExists(10, 300)) {
|
||||||
log.error("Table was not created in time");
|
log.error("Table was not created in time");
|
||||||
|
|
|
||||||
|
|
@ -34,4 +34,3 @@ public class LeaseIntegrationBillingModePayPerRequestTest extends LeaseIntegrati
|
||||||
tableCreatorCallback, LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT, BillingMode.PAY_PER_REQUEST);
|
tableCreatorCallback, LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT, BillingMode.PAY_PER_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ public class LeaseIntegrationTest {
|
||||||
|
|
||||||
protected DynamoDBLeaseRefresher getLeaseRefresher() {
|
protected DynamoDBLeaseRefresher getLeaseRefresher() {
|
||||||
return new DynamoDBLeaseRefresher(tableName, ddbClient, leaseSerializer, true,
|
return new DynamoDBLeaseRefresher(tableName, ddbClient, leaseSerializer, true,
|
||||||
tableCreatorCallback, LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT, BillingMode.PROVISIONED);
|
tableCreatorCallback, LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT, BillingMode.PAY_PER_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
package software.amazon.kinesis.leases.dynamodb;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
import software.amazon.kinesis.leases.LeaseRefresher;
|
||||||
|
import software.amazon.kinesis.leases.exceptions.DependencyException;
|
||||||
|
import software.amazon.kinesis.metrics.MetricsFactory;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class DynamoDBLeaseCoordinatorTest {
|
||||||
|
|
||||||
|
private static final String WORKER_ID = UUID.randomUUID().toString();
|
||||||
|
private static final long LEASE_DURATION_MILLIS = 5000L;
|
||||||
|
private static final long EPSILON_MILLIS = 25L;
|
||||||
|
private static final int MAX_LEASES_FOR_WORKER = Integer.MAX_VALUE;
|
||||||
|
private static final int MAX_LEASES_TO_STEAL_AT_ONE_TIME = 1;
|
||||||
|
private static final int MAX_LEASE_RENEWER_THREAD_COUNT = 20;
|
||||||
|
private static final long INITIAL_LEASE_TABLE_READ_CAPACITY = 10L;
|
||||||
|
private static final long INITIAL_LEASE_TABLE_WRITE_CAPACITY = 10L;
|
||||||
|
private static final long SECONDS_BETWEEN_POLLS = 10L;
|
||||||
|
private static final long TIMEOUT_SECONDS = 600L;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private LeaseRefresher leaseRefresher;
|
||||||
|
@Mock
|
||||||
|
private MetricsFactory metricsFactory;
|
||||||
|
|
||||||
|
private DynamoDBLeaseCoordinator leaseCoordinator;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
this.leaseCoordinator = new DynamoDBLeaseCoordinator(leaseRefresher, WORKER_ID, LEASE_DURATION_MILLIS,
|
||||||
|
EPSILON_MILLIS, MAX_LEASES_FOR_WORKER, MAX_LEASES_TO_STEAL_AT_ONE_TIME, MAX_LEASE_RENEWER_THREAD_COUNT,
|
||||||
|
INITIAL_LEASE_TABLE_READ_CAPACITY, INITIAL_LEASE_TABLE_WRITE_CAPACITY, metricsFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInitialize_tableCreationSucceeds() throws Exception {
|
||||||
|
when(leaseRefresher.createLeaseTableIfNotExists()).thenReturn(true);
|
||||||
|
when(leaseRefresher.waitUntilLeaseTableExists(SECONDS_BETWEEN_POLLS, TIMEOUT_SECONDS)).thenReturn(true);
|
||||||
|
|
||||||
|
leaseCoordinator.initialize();
|
||||||
|
|
||||||
|
verify(leaseRefresher, times(1)).createLeaseTableIfNotExists();
|
||||||
|
verify(leaseRefresher, times(1)).waitUntilLeaseTableExists(SECONDS_BETWEEN_POLLS, TIMEOUT_SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInitialize_tableCreationFails() throws Exception {
|
||||||
|
when(leaseRefresher.createLeaseTableIfNotExists()).thenReturn(false);
|
||||||
|
when(leaseRefresher.waitUntilLeaseTableExists(SECONDS_BETWEEN_POLLS, TIMEOUT_SECONDS)).thenReturn(false);
|
||||||
|
|
||||||
|
Assert.assertThrows(DependencyException.class, () -> leaseCoordinator.initialize());
|
||||||
|
verify(leaseRefresher, times(1)).createLeaseTableIfNotExists();
|
||||||
|
verify(leaseRefresher, times(1)).waitUntilLeaseTableExists(SECONDS_BETWEEN_POLLS, TIMEOUT_SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,6 +21,8 @@ import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.anyBoolean;
|
import static org.mockito.Matchers.anyBoolean;
|
||||||
import static org.mockito.Matchers.anyLong;
|
import static org.mockito.Matchers.anyLong;
|
||||||
import static org.mockito.Matchers.anyString;
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
@ -33,6 +35,7 @@ import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -49,10 +52,14 @@ import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
|
||||||
import software.amazon.awssdk.services.dynamodb.model.DeleteItemResponse;
|
import software.amazon.awssdk.services.dynamodb.model.DeleteItemResponse;
|
||||||
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
|
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
|
||||||
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
|
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
|
||||||
|
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
|
||||||
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
|
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
|
||||||
import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;
|
import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;
|
||||||
|
import software.amazon.awssdk.services.dynamodb.model.LimitExceededException;
|
||||||
|
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
|
||||||
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
|
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
|
||||||
import software.amazon.awssdk.services.dynamodb.model.PutItemResponse;
|
import software.amazon.awssdk.services.dynamodb.model.PutItemResponse;
|
||||||
|
import software.amazon.awssdk.services.dynamodb.model.ResourceInUseException;
|
||||||
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
|
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
|
||||||
import software.amazon.awssdk.services.dynamodb.model.ScanRequest;
|
import software.amazon.awssdk.services.dynamodb.model.ScanRequest;
|
||||||
import software.amazon.awssdk.services.dynamodb.model.ScanResponse;
|
import software.amazon.awssdk.services.dynamodb.model.ScanResponse;
|
||||||
|
|
@ -66,6 +73,8 @@ import software.amazon.kinesis.leases.Lease;
|
||||||
import software.amazon.kinesis.leases.LeaseManagementConfig;
|
import software.amazon.kinesis.leases.LeaseManagementConfig;
|
||||||
import software.amazon.kinesis.leases.LeaseSerializer;
|
import software.amazon.kinesis.leases.LeaseSerializer;
|
||||||
import software.amazon.kinesis.leases.exceptions.DependencyException;
|
import software.amazon.kinesis.leases.exceptions.DependencyException;
|
||||||
|
import software.amazon.kinesis.leases.exceptions.ProvisionedThroughputException;
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class DynamoDBLeaseRefresherTest {
|
public class DynamoDBLeaseRefresherTest {
|
||||||
|
|
||||||
|
|
@ -99,6 +108,8 @@ public class DynamoDBLeaseRefresherTest {
|
||||||
public ExpectedException expectedException = ExpectedException.none();
|
public ExpectedException expectedException = ExpectedException.none();
|
||||||
|
|
||||||
private DynamoDBLeaseRefresher leaseRefresher;
|
private DynamoDBLeaseRefresher leaseRefresher;
|
||||||
|
private DescribeTableRequest describeTableRequest;
|
||||||
|
private CreateTableRequest createTableRequest;
|
||||||
|
|
||||||
private Map<String, AttributeValue> serializedLease;
|
private Map<String, AttributeValue> serializedLease;
|
||||||
|
|
||||||
|
|
@ -108,6 +119,13 @@ public class DynamoDBLeaseRefresherTest {
|
||||||
tableCreatorCallback);
|
tableCreatorCallback);
|
||||||
serializedLease = new HashMap<>();
|
serializedLease = new HashMap<>();
|
||||||
|
|
||||||
|
describeTableRequest = DescribeTableRequest.builder().tableName(TABLE_NAME).build();
|
||||||
|
createTableRequest = CreateTableRequest.builder()
|
||||||
|
.tableName(TABLE_NAME)
|
||||||
|
.keySchema(leaseSerializer.getKeySchema())
|
||||||
|
.attributeDefinitions(leaseSerializer.getAttributeDefinitions())
|
||||||
|
.billingMode(BillingMode.PAY_PER_REQUEST)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -265,7 +283,151 @@ public class DynamoDBLeaseRefresherTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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(describeTableRequest)).thenReturn(mockDescribeTableFuture);
|
||||||
|
when(mockDescribeTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(ResourceNotFoundException.builder().message("Table doesn't exist").build());
|
||||||
|
|
||||||
|
final ProvisionedThroughput throughput = ProvisionedThroughput.builder().readCapacityUnits(10L)
|
||||||
|
.writeCapacityUnits(10L).build();
|
||||||
|
final CreateTableRequest createTableRequest = CreateTableRequest.builder()
|
||||||
|
.tableName(TABLE_NAME)
|
||||||
|
.keySchema(leaseSerializer.getKeySchema())
|
||||||
|
.attributeDefinitions(leaseSerializer.getAttributeDefinitions())
|
||||||
|
.provisionedThroughput(throughput)
|
||||||
|
.build();
|
||||||
|
when(dynamoDbClient.createTable(createTableRequest)).thenReturn(mockCreateTableFuture);
|
||||||
|
when(mockCreateTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenReturn(null);
|
||||||
|
|
||||||
|
final boolean result = leaseRefresher.createLeaseTableIfNotExists(10L, 10L);
|
||||||
|
|
||||||
|
verify(dynamoDbClient, times(1)).describeTable(describeTableRequest);
|
||||||
|
verify(dynamoDbClient, times(1)).createTable(createTableRequest);
|
||||||
|
verify(mockDescribeTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
verify(mockCreateTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
Assert.assertTrue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateLeaseTableIfNotExists() throws Exception {
|
||||||
|
when(dynamoDbClient.describeTable(describeTableRequest)).thenReturn(mockDescribeTableFuture);
|
||||||
|
when(mockDescribeTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(ResourceNotFoundException.builder().message("Table doesn't exist").build());
|
||||||
|
when(dynamoDbClient.createTable(createTableRequest)).thenReturn(mockCreateTableFuture);
|
||||||
|
when(mockCreateTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenReturn(null);
|
||||||
|
|
||||||
|
final boolean result = leaseRefresher.createLeaseTableIfNotExists();
|
||||||
|
|
||||||
|
verify(dynamoDbClient, times(1)).describeTable(describeTableRequest);
|
||||||
|
verify(dynamoDbClient, times(1)).createTable(createTableRequest);
|
||||||
|
verify(mockDescribeTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
verify(mockCreateTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
Assert.assertTrue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateLeaseTableIfNotExists_throwsDependencyException() throws Exception {
|
||||||
|
when(dynamoDbClient.describeTable(describeTableRequest)).thenReturn(mockDescribeTableFuture);
|
||||||
|
when(mockDescribeTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(new InterruptedException());
|
||||||
|
when(dynamoDbClient.createTable(createTableRequest)).thenReturn(mockCreateTableFuture);
|
||||||
|
when(mockCreateTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(ResourceInUseException.builder().message("Table already exists").build());
|
||||||
|
|
||||||
|
Assert.assertFalse(leaseRefresher.createLeaseTableIfNotExists());
|
||||||
|
verify(dynamoDbClient, times(1)).describeTable(describeTableRequest);
|
||||||
|
verify(dynamoDbClient, times(1)).createTable(createTableRequest);
|
||||||
|
verify(mockDescribeTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
verify(mockCreateTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateLeaseTableIfNotExists_tableAlreadyExists_throwsResourceInUseException_expectFalse() throws Exception {
|
||||||
|
when(dynamoDbClient.describeTable(describeTableRequest)).thenReturn(mockDescribeTableFuture);
|
||||||
|
when(mockDescribeTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(ResourceNotFoundException.builder().message("Table doesn't exist").build());
|
||||||
|
when(dynamoDbClient.createTable(createTableRequest)).thenReturn(mockCreateTableFuture);
|
||||||
|
when(mockCreateTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(ResourceInUseException.builder().message("Table already exists").build());
|
||||||
|
|
||||||
|
Assert.assertFalse(leaseRefresher.createLeaseTableIfNotExists());
|
||||||
|
verify(dynamoDbClient, times(1)).describeTable(describeTableRequest);
|
||||||
|
verify(dynamoDbClient, times(1)).createTable(createTableRequest);
|
||||||
|
verify(mockDescribeTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
verify(mockCreateTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateLeaseTableIfNotExists_throwsLimitExceededException_expectProvisionedThroughputException() throws Exception {
|
||||||
|
when(dynamoDbClient.describeTable(describeTableRequest)).thenReturn(mockDescribeTableFuture);
|
||||||
|
when(mockDescribeTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(ResourceNotFoundException.builder().message("Table doesn't exist").build());
|
||||||
|
when(dynamoDbClient.createTable(createTableRequest)).thenReturn(mockCreateTableFuture);
|
||||||
|
when(mockCreateTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(LimitExceededException.builder().build());
|
||||||
|
|
||||||
|
Assert.assertThrows(ProvisionedThroughputException.class, () -> leaseRefresher.createLeaseTableIfNotExists());
|
||||||
|
verify(dynamoDbClient, times(1)).describeTable(describeTableRequest);
|
||||||
|
verify(dynamoDbClient, times(1)).createTable(createTableRequest);
|
||||||
|
verify(mockDescribeTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
verify(mockCreateTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateLeaseTableIfNotExists_throwsDynamoDbException_expectDependencyException() throws Exception {
|
||||||
|
when(dynamoDbClient.describeTable(describeTableRequest)).thenReturn(mockDescribeTableFuture);
|
||||||
|
when(mockDescribeTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(ResourceNotFoundException.builder().message("Table doesn't exist").build());
|
||||||
|
when(dynamoDbClient.createTable(createTableRequest)).thenReturn(mockCreateTableFuture);
|
||||||
|
when(mockCreateTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(DynamoDbException.builder().build());
|
||||||
|
|
||||||
|
Assert.assertThrows(DependencyException.class, () -> leaseRefresher.createLeaseTableIfNotExists());
|
||||||
|
verify(dynamoDbClient, times(1)).describeTable(describeTableRequest);
|
||||||
|
verify(dynamoDbClient, times(1)).createTable(createTableRequest);
|
||||||
|
verify(mockDescribeTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
verify(mockCreateTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateLeaseTableIfNotExists_throwsTimeoutException_expectDependencyException() throws Exception {
|
||||||
|
when(dynamoDbClient.describeTable(describeTableRequest)).thenReturn(mockDescribeTableFuture);
|
||||||
|
when(mockDescribeTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(ResourceNotFoundException.builder().message("Table doesn't exist").build());
|
||||||
|
when(dynamoDbClient.createTable(createTableRequest)).thenReturn(mockCreateTableFuture);
|
||||||
|
when(mockCreateTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS)))
|
||||||
|
.thenThrow(new TimeoutException());
|
||||||
|
|
||||||
|
Assert.assertThrows(DependencyException.class, () -> leaseRefresher.createLeaseTableIfNotExists());
|
||||||
|
verify(dynamoDbClient, times(1)).describeTable(describeTableRequest);
|
||||||
|
verify(dynamoDbClient, times(1)).createTable(createTableRequest);
|
||||||
|
verify(mockDescribeTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
verify(mockCreateTableFuture, times(1))
|
||||||
|
.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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();
|
TimeoutException te = setRuleForDependencyTimeout();
|
||||||
|
|
||||||
when(dynamoDbClient.describeTable(any(DescribeTableRequest.class))).thenReturn(mockDescribeTableFuture);
|
when(dynamoDbClient.describeTable(any(DescribeTableRequest.class))).thenReturn(mockDescribeTableFuture);
|
||||||
|
|
@ -279,10 +441,7 @@ public class DynamoDBLeaseRefresherTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateLeaseTableBillingMode() throws Exception {
|
public void testCreateLeaseTableTimesOut() throws Exception {
|
||||||
leaseRefresher = new DynamoDBLeaseRefresher(TABLE_NAME, dynamoDbClient, leaseSerializer, CONSISTENT_READS,
|
|
||||||
tableCreatorCallback, LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT, BillingMode.PAY_PER_REQUEST);
|
|
||||||
|
|
||||||
TimeoutException te = setRuleForDependencyTimeout();
|
TimeoutException te = setRuleForDependencyTimeout();
|
||||||
|
|
||||||
when(dynamoDbClient.describeTable(any(DescribeTableRequest.class))).thenReturn(mockDescribeTableFuture);
|
when(dynamoDbClient.describeTable(any(DescribeTableRequest.class))).thenReturn(mockDescribeTableFuture);
|
||||||
|
|
@ -292,7 +451,7 @@ public class DynamoDBLeaseRefresherTest {
|
||||||
when(dynamoDbClient.createTable(any(CreateTableRequest.class))).thenReturn(mockCreateTableFuture);
|
when(dynamoDbClient.createTable(any(CreateTableRequest.class))).thenReturn(mockCreateTableFuture);
|
||||||
when(mockCreateTableFuture.get(anyLong(), any())).thenThrow(te);
|
when(mockCreateTableFuture.get(anyLong(), any())).thenThrow(te);
|
||||||
|
|
||||||
verifyCancel(mockCreateTableFuture, () -> leaseRefresher.createLeaseTableIfNotExists(10L, 10L));
|
verifyCancel(mockCreateTableFuture, () -> leaseRefresher.createLeaseTableIfNotExists());
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue