Expose veryOldLeaseDurationMultiplier in LeaseManagementConfig (#1307)
* Expose veryOldLeaseDurationMultiplier in LeaseManagementConfig as agedFailoverTimeMultiplier
This commit is contained in:
parent
7f1f243676
commit
981899499f
10 changed files with 216 additions and 12 deletions
|
|
@ -217,6 +217,7 @@ public class KinesisClientLibConfiguration {
|
||||||
private AwsCredentialsProvider dynamoDBCredentialsProvider;
|
private AwsCredentialsProvider dynamoDBCredentialsProvider;
|
||||||
private AwsCredentialsProvider cloudWatchCredentialsProvider;
|
private AwsCredentialsProvider cloudWatchCredentialsProvider;
|
||||||
private long failoverTimeMillis;
|
private long failoverTimeMillis;
|
||||||
|
private int agedFailoverTimeMultiplier;
|
||||||
private String workerIdentifier;
|
private String workerIdentifier;
|
||||||
private long shardSyncIntervalMillis;
|
private long shardSyncIntervalMillis;
|
||||||
private int maxRecords;
|
private int maxRecords;
|
||||||
|
|
@ -959,6 +960,12 @@ public class KinesisClientLibConfiguration {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KinesisClientLibConfiguration withAgedFailoverTimeMultiplier(int agedFailoverTimeMultiplier) {
|
||||||
|
checkIsValuePositive("AgedFailoverTimeMultiplier", agedFailoverTimeMultiplier);
|
||||||
|
this.agedFailoverTimeMultiplier = agedFailoverTimeMultiplier;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param shardSyncIntervalMillis
|
* @param shardSyncIntervalMillis
|
||||||
* Time between tasks to sync leases and Kinesis shards
|
* Time between tasks to sync leases and Kinesis shards
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,8 @@ public class MultiLangDaemonConfiguration {
|
||||||
@ConfigurationSettable(configurationClass = LeaseManagementConfig.class)
|
@ConfigurationSettable(configurationClass = LeaseManagementConfig.class)
|
||||||
private long failoverTimeMillis;
|
private long failoverTimeMillis;
|
||||||
@ConfigurationSettable(configurationClass = LeaseManagementConfig.class)
|
@ConfigurationSettable(configurationClass = LeaseManagementConfig.class)
|
||||||
|
private int agedFailoverTimeMultiplier;
|
||||||
|
@ConfigurationSettable(configurationClass = LeaseManagementConfig.class)
|
||||||
private long shardSyncIntervalMillis;
|
private long shardSyncIntervalMillis;
|
||||||
@ConfigurationSettable(configurationClass = LeaseManagementConfig.class)
|
@ConfigurationSettable(configurationClass = LeaseManagementConfig.class)
|
||||||
private boolean cleanupLeasesUponShardCompletion;
|
private boolean cleanupLeasesUponShardCompletion;
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,17 @@ public class MultiLangDaemonConfigurationTest {
|
||||||
assertThat(resolvedConfiguration.leaseManagementConfig.maxLeasesForWorker(), equalTo(10));
|
assertThat(resolvedConfiguration.leaseManagementConfig.maxLeasesForWorker(), equalTo(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetAgedFailoverTimeMultiplier() {
|
||||||
|
MultiLangDaemonConfiguration configuration = baseConfiguration();
|
||||||
|
configuration.setAgedFailoverTimeMultiplier(5);
|
||||||
|
|
||||||
|
MultiLangDaemonConfiguration.ResolvedConfiguration resolvedConfiguration = configuration
|
||||||
|
.resolvedConfiguration(shardRecordProcessorFactory);
|
||||||
|
|
||||||
|
assertThat(resolvedConfiguration.leaseManagementConfig.agedFailoverTimeMultiplier(), equalTo(5));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDefaultRetrievalConfig() {
|
public void testDefaultRetrievalConfig() {
|
||||||
MultiLangDaemonConfiguration configuration = baseConfiguration();
|
MultiLangDaemonConfiguration configuration = baseConfiguration();
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ public class LeaseManagementConfig {
|
||||||
public static final long DEFAULT_COMPLETED_LEASE_CLEANUP_INTERVAL_MILLIS = Duration.ofMinutes(5).toMillis();
|
public static final long DEFAULT_COMPLETED_LEASE_CLEANUP_INTERVAL_MILLIS = Duration.ofMinutes(5).toMillis();
|
||||||
public static final long DEFAULT_GARBAGE_LEASE_CLEANUP_INTERVAL_MILLIS = Duration.ofMinutes(30).toMillis();
|
public static final long DEFAULT_GARBAGE_LEASE_CLEANUP_INTERVAL_MILLIS = Duration.ofMinutes(30).toMillis();
|
||||||
public static final long DEFAULT_PERIODIC_SHARD_SYNC_INTERVAL_MILLIS = 2 * 60 * 1000L;
|
public static final long DEFAULT_PERIODIC_SHARD_SYNC_INTERVAL_MILLIS = 2 * 60 * 1000L;
|
||||||
|
public static final int DEFAULT_AGED_FAILOVER_TIME_MULTIPLIER = 3;
|
||||||
public static final int DEFAULT_CONSECUTIVE_HOLES_FOR_TRIGGERING_LEASE_RECOVERY = 3;
|
public static final int DEFAULT_CONSECUTIVE_HOLES_FOR_TRIGGERING_LEASE_RECOVERY = 3;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -102,6 +103,15 @@ public class LeaseManagementConfig {
|
||||||
*/
|
*/
|
||||||
private long failoverTimeMillis = 10000L;
|
private long failoverTimeMillis = 10000L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplier for the failoverTimeMillis in which leases which are expired for an extended period of time defined by
|
||||||
|
* (agedFailoverTimeMultiplier * failoverTimeMillis) are taken with priority, disregarding the target
|
||||||
|
* but obeying the maximum limit per worker.
|
||||||
|
*
|
||||||
|
* <p>Default value: 3 </p>
|
||||||
|
*/
|
||||||
|
private int agedFailoverTimeMultiplier = DEFAULT_AGED_FAILOVER_TIME_MULTIPLIER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shard sync interval in milliseconds - e.g. wait for this long between shard sync tasks.
|
* Shard sync interval in milliseconds - e.g. wait for this long between shard sync tasks.
|
||||||
*
|
*
|
||||||
|
|
@ -370,6 +380,7 @@ public class LeaseManagementConfig {
|
||||||
workerIdentifier(),
|
workerIdentifier(),
|
||||||
executorService(),
|
executorService(),
|
||||||
failoverTimeMillis(),
|
failoverTimeMillis(),
|
||||||
|
agedFailoverTimeMultiplier(),
|
||||||
epsilonMillis(),
|
epsilonMillis(),
|
||||||
maxLeasesForWorker(),
|
maxLeasesForWorker(),
|
||||||
maxLeasesToStealAtOneTime(),
|
maxLeasesToStealAtOneTime(),
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
import software.amazon.kinesis.annotations.KinesisClientInternalApi;
|
import software.amazon.kinesis.annotations.KinesisClientInternalApi;
|
||||||
import software.amazon.kinesis.leases.Lease;
|
import software.amazon.kinesis.leases.Lease;
|
||||||
import software.amazon.kinesis.leases.LeaseCoordinator;
|
import software.amazon.kinesis.leases.LeaseCoordinator;
|
||||||
|
import software.amazon.kinesis.leases.LeaseManagementConfig;
|
||||||
import software.amazon.kinesis.leases.LeaseRefresher;
|
import software.amazon.kinesis.leases.LeaseRefresher;
|
||||||
import software.amazon.kinesis.leases.LeaseRenewer;
|
import software.amazon.kinesis.leases.LeaseRenewer;
|
||||||
import software.amazon.kinesis.leases.LeaseTaker;
|
import software.amazon.kinesis.leases.LeaseTaker;
|
||||||
|
|
@ -140,6 +141,7 @@ public class DynamoDBLeaseCoordinator implements LeaseCoordinator {
|
||||||
* @param metricsFactory
|
* @param metricsFactory
|
||||||
* Used to publish metrics about lease operations
|
* Used to publish metrics about lease operations
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public DynamoDBLeaseCoordinator(final LeaseRefresher leaseRefresher,
|
public DynamoDBLeaseCoordinator(final LeaseRefresher leaseRefresher,
|
||||||
final String workerIdentifier,
|
final String workerIdentifier,
|
||||||
final long leaseDurationMillis,
|
final long leaseDurationMillis,
|
||||||
|
|
@ -150,11 +152,54 @@ public class DynamoDBLeaseCoordinator implements LeaseCoordinator {
|
||||||
final long initialLeaseTableReadCapacity,
|
final long initialLeaseTableReadCapacity,
|
||||||
final long initialLeaseTableWriteCapacity,
|
final long initialLeaseTableWriteCapacity,
|
||||||
final MetricsFactory metricsFactory) {
|
final MetricsFactory metricsFactory) {
|
||||||
|
this(leaseRefresher, workerIdentifier, leaseDurationMillis,
|
||||||
|
LeaseManagementConfig.DEFAULT_AGED_FAILOVER_TIME_MULTIPLIER, epsilonMillis, maxLeasesForWorker,
|
||||||
|
maxLeasesToStealAtOneTime, maxLeaseRenewerThreadCount,
|
||||||
|
TableConstants.DEFAULT_INITIAL_LEASE_TABLE_READ_CAPACITY,
|
||||||
|
TableConstants.DEFAULT_INITIAL_LEASE_TABLE_WRITE_CAPACITY, metricsFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param leaseRefresher
|
||||||
|
* LeaseRefresher instance to use
|
||||||
|
* @param workerIdentifier
|
||||||
|
* Identifies the worker (e.g. useful to track lease ownership)
|
||||||
|
* @param leaseDurationMillis
|
||||||
|
* Duration of a lease
|
||||||
|
* @param agedFailoverTimeMultiplier
|
||||||
|
* Multiplier to determine when leases should be taken at priority
|
||||||
|
* @param epsilonMillis
|
||||||
|
* Allow for some variance when calculating lease expirations
|
||||||
|
* @param maxLeasesForWorker
|
||||||
|
* Max leases this Worker can handle at a time
|
||||||
|
* @param maxLeasesToStealAtOneTime
|
||||||
|
* Steal up to these many leases at a time (for load balancing)
|
||||||
|
* @param initialLeaseTableReadCapacity
|
||||||
|
* Initial dynamodb lease table read iops if creating the lease table
|
||||||
|
* @param initialLeaseTableWriteCapacity
|
||||||
|
* Initial dynamodb lease table write iops if creating the lease table
|
||||||
|
* @param metricsFactory
|
||||||
|
* Used to publish metrics about lease operations
|
||||||
|
*/
|
||||||
|
public DynamoDBLeaseCoordinator(final LeaseRefresher leaseRefresher,
|
||||||
|
final String workerIdentifier,
|
||||||
|
final long leaseDurationMillis,
|
||||||
|
final int agedFailoverTimeMultiplier,
|
||||||
|
final long epsilonMillis,
|
||||||
|
final int maxLeasesForWorker,
|
||||||
|
final int maxLeasesToStealAtOneTime,
|
||||||
|
final int maxLeaseRenewerThreadCount,
|
||||||
|
final long initialLeaseTableReadCapacity,
|
||||||
|
final long initialLeaseTableWriteCapacity,
|
||||||
|
final MetricsFactory metricsFactory) {
|
||||||
this.leaseRefresher = leaseRefresher;
|
this.leaseRefresher = leaseRefresher;
|
||||||
this.leaseRenewalThreadpool = getLeaseRenewalExecutorService(maxLeaseRenewerThreadCount);
|
this.leaseRenewalThreadpool = getLeaseRenewalExecutorService(maxLeaseRenewerThreadCount);
|
||||||
this.leaseTaker = new DynamoDBLeaseTaker(leaseRefresher, workerIdentifier, leaseDurationMillis, metricsFactory)
|
this.leaseTaker = new DynamoDBLeaseTaker(leaseRefresher, workerIdentifier, leaseDurationMillis, metricsFactory)
|
||||||
.withMaxLeasesForWorker(maxLeasesForWorker)
|
.withMaxLeasesForWorker(maxLeasesForWorker)
|
||||||
.withMaxLeasesToStealAtOneTime(maxLeasesToStealAtOneTime);
|
.withMaxLeasesToStealAtOneTime(maxLeasesToStealAtOneTime)
|
||||||
|
.withVeryOldLeaseDurationNanosMultiplier(agedFailoverTimeMultiplier);
|
||||||
this.leaseRenewer = new DynamoDBLeaseRenewer(
|
this.leaseRenewer = new DynamoDBLeaseRenewer(
|
||||||
leaseRefresher, workerIdentifier, leaseDurationMillis, leaseRenewalThreadpool, metricsFactory);
|
leaseRefresher, workerIdentifier, leaseDurationMillis, leaseRenewalThreadpool, metricsFactory);
|
||||||
this.renewerIntervalMillis = getRenewerTakerIntervalMillis(leaseDurationMillis, epsilonMillis);
|
this.renewerIntervalMillis = getRenewerTakerIntervalMillis(leaseDurationMillis, epsilonMillis);
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ public class DynamoDBLeaseManagementFactory implements LeaseManagementFactory {
|
||||||
private Function<StreamConfig, ShardDetector> customShardDetectorProvider;
|
private Function<StreamConfig, ShardDetector> customShardDetectorProvider;
|
||||||
|
|
||||||
private final long failoverTimeMillis;
|
private final long failoverTimeMillis;
|
||||||
|
private final int agedFailoverTimeMultiplier;
|
||||||
private final long epsilonMillis;
|
private final long epsilonMillis;
|
||||||
private final int maxLeasesForWorker;
|
private final int maxLeasesForWorker;
|
||||||
private final int maxLeasesToStealAtOneTime;
|
private final int maxLeasesToStealAtOneTime;
|
||||||
|
|
@ -487,6 +488,7 @@ public class DynamoDBLeaseManagementFactory implements LeaseManagementFactory {
|
||||||
* @param leaseTableDeletionProtectionEnabled
|
* @param leaseTableDeletionProtectionEnabled
|
||||||
* @param tags
|
* @param tags
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
private DynamoDBLeaseManagementFactory(final KinesisAsyncClient kinesisClient, final StreamConfig streamConfig,
|
private DynamoDBLeaseManagementFactory(final KinesisAsyncClient kinesisClient, final StreamConfig streamConfig,
|
||||||
final DynamoDbAsyncClient dynamoDBClient, final String tableName, final String workerIdentifier,
|
final DynamoDbAsyncClient dynamoDBClient, final String tableName, final String workerIdentifier,
|
||||||
final ExecutorService executorService, final long failoverTimeMillis, final long epsilonMillis,
|
final ExecutorService executorService, final long failoverTimeMillis, final long epsilonMillis,
|
||||||
|
|
@ -544,6 +546,7 @@ public class DynamoDBLeaseManagementFactory implements LeaseManagementFactory {
|
||||||
* @param isMultiStreamMode
|
* @param isMultiStreamMode
|
||||||
* @param leaseCleanupConfig
|
* @param leaseCleanupConfig
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public DynamoDBLeaseManagementFactory(final KinesisAsyncClient kinesisClient,
|
public DynamoDBLeaseManagementFactory(final KinesisAsyncClient kinesisClient,
|
||||||
final DynamoDbAsyncClient dynamoDBClient, final String tableName, final String workerIdentifier,
|
final DynamoDbAsyncClient dynamoDBClient, final String tableName, final String workerIdentifier,
|
||||||
final ExecutorService executorService, final long failoverTimeMillis, final long epsilonMillis,
|
final ExecutorService executorService, final long failoverTimeMillis, final long epsilonMillis,
|
||||||
|
|
@ -558,12 +561,74 @@ public class DynamoDBLeaseManagementFactory implements LeaseManagementFactory {
|
||||||
Collection<Tag> tags, LeaseSerializer leaseSerializer,
|
Collection<Tag> tags, LeaseSerializer leaseSerializer,
|
||||||
Function<StreamConfig, ShardDetector> customShardDetectorProvider, boolean isMultiStreamMode,
|
Function<StreamConfig, ShardDetector> customShardDetectorProvider, boolean isMultiStreamMode,
|
||||||
LeaseCleanupConfig leaseCleanupConfig) {
|
LeaseCleanupConfig leaseCleanupConfig) {
|
||||||
|
this(kinesisClient, dynamoDBClient, tableName,
|
||||||
|
workerIdentifier, executorService, failoverTimeMillis,
|
||||||
|
LeaseManagementConfig.DEFAULT_AGED_FAILOVER_TIME_MULTIPLIER, epsilonMillis, maxLeasesForWorker,
|
||||||
|
maxLeasesToStealAtOneTime, maxLeaseRenewalThreads, cleanupLeasesUponShardCompletion,
|
||||||
|
ignoreUnexpectedChildShards, shardSyncIntervalMillis, consistentReads, listShardsBackoffTimeMillis,
|
||||||
|
maxListShardsRetryAttempts, maxCacheMissesBeforeReload, listShardsCacheAllowedAgeInSeconds,
|
||||||
|
cacheMissWarningModulus, initialLeaseTableReadCapacity, initialLeaseTableWriteCapacity,
|
||||||
|
deprecatedHierarchicalShardSyncer, tableCreatorCallback, dynamoDbRequestTimeout, billingMode,
|
||||||
|
leaseTableDeletionProtectionEnabled, tags, leaseSerializer, customShardDetectorProvider, isMultiStreamMode,
|
||||||
|
leaseCleanupConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param kinesisClient
|
||||||
|
* @param dynamoDBClient
|
||||||
|
* @param tableName
|
||||||
|
* @param workerIdentifier
|
||||||
|
* @param executorService
|
||||||
|
* @param failoverTimeMillis
|
||||||
|
* @param agedFailoverTimeMultiplier
|
||||||
|
* @param epsilonMillis
|
||||||
|
* @param maxLeasesForWorker
|
||||||
|
* @param maxLeasesToStealAtOneTime
|
||||||
|
* @param maxLeaseRenewalThreads
|
||||||
|
* @param cleanupLeasesUponShardCompletion
|
||||||
|
* @param ignoreUnexpectedChildShards
|
||||||
|
* @param shardSyncIntervalMillis
|
||||||
|
* @param consistentReads
|
||||||
|
* @param listShardsBackoffTimeMillis
|
||||||
|
* @param maxListShardsRetryAttempts
|
||||||
|
* @param maxCacheMissesBeforeReload
|
||||||
|
* @param listShardsCacheAllowedAgeInSeconds
|
||||||
|
* @param cacheMissWarningModulus
|
||||||
|
* @param initialLeaseTableReadCapacity
|
||||||
|
* @param initialLeaseTableWriteCapacity
|
||||||
|
* @param deprecatedHierarchicalShardSyncer
|
||||||
|
* @param tableCreatorCallback
|
||||||
|
* @param dynamoDbRequestTimeout
|
||||||
|
* @param billingMode
|
||||||
|
* @param leaseTableDeletionProtectionEnabled
|
||||||
|
* @param leaseSerializer
|
||||||
|
* @param customShardDetectorProvider
|
||||||
|
* @param isMultiStreamMode
|
||||||
|
* @param leaseCleanupConfig
|
||||||
|
*/
|
||||||
|
public DynamoDBLeaseManagementFactory(final KinesisAsyncClient kinesisClient,
|
||||||
|
final DynamoDbAsyncClient dynamoDBClient, final String tableName, final String workerIdentifier,
|
||||||
|
final ExecutorService executorService, final long failoverTimeMillis,
|
||||||
|
final int agedFailoverTimeMultiplier, final long epsilonMillis,
|
||||||
|
final int maxLeasesForWorker, final int maxLeasesToStealAtOneTime, final int maxLeaseRenewalThreads,
|
||||||
|
final boolean cleanupLeasesUponShardCompletion, final boolean ignoreUnexpectedChildShards,
|
||||||
|
final long shardSyncIntervalMillis, final boolean consistentReads, final long listShardsBackoffTimeMillis,
|
||||||
|
final int maxListShardsRetryAttempts, final int maxCacheMissesBeforeReload,
|
||||||
|
final long listShardsCacheAllowedAgeInSeconds, final int cacheMissWarningModulus,
|
||||||
|
final long initialLeaseTableReadCapacity, final long initialLeaseTableWriteCapacity,
|
||||||
|
final HierarchicalShardSyncer deprecatedHierarchicalShardSyncer, final TableCreatorCallback tableCreatorCallback,
|
||||||
|
Duration dynamoDbRequestTimeout, BillingMode billingMode, final boolean leaseTableDeletionProtectionEnabled,
|
||||||
|
Collection<Tag> tags, LeaseSerializer leaseSerializer,
|
||||||
|
Function<StreamConfig, ShardDetector> customShardDetectorProvider, boolean isMultiStreamMode,
|
||||||
|
LeaseCleanupConfig leaseCleanupConfig) {
|
||||||
this.kinesisClient = kinesisClient;
|
this.kinesisClient = kinesisClient;
|
||||||
this.dynamoDBClient = dynamoDBClient;
|
this.dynamoDBClient = dynamoDBClient;
|
||||||
this.tableName = tableName;
|
this.tableName = tableName;
|
||||||
this.workerIdentifier = workerIdentifier;
|
this.workerIdentifier = workerIdentifier;
|
||||||
this.executorService = executorService;
|
this.executorService = executorService;
|
||||||
this.failoverTimeMillis = failoverTimeMillis;
|
this.failoverTimeMillis = failoverTimeMillis;
|
||||||
|
this.agedFailoverTimeMultiplier = agedFailoverTimeMultiplier;
|
||||||
this.epsilonMillis = epsilonMillis;
|
this.epsilonMillis = epsilonMillis;
|
||||||
this.maxLeasesForWorker = maxLeasesForWorker;
|
this.maxLeasesForWorker = maxLeasesForWorker;
|
||||||
this.maxLeasesToStealAtOneTime = maxLeasesToStealAtOneTime;
|
this.maxLeasesToStealAtOneTime = maxLeasesToStealAtOneTime;
|
||||||
|
|
@ -596,6 +661,7 @@ public class DynamoDBLeaseManagementFactory implements LeaseManagementFactory {
|
||||||
return new DynamoDBLeaseCoordinator(this.createLeaseRefresher(),
|
return new DynamoDBLeaseCoordinator(this.createLeaseRefresher(),
|
||||||
workerIdentifier,
|
workerIdentifier,
|
||||||
failoverTimeMillis,
|
failoverTimeMillis,
|
||||||
|
agedFailoverTimeMultiplier,
|
||||||
epsilonMillis,
|
epsilonMillis,
|
||||||
maxLeasesForWorker,
|
maxLeasesForWorker,
|
||||||
maxLeasesToStealAtOneTime,
|
maxLeasesToStealAtOneTime,
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ public class DynamoDBLeaseTaker implements LeaseTaker {
|
||||||
private int maxLeasesForWorker = Integer.MAX_VALUE;
|
private int maxLeasesForWorker = Integer.MAX_VALUE;
|
||||||
private int maxLeasesToStealAtOneTime = 1;
|
private int maxLeasesToStealAtOneTime = 1;
|
||||||
|
|
||||||
private long veryOldLeaseDurationNanosMultiplier = 3;
|
private int veryOldLeaseDurationNanosMultiplier = 3;
|
||||||
private long lastScanTimeNanos = 0L;
|
private long lastScanTimeNanos = 0L;
|
||||||
|
|
||||||
public DynamoDBLeaseTaker(LeaseRefresher leaseRefresher, String workerIdentifier, long leaseDurationMillis,
|
public DynamoDBLeaseTaker(LeaseRefresher leaseRefresher, String workerIdentifier, long leaseDurationMillis,
|
||||||
|
|
@ -103,15 +103,24 @@ public class DynamoDBLeaseTaker implements LeaseTaker {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Misspelled method, use {@link DynamoDBLeaseTaker#withVeryOldLeaseDurationNanosMultiplier(int)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public DynamoDBLeaseTaker withVeryOldLeaseDurationNanosMultipler(long veryOldLeaseDurationNanosMultipler) {
|
||||||
|
this.veryOldLeaseDurationNanosMultiplier = (int) veryOldLeaseDurationNanosMultipler;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides the default very old lease duration nanos multiplier to increase the threshold for taking very old leases.
|
* Overrides the default very old lease duration nanos multiplier to increase the threshold for taking very old leases.
|
||||||
* Setting this to a higher value than 3 will increase the threshold for very old lease taking.
|
* Setting this to a higher value than 3 will increase the threshold for very old lease taking.
|
||||||
*
|
*
|
||||||
* @param veryOldLeaseDurationNanosMultipler Very old lease duration multiplier for adjusting very old lease taking.
|
* @param veryOldLeaseDurationNanosMultiplier Very old lease duration multiplier for adjusting very old lease taking.
|
||||||
* @return LeaseTaker
|
* @return LeaseTaker
|
||||||
*/
|
*/
|
||||||
public DynamoDBLeaseTaker withVeryOldLeaseDurationNanosMultipler(long veryOldLeaseDurationNanosMultipler) {
|
public DynamoDBLeaseTaker withVeryOldLeaseDurationNanosMultiplier(int veryOldLeaseDurationNanosMultiplier) {
|
||||||
this.veryOldLeaseDurationNanosMultiplier = veryOldLeaseDurationNanosMultipler;
|
this.veryOldLeaseDurationNanosMultiplier = veryOldLeaseDurationNanosMultiplier;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,7 +200,7 @@ public class DynamoDBLeaseTaker implements LeaseTaker {
|
||||||
|
|
||||||
List<Lease> expiredLeases = getExpiredLeases();
|
List<Lease> expiredLeases = getExpiredLeases();
|
||||||
|
|
||||||
Set<Lease> leasesToTake = computeLeasesToTake(expiredLeases);
|
Set<Lease> leasesToTake = computeLeasesToTake(expiredLeases, timeProvider);
|
||||||
leasesToTake = updateStaleLeasesWithLatestState(updateAllLeasesTotalTimeMillis, leasesToTake);
|
leasesToTake = updateStaleLeasesWithLatestState(updateAllLeasesTotalTimeMillis, leasesToTake);
|
||||||
|
|
||||||
Set<String> untakenLeaseKeys = new HashSet<>();
|
Set<String> untakenLeaseKeys = new HashSet<>();
|
||||||
|
|
@ -374,9 +383,11 @@ public class DynamoDBLeaseTaker implements LeaseTaker {
|
||||||
* Compute the number of leases I should try to take based on the state of the system.
|
* Compute the number of leases I should try to take based on the state of the system.
|
||||||
*
|
*
|
||||||
* @param expiredLeases list of leases we determined to be expired
|
* @param expiredLeases list of leases we determined to be expired
|
||||||
|
* @param timeProvider callable which returns the current time in nanos
|
||||||
* @return set of leases to take.
|
* @return set of leases to take.
|
||||||
*/
|
*/
|
||||||
private Set<Lease> computeLeasesToTake(List<Lease> expiredLeases) {
|
@VisibleForTesting
|
||||||
|
Set<Lease> computeLeasesToTake(List<Lease> expiredLeases, Callable<Long> timeProvider) throws DependencyException {
|
||||||
Map<String, Integer> leaseCounts = computeLeaseCounts(expiredLeases);
|
Map<String, Integer> leaseCounts = computeLeaseCounts(expiredLeases);
|
||||||
Set<Lease> leasesToTake = new HashSet<>();
|
Set<Lease> leasesToTake = new HashSet<>();
|
||||||
final MetricsScope scope = MetricsUtil.createMetricsWithOperation(metricsFactory, TAKE_LEASES_DIMENSION);
|
final MetricsScope scope = MetricsUtil.createMetricsWithOperation(metricsFactory, TAKE_LEASES_DIMENSION);
|
||||||
|
|
@ -430,7 +441,13 @@ public class DynamoDBLeaseTaker implements LeaseTaker {
|
||||||
// If there are leases that have been expired for an extended period of
|
// If there are leases that have been expired for an extended period of
|
||||||
// time, take them with priority, disregarding the target (computed
|
// time, take them with priority, disregarding the target (computed
|
||||||
// later) but obeying the maximum limit per worker.
|
// later) but obeying the maximum limit per worker.
|
||||||
final long nanoThreshold = System.nanoTime() - (veryOldLeaseDurationNanosMultiplier * leaseDurationNanos);
|
long currentNanoTime;
|
||||||
|
try {
|
||||||
|
currentNanoTime = timeProvider.call();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new DependencyException("Exception caught from timeProvider", e);
|
||||||
|
}
|
||||||
|
final long nanoThreshold = currentNanoTime - (veryOldLeaseDurationNanosMultiplier * leaseDurationNanos);
|
||||||
final List<Lease> veryOldLeases = allLeases.values().stream()
|
final List<Lease> veryOldLeases = allLeases.values().stream()
|
||||||
.filter(lease -> nanoThreshold > lease.lastCounterIncrementNanos())
|
.filter(lease -> nanoThreshold > lease.lastCounterIncrementNanos())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import static org.mockito.Mockito.when;
|
||||||
public class DynamoDBLeaseCoordinatorTest {
|
public class DynamoDBLeaseCoordinatorTest {
|
||||||
|
|
||||||
private static final String WORKER_ID = UUID.randomUUID().toString();
|
private static final String WORKER_ID = UUID.randomUUID().toString();
|
||||||
|
private static final int VERY_OLD_LEASE_DURATION_MULTIPLIER = 5;
|
||||||
private static final long LEASE_DURATION_MILLIS = 5000L;
|
private static final long LEASE_DURATION_MILLIS = 5000L;
|
||||||
private static final long EPSILON_MILLIS = 25L;
|
private static final long EPSILON_MILLIS = 25L;
|
||||||
private static final int MAX_LEASES_FOR_WORKER = Integer.MAX_VALUE;
|
private static final int MAX_LEASES_FOR_WORKER = Integer.MAX_VALUE;
|
||||||
|
|
@ -39,7 +40,8 @@ public class DynamoDBLeaseCoordinatorTest {
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
this.leaseCoordinator = new DynamoDBLeaseCoordinator(leaseRefresher, WORKER_ID, LEASE_DURATION_MILLIS,
|
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,
|
VERY_OLD_LEASE_DURATION_MULTIPLIER, 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);
|
INITIAL_LEASE_TABLE_READ_CAPACITY, INITIAL_LEASE_TABLE_WRITE_CAPACITY, metricsFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ public class DynamoDBLeaseTakerIntegrationTest extends LeaseIntegrationTest {
|
||||||
builder.withLease("4", "bar").build();
|
builder.withLease("4", "bar").build();
|
||||||
|
|
||||||
// setting multiplier to unusually high number to avoid very old lease taking
|
// setting multiplier to unusually high number to avoid very old lease taking
|
||||||
taker.withVeryOldLeaseDurationNanosMultipler(5000000000L);
|
taker.withVeryOldLeaseDurationNanosMultiplier(5000000);
|
||||||
builder.takeMutateAssert(taker, 2);
|
builder.takeMutateAssert(taker, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
@ -46,6 +48,8 @@ public class DynamoDBLeaseTakerTest {
|
||||||
|
|
||||||
private static final String WORKER_IDENTIFIER = "foo";
|
private static final String WORKER_IDENTIFIER = "foo";
|
||||||
private static final long LEASE_DURATION_MILLIS = 1000L;
|
private static final long LEASE_DURATION_MILLIS = 1000L;
|
||||||
|
private static final int VERY_OLD_LEASE_DURATION_MULTIPLIER = 5;
|
||||||
|
private static final long MOCK_CURRENT_TIME = 10000000000L;
|
||||||
|
|
||||||
private DynamoDBLeaseTaker dynamoDBLeaseTaker;
|
private DynamoDBLeaseTaker dynamoDBLeaseTaker;
|
||||||
|
|
||||||
|
|
@ -88,7 +92,7 @@ public class DynamoDBLeaseTakerTest {
|
||||||
|
|
||||||
when(leaseRefresher.listLeases()).thenReturn(leases);
|
when(leaseRefresher.listLeases()).thenReturn(leases);
|
||||||
when(metricsFactory.createMetrics()).thenReturn(new NullMetricsScope());
|
when(metricsFactory.createMetrics()).thenReturn(new NullMetricsScope());
|
||||||
when(timeProvider.call()).thenReturn(1000L);
|
when(timeProvider.call()).thenReturn(MOCK_CURRENT_TIME);
|
||||||
|
|
||||||
final Map<String, Integer> actualOutput = dynamoDBLeaseTaker.computeLeaseCounts(ImmutableList.of());
|
final Map<String, Integer> actualOutput = dynamoDBLeaseTaker.computeLeaseCounts(ImmutableList.of());
|
||||||
|
|
||||||
|
|
@ -112,7 +116,7 @@ public class DynamoDBLeaseTakerTest {
|
||||||
|
|
||||||
when(leaseRefresher.listLeases()).thenReturn(leases);
|
when(leaseRefresher.listLeases()).thenReturn(leases);
|
||||||
when(metricsFactory.createMetrics()).thenReturn(new NullMetricsScope());
|
when(metricsFactory.createMetrics()).thenReturn(new NullMetricsScope());
|
||||||
when(timeProvider.call()).thenReturn(1000L);
|
when(timeProvider.call()).thenReturn(MOCK_CURRENT_TIME);
|
||||||
|
|
||||||
final Map<String, Integer> actualOutput = dynamoDBLeaseTaker.computeLeaseCounts(leases);
|
final Map<String, Integer> actualOutput = dynamoDBLeaseTaker.computeLeaseCounts(leases);
|
||||||
|
|
||||||
|
|
@ -121,6 +125,32 @@ public class DynamoDBLeaseTakerTest {
|
||||||
assertEquals(expectedOutput, actualOutput);
|
assertEquals(expectedOutput, actualOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_veryOldLeaseDurationNanosMultiplierGetsCorrectLeases() throws Exception {
|
||||||
|
long veryOldThreshold = MOCK_CURRENT_TIME -
|
||||||
|
(TimeUnit.MILLISECONDS.toNanos(LEASE_DURATION_MILLIS) * VERY_OLD_LEASE_DURATION_MULTIPLIER);
|
||||||
|
DynamoDBLeaseTaker dynamoDBLeaseTakerWithCustomMultiplier =
|
||||||
|
new DynamoDBLeaseTaker(leaseRefresher, WORKER_IDENTIFIER, LEASE_DURATION_MILLIS, metricsFactory)
|
||||||
|
.withVeryOldLeaseDurationNanosMultiplier(VERY_OLD_LEASE_DURATION_MULTIPLIER);
|
||||||
|
final List<Lease> allLeases = new ImmutableList.Builder<Lease>()
|
||||||
|
.add(createLease("foo", "2", MOCK_CURRENT_TIME))
|
||||||
|
.add(createLease("bar", "3", veryOldThreshold - 1))
|
||||||
|
.add(createLease("baz", "4", veryOldThreshold))
|
||||||
|
.build();
|
||||||
|
final List<Lease> expiredLeases = allLeases.subList(1, 3);
|
||||||
|
|
||||||
|
dynamoDBLeaseTakerWithCustomMultiplier.allLeases.putAll(
|
||||||
|
allLeases.stream().collect(Collectors.toMap(Lease::leaseKey, Function.identity())));
|
||||||
|
when(leaseRefresher.listLeases()).thenReturn(allLeases);
|
||||||
|
when(metricsFactory.createMetrics()).thenReturn(new NullMetricsScope());
|
||||||
|
when(timeProvider.call()).thenReturn(MOCK_CURRENT_TIME);
|
||||||
|
|
||||||
|
Set<Lease> output = dynamoDBLeaseTakerWithCustomMultiplier.computeLeasesToTake(expiredLeases, timeProvider);
|
||||||
|
final Set<Lease> expectedOutput = new HashSet<>();
|
||||||
|
expectedOutput.add(allLeases.get(1));
|
||||||
|
assertEquals(expectedOutput, output);
|
||||||
|
}
|
||||||
|
|
||||||
private Lease createLease(String leaseOwner, String leaseKey) {
|
private Lease createLease(String leaseOwner, String leaseKey) {
|
||||||
final Lease lease = new Lease();
|
final Lease lease = new Lease();
|
||||||
lease.checkpoint(new ExtendedSequenceNumber("checkpoint"));
|
lease.checkpoint(new ExtendedSequenceNumber("checkpoint"));
|
||||||
|
|
@ -132,4 +162,17 @@ public class DynamoDBLeaseTakerTest {
|
||||||
lease.leaseKey(leaseKey);
|
lease.leaseKey(leaseKey);
|
||||||
return lease;
|
return lease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Lease createLease(String leaseOwner, String leaseKey, long lastCounterIncrementNanos) {
|
||||||
|
final Lease lease = new Lease();
|
||||||
|
lease.checkpoint(new ExtendedSequenceNumber("checkpoint"));
|
||||||
|
lease.ownerSwitchesSinceCheckpoint(0L);
|
||||||
|
lease.leaseCounter(0L);
|
||||||
|
lease.leaseOwner(leaseOwner);
|
||||||
|
lease.parentShardIds(Collections.singleton("parentShardId"));
|
||||||
|
lease.childShardIds(new HashSet<>());
|
||||||
|
lease.leaseKey(leaseKey);
|
||||||
|
lease.lastCounterIncrementNanos(lastCounterIncrementNanos);
|
||||||
|
return lease;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue