diff --git a/index.js b/index.js index 14340262..0b2d072a 100644 --- a/index.js +++ b/index.js @@ -109,7 +109,10 @@ class TreeNode { c = b4a.compare(key.value, await this.getKey(mid)) if (c === 0) { - if (cas && !(await cas((await this.getKeyNode(mid)).final(encoding), node))) return true + const older = (await this.getKeyNode(mid)).final(encoding) + const swap = cas ? (await cas(older, node)) : null + if (cas && (!swap || swap === older)) return true + this.changed = true this.keys[mid] = key return true @@ -764,7 +767,9 @@ class Batch { c = b4a.compare(target.value, await node.getKey(mid)) if (c === 0) { - if (cas && !(await cas((await node.getKeyNode(mid)).final(encoding), newNode))) return this._unlockMaybe() + const older = (await node.getKeyNode(mid)).final(encoding) + const swap = cas ? (await cas(older, newNode)) : null + if (cas && (!swap || swap === older)) return this._unlockMaybe() node.setKey(mid, target) return this._append(root, seq, key, enc(encoding.value, newNode.value)) diff --git a/test/cas.js b/test/cas.js index 72bdcfc9..992a18f7 100644 --- a/test/cas.js +++ b/test/cas.js @@ -58,6 +58,24 @@ test('cas - should not swap', async function (t) { t.alike(await db.get('/a'), { seq: 1, key: '/a', value: 1 }) }) +test('cas - swap but keep older one', async function (t) { + const db = create({ valueEncoding: 'json' }) + + await db.put('/a', 0) + + t.alike(await db.get('/a'), { seq: 1, key: '/a', value: 0 }) + + await db.put('/a', 99, { + cas: function (prev, next) { + t.alike(prev, { seq: 1, key: '/a', value: 0 }) + t.alike(next, { seq: 2, key: '/a', value: 99 }) + return prev + } + }) + + t.alike(await db.get('/a'), { seq: 1, key: '/a', value: 0 }) +}) + test('cas is called when prev does not exists', async function (t) { t.plan(6)