Couchbase returns error on success

I am using couchbase to store user profiles and their balances. As you can see in the code below I’m trying to spam couchbase queries in order to ensure website durability. There is a user in a database with the id ‘u::23’ and its balance is ‘6’. I am expecting the script to deduct the balance as many times as it is positive but problem is that couchbase just returns 3 errors and balance turns from ‘6’ into ‘0’. If I try to remove the interval and just leave the plain function, everything works as expected: the balance turns from ‘6’ into ‘4’. Have you ever experienced the same issue?

Code:

const couchbase = require('couchbase');
const cluster = new couchbase.Cluster('couchbase://localhost');

console.log('Connecting to btc');
let bucket = cluster.openBucket('btc', err => {
    if (err) {
        console.log(err);
    } else {
        console.log('Connected to btc');

        let timer = setInterval(() => {
            bucket.getAndLock('u::23', (err, doc) => {
                if (err) return console.log(err);
                if (doc.value.balance <= 0) {
                    return clearInterval(timer);
                }

                console.log(doc.cas);
                doc.value.balance -= 2;
                bucket.replace('u::23', doc.value, {
                    cas: doc.cas,
                    persist_to: 1
                }, (err, doc) => {
                    if (err) return console.log(err);
                    console.log('----------', 'DONE', '----------');
                });
            });
        }, 90);
    }
});

Output:

Connecting to btc
Connected to btc
CouchbaseCas<1505835358213832704>
CouchbaseCas<1505835358303092736>
{ CouchbaseError
    at _endureError (/var/node/crypto/shared/node_modules/couchbase/lib/bucket.js:1004:19)
    at /var/node/crypto/shared/node_modules/couchbase/lib/bucket.js:1037:18
  message: 'Durability requirements failed',
  code: undefined,
  innerError:
   { CouchbaseError
     message: 'The key already exists in the server. If you have supplied a CAS then the key exists with a CAS value different than specified',
     code: 12 } }
CouchbaseCas<1505835358393335808>
{ CouchbaseError
    at _endureError (/var/node/crypto/shared/node_modules/couchbase/lib/bucket.js:1004:19)
    at /var/node/crypto/shared/node_modules/couchbase/lib/bucket.js:1037:18
  message: 'Durability requirements failed',
  code: undefined,
  innerError:
   { CouchbaseError
     message: 'The key already exists in the server. If you have supplied a CAS then the key exists with a CAS value different than specified',
     code: 12 } }
{ CouchbaseError
    at _endureError (/var/node/crypto/shared/node_modules/couchbase/lib/bucket.js:1004:19)
    at /var/node/crypto/shared/node_modules/couchbase/lib/bucket.js:1037:18
  message: 'Durability requirements failed',
  code: undefined,
  innerError:
   { CouchbaseError
     message: 'The key already exists in the server. If you have supplied a CAS then the key exists with a CAS value different than specified',
     code: 12 } }

Hey @wascript3r,

This appears to be a side-effect of the durability implementation used by Couchbase by default along with your fast update rate. We utilize the CAS to determine whether or not an item has been replicated/persisted to another part of the cluster by default. As you are performing updates at a reasonably high rate, the server is unable to determine that the key was persisted, causing the error you see to occur. One option is to enable mutation tokens (which has a small network cost). Mutation Tokens allow you to track specific mutations at a mutation accurate level and will not exhibit this problem. You can turn this on by passing fetch_mutation_tokens to your connection string:

new couchbase.Cluster('couchbase://1.1.1.1?fetch_mutation_tokens=1');

Cheers, Brett

1 Like

Thank you very much, it solved my problem!