Re: Proxying document updates with update handlers

2021-05-28 Thread Robert Newson
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

2021-05-28 Thread Jan Lehnardt
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

2021-05-27 Thread ermouth
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

2021-05-27 Thread 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