Skip to content

Commit 26e0822

Browse files
committed
Fix move and override
1 parent 34b588d commit 26e0822

File tree

2 files changed

+47
-23
lines changed

2 files changed

+47
-23
lines changed

src/ordered-keyvalue.ts

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,29 @@ export const OrderedKeyValueApi = ({
9595
const put = async (
9696
key: string,
9797
value: DagCborEncodable,
98-
position = -1,
98+
position?: number,
9999
): Promise<string> => {
100100
// Somewhat inefficient, I suppose, but we need to know which entries are already present.
101101
const entries = await itAll(iterator());
102-
const entryValue: { value: DagCborEncodable; position: number } = {
102+
103+
// Avoid overwriting existing position; default to end of list (findIndex gives -1)
104+
let scaledPosition: number | undefined = undefined;
105+
if (position === undefined) {
106+
scaledPosition = entries.find((e) => e.key === key)?.position;
107+
}
108+
if (scaledPosition === undefined) {
109+
scaledPosition = await getScalePosition({
110+
entries,
111+
key,
112+
position: position ?? -1,
113+
});
114+
}
115+
116+
const entryValue = {
103117
value,
104-
position: await getScalePosition({ entries, key, position }),
118+
position: scaledPosition,
105119
};
120+
106121
return database.addOperation({ op: "PUT", key, value: entryValue });
107122
};
108123

@@ -143,30 +158,33 @@ export const OrderedKeyValueApi = ({
143158
unknown
144159
> {
145160
let count = 0;
146-
const keys: { [key: string]: true } = {};
147-
const positions: { [key: string]: number } = {};
161+
162+
// `true` indicates a `PUT` operation; `number` indicates a `MOVE` operation
163+
const keys: { [key: string]: true | number } = {};
148164

149165
for await (const entry of database.log.traverse()) {
150166
const { op, key, value } = entry.payload;
167+
if (typeof key !== "string") continue;
151168

152-
if (!key || keys[key]) continue;
153-
154-
if (op === "PUT") {
169+
if (op === "PUT" && keys[key] !== true) {
155170
const hash = entry.hash;
156-
const putValue = value as { value: unknown; position?: number };
171+
const putValue = value as { value: unknown; position: number };
157172

173+
const position =
174+
typeof keys[key] === "number"
175+
? (keys[key] as number)
176+
: putValue.position;
158177
keys[key] = true;
159178
count++;
160179

161180
yield {
162181
key,
163182
value: putValue.value,
164-
position: positions[key] ?? putValue.position ?? -1,
183+
position,
165184
hash,
166185
};
167-
} else if (op === "MOVE") {
168-
if (positions[key] !== undefined || keys[key]) continue;
169-
positions[key] = value as number;
186+
} else if (op === "MOVE" && !keys[key]) {
187+
keys[key] = value as number;
170188
} else if (op === "DEL") {
171189
keys[key] = true;
172190
}

test/ordered-keyvalue.spec.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ describe("OrderedKeyValue Database", () => {
227227
const hash = await db.put(key, value);
228228
const hash2 = await db.put(key2, value2);
229229
await db.move(key, 1);
230+
230231
const actual = await db.all();
231232

232233
expect(actual).to.deep.equal([
@@ -309,24 +310,29 @@ describe("OrderedKeyValue Database", () => {
309310
});
310311

311312
it("move and override a key concurrently", async () => {
312-
const value = "value1";
313-
const valueMod = "value1a";
314-
const key = "key1";
313+
const key1 = "key1";
314+
const value1 = "value1";
315315

316-
const value2 = "value2";
317316
const key2 = "key2";
317+
const value2 = "value2";
318+
const value2Mod = "value2a";
318319

319-
await db.put(key, value);
320-
const hash2 = await db.put(key2, value2);
321-
await db.move(key, 1);
320+
const key3 = "key3";
321+
const value3 = "value3";
322322

323-
const hash = await db.put(key, valueMod);
323+
const hash1 = await db.put(key1, value1);
324+
await db.put(key2, value2);
325+
const hash3 = await db.put(key3, value3);
326+
await db.move(key1, 1);
327+
328+
const hash2 = await db.put(key2, value2Mod);
324329

325330
const actual = await db.all();
326331

327332
expect(actual).to.deep.equal([
328-
{ value: value2, key: key2, hash: hash2 },
329-
{ value: valueMod, key, hash },
333+
{ value: value2Mod, key: key2, hash: hash2 },
334+
{ value: value1, key: key1, hash: hash1 },
335+
{ value: value3, key: key3, hash: hash3 },
330336
]);
331337
});
332338

0 commit comments

Comments
 (0)