Details
-
Bug
-
Resolution: Fixed
-
Minor
-
3.1.6, 4.1.2, 4.5.0
-
None
-
Untriaged
-
Unknown
Description
Performing a REPLACE_WITH_CAS operation on a key which has recently been deleted and then requested can occasionally return KEY_EEXISTS (key exists but with different CAS) instead of the expected KEY_ENOENT.
Steps to reproduce
Repeatedly:
1. Create document
2. Delete document
3. Attempt to fetch document
4. Attempt to replace document, specifying a CAS
#!/usr/bin/env python
|
|
from couchbase.bucket import Bucket |
from couchbase.exceptions import NotFoundError |
|
client = Bucket('couchbase://127.0.0.1:12000/default') |
|
while True: |
client.set("key", "x") |
client.delete("key") |
try: |
client.get("key") |
assert False |
except (NotFoundError): |
pass |
try: |
client.replace("key", "value", cas=10) |
except (NotFoundError): |
pass |
As an aside, the code here is basically making incorrect assumptions about the possible return values when using replace with CAS and not handling KEY_EEXISTS :-
- If you're in a single-client environment then the CAS is pointless (there's no possible concurrency), and so the REPLACE would always return KEY_ENOENT
- If you're in a multi-client environment (and hence using CAS to replace a given specific version of a document) then you need to handle both KEY_EEXISTS and KEY_ENOENT as:
- KEY_EEXISTS could be returned if another client modified the document (and hence the CAS has changed).
- KEY_ENOENT could be returned if another client has deleted the document.
As such I'm setting this as `minor` priority and targeting Spock.