Hi @Nitesh_Gupta
What version of Couchbase are you running?
Note, this seems to indicate you couldn’t deploy your function i.e. before you execute an UPDATE via N1QL so it is not a N1QL error.
In the future, can you please provide your Eventing Function (an export from the UI is preferrable) alternatively can you direct us to an Enterprise support ticket, i.e. an uploaded cbcollect_info.
One thing that comes to immediately to mind is that Eventing via embedded N1QL will prevent deployment of handler with N1QL writing to the Function source bucket. I assume the eventing Function’s source bucket is “promotions” and you have a statement in it with something like:
UPDATE `promotions` UNSET foo
updated this post on 12/7/2020 (above is wrong if more than one (1) item will update every thing we really want the below)
var key = meta.id;
UPDATE `promotions` USE KEYS $key UNSET foo;
Okay so for Eventing you most likely have something like (I am guessing a bit here and I called my Function 0A_myexample):
// BAD example with inline N1QL will NEVER deploy
// The function name is "0A_myexample"
// The source bucket is "promotions"
function OnUpdate(doc, meta) {
log('docId', meta.id);
// skip if the field foo has already been removed
// IMPORTANT if you use N1QL to avoid infinite recursion.
if (!doc.foo) return;
// must use a var not meta.id as a parameter to inline N1QL
var key = meta.id;
// try to use inline N1QL - this will fail if bucket `promotions`
// is the source bucket.
UPDATE `promotions` USE KEYS $key UNSET foo;
// it will fail to even deploy with an error as follows:
// deploy failed: {"code":51,"info":"Function: 0A_myexample
// N1QL dml to source bucket promotions"}
}
As you can see we get the expected error that you experienced:
deploy failed: {"code":51,"info":"Function: 0A_myexample N1QL dml to source bucket promotions"}
If you need to update the source bucket from within N1QL you will get a recursive mutation as such you have to be VERY VERY careful you could crash your server (as in the Data Nodes) if you don’t suppress recursions in your JavaScript. This is why we prevent such deployments by default.
The good news there is a way to work around this - the below would work for you:
// GOOD (but NOT OPTIMAL) example with the N1QL() function call
// The function name is "0A_myexample"
// The source bucket is "promotions"
// requires an index on bucket "promotions" note I added one as follows:
// CREATE PRIMARY INDEX `#primary_promo` ON `promotions`
function OnUpdate(doc, meta) {
log('docId', meta.id);
// skip if the field foo has already been removed
// IMPORTANT if you use N1QL to avoid infinite recursion.
if (!doc.foo) return;
// try to use the N1QL() function call - this will succeed since
// we don't perform recursion checks - but if we don't have the
// statement "if (!doc.foo) return" as above you will get infinite
// recursion - this would be very very bad.
N1QL("UPDATE `promotions` USE KEYS '"+meta.id+"' UNSET foo");
// The N1QL() function will succeed in deploying and work as
// expected - however it is not optimal as in 10X to 100X slower
// than KV.
}
Now I did say the above is not optimal as in 10X to 100X slower than KV so let’s rewrite it in a pure Eventing KV map mode and skip the N1QL entirely to implement a high performance version of the above without N1QL.
// BEST (OPTIMAL) example with no N1QL and no N1QL() function call
// The function name is "0A_myexample"
// The source bucket is "promotions"
// requires a bucket alias "src_bkt" in read-write mode to bucket 'promotions'
function OnUpdate(doc, meta) {
log('docId', meta.id);
// Optional: the KV map recursion is automatically suppressed internally by
// by Eventing - but having this will be faster as it will avoid unneeded
// writes if the property has already been removed if you undeploy then
// subsequently redeploy "From Everything"
if (!doc.foo) return;
// remove the field
delete doc["foo"]; // or delete doc.foo;
// write the updated doc back to the bucket promotions
src_bkt[meta.id] = doc;
}
Hope the above helps not essentially we have rewritten the example at Function: redactSharedData | Couchbase Docs this function doesn’t remove field but you will get the idea.
Cheers
Jon Strabala