I have an issue where we need to either create or update a document depending on whether a document with property
x does or does not already exist in the db.
here is psuedo code for the issue:
if (documentWithPropXExistsOnDbQuery()): update doc with prop X else: create doc with prop x
here is a race condition where 2 or more callers can get to the else branch and create a document. Since the primary key is generated by
uuid the DB lets it go, but in the real world we have a duplicate. (please don’t tell me to switch out the pk logic, because it’s not an option here)
my thought is to roll my own lock where I basically do something like this:
lock = getLock(codeFileName+functionName) if lock: try: do work finally: releaseLock(codeFileName + functionName)
getLock would simply write a tiny doc to the db with persistToAllNodes
releaseLock would delete that document
the thinking is that no two callers could succeed in creating that lock.
Now, this is scary to us, because who knows if something wont go wrong and something, something, we fail to delete the document and “release this lock.”
So the obvious solution is to write the document with an couchbase expiration, but I can’t get a solid enough grasp of its governing semantics.
So here are my questions:
Is there an easier way to do what I’m looking to do?
What are the semantics of expirations, namely:
Is the timing guaranteed or is it along the lines of a hint?
I’ve read that getting the doc after the expiration will result in a
not found even though the doc hasn’t been deleted but what about inserting?
If I try to insert a doc (with an expiration) which is duplicate to a document that’s been inserted with an expiration, will it result in an ‘you can’t create a duplicate document’ error like I’m hoping, or will just upsert and reconfigure the expiration?
if a doc is expired but not yet actually deleted, will inserting the same doc again just result in a new doc with a new expiration like we are hoping, or are there potential surprises we need to look out for.