Re: Proxying document updates with update handlers
Hi, It’s worth remembering that the reason the new _rev is not available in your _update handler is because the database update happens afterward, and thus the value is not known. Indeed, it is not known if the update even succeeded (or failed because couchdb crashed, or there was a validate_doc_update error or you’d get a 409). _update handler is just a way to move some logic to the server side, it isn’t being process ed inline with the database update itself. Note also that the presence of an update handler doesn’t force all clients to use it, you’d need to enforce that some other way. Jan is (of course) correct that this kind of thing is better done at the client end. B. > On 28 May 2021, at 07:50, Jan Lehnardt wrote: > > Hi Aurélien, > > we generally recommend doing this kind of stuff outside of CouchDB, > these days. > > A Node.js proxy that does this completely and reliably is maybe 50 > lines of code and not a huge operational overhead, while granted not > as neat as doing all this inside of CouchDB. > > As for getting the new _rev in the function: the rev will be generated > from the result that the function returns, so there is no way to get > that other than calculating it yourself (it is deterministic), but > that requires knowledge of erlang term encoding and such things. I’ve > done it in JS (for other things), but it is not pretty. > > Best > Jan > — > Professional Support for Apache CouchDB: > https://neighbourhood.ie/couchdb-support/ > > 24/7 Observation for your CouchDB Instances: > https://opservatory.app > >> On 27. May 2021, at 22:08, Aurélien Bénel wrote: >> >> Dear all, >> >> I have known update handlers for quite long but I never used them "for real" >> myself... My current idea, which must be very common, is to proxy updates of >> whole documents in order to add some accountability of who contributed to >> the document and when. >> >> # rewrites.json >> [{ >> "from": "", >> "to": "elsewhere", >> "method": "GET" >>}, { >> "from": "", >> "to": "_update/accounting" >> }, { >> "from": ":object", >> "to": "../../:object", >> "method": "GET" >> }, { >> "from": ":object", >> "to": "_update/accounting/:object" >> }] >> >> # accounting.js >> function(doc, req) { >> var o = JSON.parse(req.body); >> o._id = o._id || req.id || req.uuid; >> var h = doc && doc.history || []; >> h.push({ >> user: req.userCtx.name, >> timestamp: new Date() >> }); >> o.history = h; >> return [o, {json: {ok: true, id: o._id }}]; >> } >> >> Tested on CouchDB 2.3.1, it *nearly* emulates the direct update of a >> document and adds contributions accounting, however I face two problems ; >> >> 1. In the update handler, I see no way to get the new `_rev` value (which >> should be returned either in the JSON body or as an ETag for compatibility >> with normal update of an object). Is there a secret builtin function that >> could be used to get (or set) this? Or is it set afterwards and then cannot >> be get or set at this stage of the process? >> >> 2. In the update handler, when used with POST (with the `_id` in the body >> but not in the URI), it seems that `doc` is always null (even when the ID >> refers to an existing document)... Is this behaviour intended? I feel that >> the documentation could be interpreted both ways... >> Of course, we can still use PUT. But I wanted a complete emulation of normal >> updates (with both methods)... >> >> Any help or insight would be appreciated. >> >> >> Regards, >> >> Aurélien >> >> >
Re: Proxying document updates with update handlers
Hi Aurélien, we generally recommend doing this kind of stuff outside of CouchDB, these days. A Node.js proxy that does this completely and reliably is maybe 50 lines of code and not a huge operational overhead, while granted not as neat as doing all this inside of CouchDB. As for getting the new _rev in the function: the rev will be generated from the result that the function returns, so there is no way to get that other than calculating it yourself (it is deterministic), but that requires knowledge of erlang term encoding and such things. I’ve done it in JS (for other things), but it is not pretty. Best Jan — Professional Support for Apache CouchDB: https://neighbourhood.ie/couchdb-support/ 24/7 Observation for your CouchDB Instances: https://opservatory.app > On 27. May 2021, at 22:08, Aurélien Bénel wrote: > > Dear all, > > I have known update handlers for quite long but I never used them "for real" > myself... My current idea, which must be very common, is to proxy updates of > whole documents in order to add some accountability of who contributed to the > document and when. > ># rewrites.json >[{ > "from": "", > "to": "elsewhere", > "method": "GET" > }, { > "from": "", > "to": "_update/accounting" >}, { > "from": ":object", > "to": "../../:object", > "method": "GET" >}, { > "from": ":object", > "to": "_update/accounting/:object" >}] > ># accounting.js >function(doc, req) { > var o = JSON.parse(req.body); > o._id = o._id || req.id || req.uuid; > var h = doc && doc.history || []; > h.push({ >user: req.userCtx.name, >timestamp: new Date() > }); > o.history = h; > return [o, {json: {ok: true, id: o._id }}]; >} > > Tested on CouchDB 2.3.1, it *nearly* emulates the direct update of a document > and adds contributions accounting, however I face two problems ; > > 1. In the update handler, I see no way to get the new `_rev` value (which > should be returned either in the JSON body or as an ETag for compatibility > with normal update of an object). Is there a secret builtin function that > could be used to get (or set) this? Or is it set afterwards and then cannot > be get or set at this stage of the process? > > 2. In the update handler, when used with POST (with the `_id` in the body but > not in the URI), it seems that `doc` is always null (even when the ID refers > to an existing document)... Is this behaviour intended? I feel that the > documentation could be interpreted both ways... > Of course, we can still use PUT. But I wanted a complete emulation of normal > updates (with both methods)... > > Any help or insight would be appreciated. > > > Regards, > > Aurélien > >
Re: Proxying document updates with update handlers
Consider using JS _rewrite for this, it can do whatever you want with your request. https://docs.couchdb.org/en/2.3.1/api/ddoc/rewrites.html?highlight=_rewrite#using-a-stringified-function-for-rewrites Please note, that JS _rewrite in v 2.3.1 has a bug which may cause inbound attachments to drop (https://github.com/apache/couchdb/issues/1878), it was fixed in 3.0 afaik. ermouth чт, 27 мая 2021 г. в 23:09, Aurélien Bénel : > Dear all, > > I have known update handlers for quite long but I never used them "for > real" myself... My current idea, which must be very common, is to proxy > updates of whole documents in order to add some accountability of who > contributed to the document and when. > > # rewrites.json > [{ >"from": "", >"to": "elsewhere", >"method": "GET" > }, { > "from": "", > "to": "_update/accounting" > }, { >"from": ":object", > "to": "../../:object", >"method": "GET" > }, { >"from": ":object", >"to": "_update/accounting/:object" > }] > > # accounting.js > function(doc, req) { > var o = JSON.parse(req.body); > o._id = o._id || req.id || req.uuid; > var h = doc && doc.history || []; > h.push({ > user: req.userCtx.name, > timestamp: new Date() > }); > o.history = h; > return [o, {json: {ok: true, id: o._id }}]; > } > > Tested on CouchDB 2.3.1, it *nearly* emulates the direct update of a > document and adds contributions accounting, however I face two problems ; > > 1. In the update handler, I see no way to get the new `_rev` value (which > should be returned either in the JSON body or as an ETag for compatibility > with normal update of an object). Is there a secret builtin function that > could be used to get (or set) this? Or is it set afterwards and then cannot > be get or set at this stage of the process? > > 2. In the update handler, when used with POST (with the `_id` in the body > but not in the URI), it seems that `doc` is always null (even when the ID > refers to an existing document)... Is this behaviour intended? I feel that > the documentation could be interpreted both ways... > Of course, we can still use PUT. But I wanted a complete emulation of > normal updates (with both methods)... > > Any help or insight would be appreciated. > > > Regards, > > Aurélien > > >
Proxying document updates with update handlers
Dear all, I have known update handlers for quite long but I never used them "for real" myself... My current idea, which must be very common, is to proxy updates of whole documents in order to add some accountability of who contributed to the document and when. # rewrites.json [{ "from": "", "to": "elsewhere", "method": "GET" }, { "from": "", "to": "_update/accounting" }, { "from": ":object", "to": "../../:object", "method": "GET" }, { "from": ":object", "to": "_update/accounting/:object" }] # accounting.js function(doc, req) { var o = JSON.parse(req.body); o._id = o._id || req.id || req.uuid; var h = doc && doc.history || []; h.push({ user: req.userCtx.name, timestamp: new Date() }); o.history = h; return [o, {json: {ok: true, id: o._id }}]; } Tested on CouchDB 2.3.1, it *nearly* emulates the direct update of a document and adds contributions accounting, however I face two problems ; 1. In the update handler, I see no way to get the new `_rev` value (which should be returned either in the JSON body or as an ETag for compatibility with normal update of an object). Is there a secret builtin function that could be used to get (or set) this? Or is it set afterwards and then cannot be get or set at this stage of the process? 2. In the update handler, when used with POST (with the `_id` in the body but not in the URI), it seems that `doc` is always null (even when the ID refers to an existing document)... Is this behaviour intended? I feel that the documentation could be interpreted both ways... Of course, we can still use PUT. But I wanted a complete emulation of normal updates (with both methods)... Any help or insight would be appreciated. Regards, Aurélien