Skip to content

Commit 6bdda45

Browse files
committed
Fix concurrent addition errors with position
1 parent 7f5786d commit 6bdda45

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

src/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ export const getScalePosition = async ({
3131
const afterPosition = entries[Math.max(position, 0)]?.position;
3232

3333
// Insert to beginning of list if there is no preceding entry
34+
// Note: use Math.random() rather than mean to reduce risk of collisions in concurrent edits
3435
if (beforePosition === undefined)
35-
return afterPosition === undefined ? 0 : afterPosition - 1;
36+
return (afterPosition === undefined ? Math.random() : afterPosition - Math.random());
3637

3738
// Insert to end of list if there is no following entry, or somewhere between adjacent entries
38-
// Note: use Math.random() rather than mean to reduce risk of collisions in concurrent edits
3939
return afterPosition === undefined
40-
? beforePosition + 1
40+
? beforePosition + 1 * Math.random()
4141
: beforePosition + (afterPosition - beforePosition) * Math.random();
4242
};

test/ordered-keyvalue.spec.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { DBElements } from "@/types.js";
88
import { createTestHelia } from "./config.js";
99
import { isBrowser } from "wherearewe";
1010
import { expect } from "aegir/chai";
11+
import { sortPosition } from "./utils.js";
1112

1213
const keysPath = "./testkeys";
1314

@@ -368,6 +369,21 @@ describe("OrderedKeyValue Database", () => {
368369
]);
369370
});
370371

372+
it("synchronous addition", async () => {
373+
await Promise.all(
374+
[...Array(2).keys()].map((i) => db.put(`key${i}`, `value${i}`)),
375+
);
376+
const hash = await db.put("in", "between", 1);
377+
378+
const actual = await db.all();
379+
380+
// Here we only check the middle value, because we don't know if key0 or key1 was
381+
// added first due to the race condition we intentionally introduced above
382+
expect(actual[1]).to.deep.equal(
383+
{ value: "between", key: "in", hash },
384+
);
385+
})
386+
371387
it("returns all values", async () => {
372388
const keyvalue: {
373389
value: DBElements;
@@ -421,7 +437,7 @@ describe("OrderedKeyValue Database", () => {
421437
all.unshift(pair);
422438
}
423439

424-
expect(all).to.deep.equal(keyvalue);
440+
expect(sortPosition(all)).to.deep.equal(sortPosition(keyvalue));
425441
});
426442
});
427443

test/utils.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const sortPosition = <T>(array: (T & { position: number})[]): T[] => {
2+
const sorted = array.toSorted((a, b) => a.position - b.position)
3+
return sorted.map(x=>{
4+
delete (x as T & { position?: number})["position"]
5+
return x
6+
})
7+
}

0 commit comments

Comments
 (0)