josephg / node-foundationdb

Modern Node.js FoundationDB bindings
Other
115 stars 17 forks source link

atomic add, value resets to zero at 255 +1 #47

Closed davidsky closed 3 years ago

davidsky commented 3 years ago

On recent Mac, with latest fdb, client, driver and node 14.15.1.


const FDB = require('foundationdb')
FDB.setAPIVersion(620)
const DB = FDB.open().withValueEncoding(FDB.encoders.int32BE)

;(async () => {

    const promises = []

    const key = Buffer.from('key')

    const writeCount = 255
    for (let i = 0; writeCount > i; i++) {
        promises.push(DB.add(key, 1))
    }

    await Promise.all(promises)
    console.log( await DB.get(key) ) // => 255

    await DB.add(key, 1)
    console.log( await DB.get(key) ) // => 0

})();

Not sure if this is a bug, or am I doing something wrong?

davidsky commented 3 years ago

I was doing something wrong. Atomic operations are using little-endian integers. All works correctly if LE pack/unpack is used.

const FDB = require('foundationdb')
FDB.setAPIVersion(620)

// atomic ops are little-endian encoded
FDB.encoders.int32LE = {
    pack (num) {
        const buf = Buffer.allocUnsafe(4)
        buf.writeInt32LE(num, 0)
        return buf
    },
    unpack (buf) {
        return buf.readInt32LE(0)
    }
}

const DB = FDB.open().withValueEncoding(FDB.encoders.int32LE)

;(async () => {

    const promises = []

    const key = Buffer.from('key')

    const writeCount = 255
    for (let i = 0; writeCount > i; i++) {
        promises.push(DB.add(key, 1))
    }

    await Promise.all(promises)
    console.log( await DB.get(key) ) // => 255

    await DB.add(key, 1)
    console.log( await DB.get(key) ) // => 256

})();

@josephg thank you for this module! Happy holidays! :)

josephg commented 3 years ago

Cool - glad you figured it out! You're welcome :) - happy holidays to you too!

It might be worth explicitly marking that in the docs somewhere!