-
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
Allow tags to be added when lease table is created #1065
Conversation
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.
Thanks for the contribution! PR mostly LGTM, and verified mvn clean test
against a rebase. A few small requested changes, and question.
@@ -190,6 +194,8 @@ public class LeaseManagementConfig { | |||
|
|||
private BillingMode billingMode = BillingMode.PAY_PER_REQUEST; | |||
|
|||
private Collection<Tag> tags = DefaultSdkAutoConstructList.getInstance(); |
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.
FMI: why DefaultSdkAutoConstructList
(DSACL) instead of Collections.emptyList()
(CeL)? Since DSACL is backed by a CeL, what is the benefit?
Would you kindly add Javadoc to this new member variable?
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.
I used DSACL as that was the default value associated with the tags in the CreateTable
request. I'm not overly familiar with the java SDK, or java in general, but I figured if no tags were specified then we would be essentially setting the value to in the CreateTable to the default value already there, and would avoid complicated branching scenarios.
Happy to change to a CeL instead if preferred.
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.
Thanks for the context! Given the SDK dive into TagListCopier, DSACL seems the better option if the SDK sniffs for the SdkAutoConstructList
marker interface in other places.
* @param tags | ||
*/ | ||
@Deprecated | ||
public DynamoDBLeaseManagementFactory(final KinesisAsyncClient kinesisClient, final String streamName, |
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.
N.B. These large parameters lists are an anti-pattern. @see http://principles-wiki.net/anti-patterns:long_parameter_list
We (AWS) should hold ourselves to higher standards and refactor this mess (which is, unfortunately, systemic in KCL).
No change necessary by PR author.
...nt/src/main/java/software/amazon/kinesis/leases/dynamodb/DynamoDBLeaseManagementFactory.java
Show resolved
Hide resolved
} else { | ||
request = CreateTableRequest.builder().tableName(table).keySchema(serializer.getKeySchema()) | ||
.attributeDefinitions(serializer.getAttributeDefinitions()).provisionedThroughput(throughput) | ||
.tags(tags) |
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.
FYI: validated TagListCopier
protects against nulls:
static List<Tag> copy(Collection<? extends Tag> tagListParam) {
List<Tag> list;
if (tagListParam == null || tagListParam instanceof SdkAutoConstructList) {
list = DefaultSdkAutoConstructList.getInstance();
} else {
List<Tag> modifiableList = new ArrayList<>();
tagListParam.forEach(entry -> {
modifiableList.add(entry);
});
list = Collections.unmodifiableList(modifiableList);
}
return list;
(This might also answer my question w.r.t. DSACL.)
@@ -168,10 +192,13 @@ public boolean createLeaseTableIfNotExists(@NonNull final Long readCapacity, @No | |||
if(BillingMode.PAY_PER_REQUEST.equals(billingMode)){ | |||
request = CreateTableRequest.builder().tableName(table).keySchema(serializer.getKeySchema()) | |||
.attributeDefinitions(serializer.getAttributeDefinitions()) | |||
.billingMode(billingMode).build(); | |||
.billingMode(billingMode) | |||
.tags(tags) |
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.
Don't repeat yourself (i.e., here, line ~201, line ~217).
A suggested refactor is to create a method that provides the "base" builder. Example:
private CreateTableRequest.Builder createTableRequestBuilder() {
final CreateTableRequest.Builder builder = CTR.builder()
.tableName(...)
.tags(tags)
... /* and other shared elements */;
if (BillingMode.PAY_PER_REQUEST...) {
builder.billingMode(billingMode);
}
return builder;
}
Then this method simplifies to something like:
final CTR.B builder = createTRQB();
if (!BillingMode.PAY_PER_REQUEST...) {
ProvisionedThroughput throughput = ...
builder.provisionedThroughput(throughput);
}
return createTableIfNotExists(builder.build());
@@ -313,6 +317,40 @@ public void testCreateLeaseTableProvisionedBillingModeIfNotExists() throws Excep | |||
Assert.assertTrue(result); | |||
} | |||
|
|||
@Test | |||
public void testCreateLeaseTableWithTagsIfNotExists() throws Exception { | |||
tags = Arrays.asList(Tag.builder().key("foo").value("bar").build()); |
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.
IDE warning: s/Arrays.asList/Collections.singletonList/
tableCreatorCallback, LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT, BillingMode.PROVISIONED, tags); | ||
|
||
when(dynamoDbClient.describeTable(describeTableRequest)).thenReturn(mockDescribeTableFuture); | ||
when(mockDescribeTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS))) |
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.
When all parameters are "raw values", eq
is unnecessary and can/should be removed.
edit: and lines ~340, 348~350
.tags(tags) | ||
.build(); | ||
when(dynamoDbClient.createTable(createTableRequest)).thenReturn(mockCreateTableFuture); | ||
when(mockCreateTableFuture.get(eq(LeaseManagementConfig.DEFAULT_REQUEST_TIMEOUT.toMillis()), eq(TimeUnit.MILLISECONDS))) |
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.
thenReturn(null)
is the default behavior for Mockito mock objects. This statement is unnecessary and can be removed.
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.
I've just re-run the tests with this removed and it's now throwing exceptions around incomplete mocking. Adding it back in fixes the test.
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.
Strange. "Works on my machine" w/o this line (and I'm sync'd to 6783e1e
+rebase). It's an insignificant concern, so let's leave as-is for this PR.
|
||
final boolean result = leaseRefresher.createLeaseTableIfNotExists(10L, 10L); | ||
|
||
verify(dynamoDbClient, times(1)).describeTable(describeTableRequest); |
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.
FYI: times(1)
is the default VerificationMode and is therefore redundant/unnecessary.
This verification block is duplicated several times in this class. Unless you choose to take ownership, that is something we (AWS) can deduplicate in a future commit.
Thanks for taking a look and the guidance! I'm not a java dev by any means, so appreciate there's quite a bit in there I didn't know. I believe I've addressed all of the changes requested and added my reasoning about using DSACL above. |
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.
LGTM (w/ one small request)!
To double-check: did you execute this in an AWS account and validate the DDB tags appear and will satisfy your ask in #154 ?
@@ -787,6 +802,16 @@ protected DependencyException convertAndRethrowExceptions(String operation, Stri | |||
} | |||
} | |||
|
|||
private CreateTableRequest.Builder createTableRequestBuilder() { | |||
final CreateTableRequest.Builder builder = CreateTableRequest.builder().tableName(table).keySchema(serializer.getKeySchema()) |
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.
The indentation for code in this method is incorrect. (Looks like most lines should be indented +1 level?)
Would you kindly fix so the indentation matches the convention of other methods?
(FWIW, I normally regard whitespace as a nitpick. However, seeing }
at position 1 is jarring when it isn't end-of-class.)
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.
Fixed!
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.
PR LGTM. I'll take this for a "test-drive" to validate before merging. Thanks for taking ownership and contributing this PR!
I did execute this in an AWS account and could see tags being added to the table correctly. I also tested to make sure that creating without tags still worked. I can add some integration tests for this the same as the others in the project, however, I seem to be hitting intermittent failures when running them from |
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.
@RyanFrench Would you kindly apply the following patch to your branch:
diff --git a/amazon-kinesis-client/src/main/java/software/amazon/kinesis/leases/dynamodb/DynamoDBLeaseManagementFactory.java b/amazon-kinesis-client/src/main/java/software/amazon/kinesis/leases/dynamodb/DynamoDBLeaseManagementFactory.java
index b06561a..8b60f6d 100644
--- a/amazon-kinesis-client/src/main/java/software/amazon/kinesis/leases/dynamodb/DynamoDBLeaseManagementFactory.java
+++ b/amazon-kinesis-client/src/main/java/software/amazon/kinesis/leases/dynamodb/DynamoDBLeaseManagementFactory.java
@@ -648,7 +648,7 @@ public class DynamoDBLeaseManagementFactory implements LeaseManagementFactory {
@Override
public DynamoDBLeaseRefresher createLeaseRefresher() {
return new DynamoDBLeaseRefresher(tableName, dynamoDBClient, leaseSerializer, consistentReads,
- tableCreatorCallback, dynamoDbRequestTimeout, billingMode);
+ tableCreatorCallback, dynamoDbRequestTimeout, billingMode, tags);
}
@Override
With this patch, I verified that a virgin KCL application created the DDB lease table w/ the provided tags.
Nice work!
Done, and thank you for verifying and the help getting this over the line! |
Issue #, if available: #154
Description of changes: Add capability to add tags when creating the lease table
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.