-
Notifications
You must be signed in to change notification settings - Fork 167
GH-66: Add DynamoDbLockRegistry implementation #93
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
Conversation
Depends on: spring-projects/spring-integration#2455 would you mind, please, to take a look here? I don't tell that you need to jump into the AWS details, just wonder if you could find some flaws around Java concurrency usage. Thanks |
BTW, need Docs on the matter and maybe more JavaDocs (depends of the review). Thanks |
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.
That's all for this pass.
|
||
@Override | ||
public boolean isAutoStartup() { | ||
return true; |
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.
Why not configurable?
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.
If you take a look into the start()
, there is nothing just table creation on the AWS: I just moved the hard network job into the start()
instead of afterPropertiesSet()
.
Therefore I don't see reason to have this not started automatically - it isn't going to be useful without created table. Or... the table must be provided in advance.
I can't reconsider this if there is really a strong feeling on the matter.
By the way: is it going to work just with the Lifecycle
? I mean this will be as a bean and container will start it anyway. The point is do not expose lifecycle control to end user at all.
Thanks
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.
Another inconvenience that this AmazonDynamoDBLockClient
is not async and we really can't initiate request and exit, like we do in the DynamoDbMetaDataStore.afterPropertiesSet()
.
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.
OK; thanks for the explanation; no Lifecycle
beans are not started unless the user start()
s the container.
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.
OK! I decided to remove lifecycle control in favor of the separate thread execution in the afterPropertiesSet()
.
See an update in commits.
// This is allowed minimum for constant AWS requests. | ||
Thread.sleep(1000); | ||
} | ||
catch (InterruptedException e) { |
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.
Thread.currentThread().interrupt()
.
|
||
@Override | ||
public void stop() { | ||
this.running.set(false); |
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.
Nothing to do on AWS?
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.
Well, agreed. Will move the destroy()
logic here. When we stopped, we shouldn't schedule any heart beats to the AWS. Good catch! 👍
|
||
@Override | ||
public boolean isRunning() { | ||
return false; |
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.
this.running.get()
|
||
@Override | ||
public int getPhase() { | ||
return Integer.MAX_VALUE; |
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.
Why not configurable? Shouldn't it be relatively early?
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.
M-m-m. I thought Integer.MAX_VALUE
is the last phase in the order. No?
Should it be Integer.MIN_VALUE
then.
On the other hand it really might be better to create table on AWS as early as possible and let our consumers (e.g. aggregator) to do its work just in time.
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.
Max value seems wrong in cases where someone wants to get a lock in a Lifecycle.start().
I would have thought earlier than max_value, but certainly not min-value; maybe 0 is the best in this case.
} | ||
catch (InterruptedException e) { | ||
Thread.currentThread().interrupt(); | ||
throw new IllegalStateException("The DynamoDb table " + this.tableName + |
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.
Shouldn't this be also thrown in the await returns false?
|
||
@Override | ||
public Lock obtain(Object lockKey) { | ||
Assert.isInstanceOf(String.class, lockKey); |
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.
Deprecated assertion - needs message.
* This method must be uninterruptible so catch and ignore | ||
* interrupts and only break out of the while loop when | ||
* we get the lock. | ||
*/ |
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.
We should reinstate the interrupt before exiting, though - set a boolean and add finally to an outer try?
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.
That's just Dave Syer's magic copy/paste from the JdbcLockRegistry
😄 . Sorry, I don't understand what you mean.
Some code sample?
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.
public void lock() {
this.delegate.lock();
boolean wasInterruptedWhileUninterruptible = false;
try {
while (true) {
try {
while (!doLock()) {
Thread.sleep(100); //NOSONAR
}
break;
}
catch (CannotSerializeTransactionException | TransactionTimedOutException | QueryTimeoutException e) {
// try again
}
catch (InterruptedException e) {
/*
* This method must be uninterruptible so catch and ignore
* interrupts and only break out of the while loop when
* we get the lock.
*/
wasInterruptedWhileUninterruptible = true;
}
catch (Exception e) {
this.delegate.unlock();
rethrowAsLockException(e);
}
}
}
finally {
if (wasInterruptedWhileUninterruptible) {
Thread.currentThread().interrupt();
}
}
}
execution in the `afterPropertiesSet()` * Fix `lock()` interruptibility logic
build.gradle
Outdated
@@ -23,6 +23,7 @@ apply from: "${rootProject.projectDir}/publish-maven.gradle" | |||
group = 'org.springframework.integration' | |||
|
|||
repositories { | |||
mavenLocal() |
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.
Intentional?
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.
Right, because I tested it against the build in my just merged PR in SI spring-projects/spring-integration#2455.
Now this change can be reverted.
* decrease an amount of expectations in the Kinesis test
Fixes #66