Eventing between collections, same ID giving an error

Hello.

I am trying to subtract some values from a collection and upsert the values in a new collection. So far i got a code that is working, but it do give alot of errors, and I guess i have not made a very good solutin. First of all i try to send a field and its value to a new collection, and I need to keep the same meta id.

  1. If the document is not excisting i want to create it. And insert the field.
  2. If the document is excisting i want to create the field.
  3. If the field is excisiting i want to update the value.

The working code i got so far:

function OnUpdate(doc, meta) {
log('Running OnUpdate for doc ID: ' + meta.id);

function get(data) {
    let results = [];

    Object.keys(data).forEach(key => {
        if (data[key] && typeof data[key] === 'object' && data[key].hasOwnProperty('type') && Array.isArray(data[key].value)) {
            const values = data[key].value.map(priceObj => parseFloat(priceObj.value));
            const highestValue = Math.max(...values);
            results.push({ type: data[key].type, value: value});
        }
    });

    return results;
}

const results = valueAndPrice(doc);
const metaObj = { id: meta.id };
const mutateOps = results.map(result => {
    log(`Adding operation to upsert ${result.type} with value ${result.value}`);
    return couchbase.MutateInSpec.upsert(result.type, result.value);
});

try {
    const mutateResult = couchbase.mutateIn(dst_bucket, metaObj, mutateOps);
    log('Document updated in a batch: ' + JSON.stringify(mutateResult));
} catch (error) {
    log(`Error updating document in a batch. Attempting to create a new document.`);
    let newDoc = {};
    results.forEach(result => {
        newDoc[result.type] = result.value;
    });

    try {
        const insertResult = couchbase.insert(dst_bucket, metaObj, newDoc);
        log('New document created: ' + JSON.stringify(insertResult));
    } catch (insertError) {
        log(`Error creating new document: ${JSON.stringify(insertError)}`);
    }
}

}

The errors:

  1. At the moment i just got to pray the error is caused of missing document, so I feel this is not a good solution.
  2. The code is working but is producing equal errors and success:
    The error i get: “New document created: {"error":{"code":2,"name":"LCB_KEY_EEXISTS","desc":"The document key already exists in the server.","key_already_exists":true},"success":false}”

Issues:

  1. I tried to find a better function for upserting a document, then a field or updating a value with no luck. Is there a function thats better suited for my needs? That would probably also adress the issue nr 2? The missing document is always created and the values seems to be updated with the newst ones. But the code always gives an error even it seems like its running seccessfully.

Can you show what the exception is here:

log(`Error updating document in a batch. Attempting to create a new document.`);

If the error is something other than the document not being found, the subsequent insert is going to fail with document key exists (like it is).

1 Like

Thank you for the response. This is the error I am getting:

"Error updating document: {"message":{"code":16,"desc":"LCB_ERR_INVALID_ARGUMENT (203): It is unambiguously determined that the error was caused because of invalid arguments from the user","name":"LCB_ERR_INVALID_ARGUMENT"},"stack":"Error\n at couchbase.mutateIn (couchbase.js:133:24)\n at OnUpdate (Values.js:27:40)"}

I also get this one:

[INFO] “Error updating document: {"message":{"code":18,"desc":"LCB_ERR_SUBDOC_XATTR_UNKNOWN_MACRO (324): Subdoc: XATTR unknown macro","name":"LCB_ERR_SUBDOC_XATTR_UNKNOWN_MACRO"},"stack":"Error\n at couchbase.mutateIn (couchbase.js:133:24)\n at OnUpdate (Values.js:27:40)"}”

Can you show what is output by this line before both types of errors?

log(`Adding operation to upsert ${result.type} with value ${result.value}`);

There might be more information from the errors if you remove the try/catch and let the frame work display the errors.

1 Like

I tried some changes and removed the try/catch, simplified the code and added some more logging. I can now see that some updates are working fine, but suddently it stops at some random reason with this error:

2024-03-28T15:44:12.114+00:00 [INFO] {“count”:1,“exception”:“{\n "message": {\n "code": 0,\n "desc": "LCB_ERR_KVENGINE_UNKNOWN_ERROR (1040): The server replied with an unrecognized status code. A newer version of this library may be able to decode it",\n "name": "LCB_ERR_KVENGINE_UNKNOWN_ERROR"\n },\n "stack": "Error\n at couchbase.mutateIn (couchbase.js:133:24)\n at Value.js:26:19\n at Array.forEach ()\n at OnUpdate (Value.js:21:13)"\n}”,“file”:“couchbase.js”,“line”:132,“since”:“2024-03-28T15:43:33”,“srcLine”:“return couchbase.mutateInInternal(bucket, meta, op_array, options);”,“stack”:“Error\n at couchbase.mutateIn (couchbase.js:133:24)\n at Value.js:26:19\n at Array.forEach ()\n at OnUpdate (value.js:21:13)”}

2024-03-28T15:43:33.697+00:00 [INFO] {“exception”:“{\n "message": {\n "code": 0,\n "desc": "LCB_ERR_KVENGINE_UNKNOWN_ERROR (1040): The server replied with an unrecognized status code. A newer version of this library may be able to decode it",\n "name": "LCB_ERR_KVENGINE_UNKNOWN_ERROR"\n },\n "stack": "Error\n at couchbase.mutateIn (couchbase.js:133:24)\n at Value.js:26:19\n at Array.forEach ()\n at OnUpdate (Value.js:21:13)"\n}”,“file”:“couchbase.js”,“line”:132,“srcLine”:“return couchbase.mutateInInternal(bucket, meta, op_array, options);”,“stack”:“Error\n at couchbase.mutateIn (couchbase.js:133:24)\n at Value.js:26:19\n at Array.forEach ()\n at OnUpdate (Value.js:21:13)”}

2024-03-28T15:43:33.696+00:00 [INFO] “Starting update for thursday,m with value 160.78 using meta info: {"id":"12459862_5953398.1"}”

2024-03-28T15:43:33.696+00:00 [INFO] “Finished update attempt for sun,m using meta info: {"id":"12459862_5953398.1"}”

2024-03-28T15:43:33.694+00:00 [INFO] “Starting update for sun,m with value 140.35 using meta info: {"id":"12459862_5953398.1"}”

2024-03-28T15:43:33.694+00:00 [INFO] “Running OnUpdate for doc ID: 12459862.5953398.1”

I saw that you have since posted and found some xattr mysteriously added to your inputs. I was going to post:

That should be logged as an ERROR.

lcb_STATUS lcb_errmap_default(lcb_INSTANCE *instance, lcb_uint16_t in)
{
    switch (in) {
        case PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET:
            return LCB_ERR_TIMEOUT;
        case PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE:
            return LCB_ERR_AUTH_CONTINUE;
        case PROTOCOL_BINARY_RESPONSE_EBUSY:
        case PROTOCOL_BINARY_RESPONSE_ETMPFAIL:
            return LCB_ERR_TEMPORARY_FAILURE;

        case PROTOCOL_BINARY_RESPONSE_EINTERNAL:
        default:
            if (instance) {
                lcb_log(LOGARGS(instance, ERROR), "Got unhandled memcached error 0x%X", in); 
            } else {
                fprintf(stderr, "COUCHBASE: Unhandled memcached status=0x%x\n", in); 
            }    
            return LCB_ERR_KVENGINE_UNKNOWN_ERROR;
    }    
}
1 Like

Thanks for helping me out. I found out that for some strange reason som values have been updated to “xattrs” in metadata. Now i just have to find out why that is :slight_smile:

To the other part of the code. Is it the best solution regarding upserting a field, to just catch the error and create a new document? Or is it more elegant ways to go about it?

EDIT: And it seems like the issue comes down to the way i try to insert a doc when the doc is missing. If i create it myself, then its no issues.

When the function try to create it i get the same XATTR errors even the doc is not present.

Yes. Which is why I’ve been begging you to print out the arguments before calling the. operation.

You could check if the document exists() to decide to mutateIn or insert.

1 Like

Thanks for the suggestion. I will go about it that way :slight_smile:

When i try to pass the docKey as a string it gives me this error:

{“exception”:“"TypeError: 2nd argument should be object"”,“file”:“couchbase.js”,“line”:125,“srcLine”:“var details = couchbase.bindingDetails(bucket, meta);”,“stack”:“TypeError: 2nd argument should be object\n at couchbase.mutateIn (couchbase.js:126:31)\n at OnUpdate (Odds.js:20:19)”}

And from what I could find it the documentation it seems like the docKey has to be passed as an object.

ok, my fault. I usually work with the java sdk which just takes a string.

Can you show me what the args were to the call that got LCB_ERR_KVENGINE_UNKNOWN_ERROR so I can reproduce this and look with the debugger what the error was?

Yes, of course. Just let me know if I am unclear. But it seems like i figuered out what was the issue for the other error, but not the one you are mentioning.

  1. When you pass this:

if (mutations.length > 0) {
try {
couchbase.mutateIn(dst_bucket, meta.id, mutations.map(mutation => couchbase.MutateInSpec.upsert(mutation.path, mutation.value)));
} catch (error) {
const newDoc = mutations.reduce((acc, mutation) => {
acc[mutation.path] = mutation.value;
return acc;
}, {});
couchbase.insert(dst_bucket, meta.id, newDoc);
}

In this case it will catch the following error if the document do not excist:

Error: {"message":{"code":18,"desc":"LCB_ERR_SUBDOC_XATTR_UNKNOWN_MACRO (324): Subdoc: XATTR unknown macro","name":"LCB_ERR_SUBDOC_XATTR_UNKNOWN_MACRO"},"stack":"Error\n at couchbase.mutateIn (couchbase.js:133:24)\n at OnUpdate (Value.js:15:23)"}"

The reason this was confusing, is that if you get this error on the first document. Then it will continue to produce this error for all the following operations, even they are successfull. If you restart the function the error goes away.

I see you are reffering to this error:

LCB_ERR_KVENGINE_UNKNOWN_ERROR (1040

Unfortunaly I am not sure what the code was at that instance as I have been trying alot. But what I have been doing is mainly trying to catch the error after the MutateIn-operation. So Im been fooling around alot with functions like this:

if (mutations.length > 0) {
couchbase.mutateIn(dst_bucket, meta.id, mutations, (error, result) => {
if (error || !result) {
createDocument(meta, mutations);

I tried to reproduce exactly this error,but with no luck. At some point the XATTR of some of my documents also got altered, and Im also unable to reproduce this, so probably one of the many functions I made that did this.

EDIT: I gone trough the logs and im 99% sure this was the code that produced the LCB_ERR_KVENGINE_UNKNOWN_ERROR. But I am not able to reproduce the error:

results.forEach(result => {
const path = \${result.field}``;
const metaInfo = { id: meta.id };

couchbase.mutateIn(dst_bucket, metaInfo [ 
        couchbase.MutateInSpec.upsert(path, result.value)
    ]);
});

Ok, let me rephrase that. Can you show me the contents of the arguments? Can you log them before the call? What I want to do is make the same call, with the same arguments and using the debugger look what is the error status that the SDK is saying is UNKNOWN. Then I can fix the SDK so that it gives the actual error.

 log('about to call mutateIn : ' + metaObj +'  '+mutateOps); <-- add this line
 const mutateResult = couchbase.mutateIn(dst_bucket, metaObj, mutateOps);
 log('about to call insert : ' + metaObj +'  '+newDoc); <-- add this line
 const insertResult = couchbase.insert(dst_bucket, metaObj, newDoc);

Now I understand! The content of the args have always been the same as this part of the code i have not changed:

[INFO] “about to call mutateIn: {"cas":"1711655939849519104","id":"L12459863_5953385.1","expiration":0,"flags":33554438,"vb":822,"seq":13817,"datatype":"json","keyspace":{"bucket_name":"Value","scope_name":"_default","collection_name":"_default"},"cid":0} [{"op_type":2,"path":"sun,d","value":"111117.55"}]”

[INFO] “about to call mutateIn: {"cas":"1711655927663165440","id":"L12459862_5953398.1","expiration":0,"flags":33554438,"vb":732,"seq":16859,"datatype":"json","keyspace":{"bucket_name":"Value","scope_name":"_default","collection_name":"_default"},"cid":0} [{"op_type":2,"path":"sun,d","value":"11111111111111110000"}]”

I don’t understand how metaObj can be

{"cas":"1711655939849519104","id":"L12459863_5953385.1","expiration":0,"flags":33554438,"vb":822,"seq":13817,"datatype":"json","keyspace":{"bucket_name":"Value","scope_name":"_default","collection_name":"_default"},"cid":0}

When it is created with

const metaObj = { id: meta.id };

Do you mean the syntax of the metaObj or how it gets its value?

I mean that the value that you are printing out :

{"cas":"1711655939849519104","id":"L12459863_5953385.1","expiration":0,"flags":33554438,"vb":822,"seq":13817,"datatype":"json","keyspace":{"bucket_name":"Value","scope_name":"_default","collection_name":"_default"},"cid":0}

does not match with the code you show that creates it

const metaObj = { id: meta.id };

From the code you are showing that creates it, it should only contain {"id":"xyz"}
But what you show is being printed out appears to be { meta } (i.e. all the metatdata from couchbase).

Also - what version of the SDK are you using?

This is how i create the ID:

function OnUpdate(doc, meta) {
log(about to call mutateIn: ${JSON.stringify(meta)} ${JSON.stringify(mutations)});
const mutateResult = couchbase.mutateIn(dst_bucket, { id: meta.id }, mutations);

I pass the ID from docX from collection1 to docY upserting to collection 2. Im using the eventing function in couchbase 7.6.0.

EDIT: For others wanting to replicate the functonality i solved it like this:

const result = couchbase.mutateIn(dst_bucket, { id: meta.id }, mutations.map(mutation => couchbase.MutateInSpec.upsert(mutation.path, mutation.value)));
if (result.error && result.error.key_not_found) {

This will catch the “error” and you can upsert a new doc.

Markus - the code in your first post - is this:

It’s difficult for me to reproduce the UNKNOWN_ERROR, when the code you are posting now does not match what is being logged, and what is being logged now does not match the original code (that was presumably resulting in the UNKNOWN_ERROR).

I understand. Im sorry, but im been trying so many solutions so I have lost of track on what code produced which errors. This is the code that I am 99% sure produced
LCB_ERR_KVENGINE_UNKNOWN_ERROR:

function OnUpdate(doc, meta) {

function get(data) {
    let results = [];

    for (let key in data) {
        if (data.hasOwnProperty(key) && data[key] && typeof data[key] === 'object' && data[key].hasOwnProperty('value') && Array.isArray(data[key].value)) {
            const values = data[key].value.map(valueObj => parseFloat(valueObj.value));
            const highestValue = Math.max(...values);
            results.push({ type: data[key].type, highestValue: highestValue });
        }
    }

    return results;
}

const results = valueAndPrice(doc);

results.forEach(result => {
    const path = `\`${result.type}\``;
    const metaInfo = { id: meta.id }; 

    couchbase.mutateIn(dst_bucket, metaInfo , [ 
        couchbase.MutateInSpec.upsert(path, result.highestValue)
    ]);

});