Hey all, We had a customer get tripped up on a fairly obscure part of the API today and I thought I'd ask the community if we shouldn't tweak things lightly.
The basic setup was that a user accidentally deleted a doc and then went through the steps to recreate it. It all worked fine except the actual recreation threw an conflict error even though the user specified the "correct" revision of the deleted doc (ie, the revision that marked it as deleted rather than the revision of the body they used to restore). The issue here was that when we last changed revision tree merging in couch_db_updater we expressly tightened a check when recreating deleted documents to require that it have a _rev value at the root of the tree. (ie, no revision specified and had one auto-generated by couch). The reason for this was that there were cases when people specified internal revisions (ie, non leaf revisions) which CouchDB happily accepted and extended which created branches where there weren't any previously. I asked Robert Newson his thoughts and he leaned toward the current behavior being correct where I'm thinking that we should allow the extension. Given the disagreement I figured the mailing list would be the best place to ask what others though would be best given that its all a bit subtle. For the record, Bob's point was that by requiring the rev be absent when creating (or re-creating) a doc directly delineates (re-)?creation from update. I on the other hand know that even though no revision is specified it will still create a revision based on the deleted revision so the response you get back might look surprising when it doesn't start with "1-" which clearly indicates is using old history when re-creating the doc. Here's a link to a gist that shows the corner case towards the bottom. I'll also paste it below for future people that live in a sad post-gist world. https://gist.github.com/davisp/8484f2a8187dd214cae0fcde4d0c2440 Paul N.B. acurl is basically just an alias to "curl -u davisp" $ acurl 'https://davisp.cloudant.com/test-db/_all_docs?keys=["foo"]' | python -m json.tool { "rows": [ { "id": "foo", "key": "foo", "value": { "deleted": true, "rev": "2-eec205a9d413992850a6e32678485900" } } ], "total_rows": 7 } $ acurl 'https://davisp.cloudant.com/test-db/foo?rev=2-eec205a9d413992850a6e32678485900&revs=true' | python -m json.tool { "_deleted": true, "_id": "foo", "_rev": "2-eec205a9d413992850a6e32678485900", "_revisions": { "ids": [ "eec205a9d413992850a6e32678485900", "967a00dff5e02add41819138abb3284d" ], "start": 2 } } $ acurl https://davisp.cloudant.com/test-db/foo?rev=1-967a00dff5e02add41819138abb3284d | python -m json.tool { "error": "not_found", "reason": "missing" } $ # A curious corner case $ cat foo.json { "_id": "foo", "_rev": "2-eec205a9d413992850a6e32678485900", "stuff": "bar" } $ acurl -X PUT https://davisp.cloudant.com/test-db/foo -d @foo.json | python -m json.tool { "error": "conflict", "reason": "Document update conflict." }
