Skip to content
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

Optimistic Locking is not working when using Repository save method [DATACOUCH-212] #522

Closed
spring-projects-issues opened this issue Mar 5, 2016 · 7 comments
Labels
type: bug

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented Mar 5, 2016

Jordan Scherle opened DATACOUCH-212 and commented

Optimistic Locking doesn't appear to be working any longer when using the repository "save" method to save an entity. This was previously working in the 1.4 release.

Steps to reproduce:
-Create a Document class with the @Version annotation
-Create a CrudRepository referencing the Document class
-Load an existing document via the repository "findOne" method in thread 1 (validated the cas is set in this document)
-In thread 2 update the same document
-In thread 1, save the document using the repository "save" method

Expected Result:
A CASMismatchException is thrown

Actual Result:
No exception is thrown and thread 1 overwrites the document thread 2 had saved

Note: this exact scenario was working in 1.4 release


Affects: 2.0 GA, 2.1 RC1 (Hopper)

Issue Links:

  • DATACOUCH-224 Improve concurrent save/insert optimistic locking
    ("is depended on by")
@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 23, 2016

Anastasiia Smirnova commented

I've just found the same issue, tried last version with fix. But it seems that it does not handle case of concurrent writes of new document with the same key.
I have created pull request with failing test for this case: #109
I am not sure, but it looks like it is not quite correct behavior

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 23, 2016

Simon Baslé commented

@anastasiia thanks for checking this further. Turns out the OptimisticLocking check is only meaningful if the @Version annotated field bears a CAS that is non-zero.

So what you could do is do a first insert, get the associated version value and set that as the version of the ones that you construct in the threads. This should trigger the optimistic locking. I'll comment on the PR with some code to achieve that, since JIRA is not ideal for long(ish) code snippets ;)

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 23, 2016

Anastasiia Smirnova commented

Thanks for the quick reply!
I was hoping to use only CrudRepository interface for merging data, but it looks like I need more low level operations to do that. In previous version of spring-data-couchbase this case worked, but now not. :( I think, that this case should be handled appropriately by Repository without any other manipulations with neither CouchbaseOperation nor Bucket. Correct me if I am wrong. Thanks

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 23, 2016

Simon Baslé commented

I think it should work equally as well with the CrudRepository, just that you need a non-zero value for the @Version field (since this maps to the CAS in couchbase, and at the protocol level the CAS is not checked against if it is 0)

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 23, 2016

Simon Baslé commented

Jordan's scenario works as well: get the doc from the database (through the repository), which will populate it's @Version annotated field. Mutate that document and save, or reuse that document's version value and attempt multiple parallel saves

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 23, 2016

Anastasiia Smirnova commented

Using the following https://github.com/spring-projects/spring-retry#java-configuration-for-retry-proxies
Was observed the following issue:

doWithRetryOnOptimisticLock{
  findOne()
  if exists -> merge with new data
  if not exists -> generate new doc
  save()
} 

This flow was working for spring data for couchbase client 1.x and gives data loss in 2.x since there is no error when saving document with no version over existing document in concurrent mode.

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Mar 24, 2016

Anastasiia Smirnova commented

I've made a fix, please review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug
Projects
None yet
Development

No branches or pull requests

1 participant