Skip to content

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

Merged
merged 5 commits into from
Jun 8, 2018

Conversation

artembilan
Copy link
Member

Fixes #66

@artembilan
Copy link
Member Author

Depends on: spring-projects/spring-integration#2455

@garyrussell ,

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

@artembilan
Copy link
Member Author

BTW, need Docs on the matter and maybe more JavaDocs (depends of the review).
Will come back to that after some feedback.

Thanks

Copy link
Contributor

@garyrussell garyrussell left a 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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not configurable?

Copy link
Member Author

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

Copy link
Member Author

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().

Copy link
Contributor

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.

Copy link
Member Author

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) {
Copy link
Contributor

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);
Copy link
Contributor

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?

Copy link
Member Author

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;
Copy link
Contributor

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;
Copy link
Contributor

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?

Copy link
Member Author

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.

Copy link
Contributor

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 +
Copy link
Contributor

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);
Copy link
Contributor

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.
*/
Copy link
Contributor

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?

Copy link
Member Author

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?

Copy link
Contributor

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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional?

Copy link
Member Author

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.

@garyrussell garyrussell merged commit 5c262f1 into spring-projects:master Jun 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants