fix findExistingKeys too many (existing but not requested) keys

This commit is contained in:
Bruno Windels 2021-09-27 16:27:52 +02:00
parent cc0b938a6d
commit f55f450850
2 changed files with 87 additions and 8 deletions

View file

@ -160,20 +160,35 @@ export class QueryTarget<T> {
/** /**
* Checks if a given set of keys exist. * Checks if a given set of keys exist.
* Calls `callback(key, found)` for each key in `keys`, in key sorting order (or reversed if backwards=true).
* If the callback returns true, the search is halted and callback won't be called again. * If the callback returns true, the search is halted and callback won't be called again.
* `callback` is called with the same instances of the key as given in `keys`, so direct comparison can be used.
*/ */
async findExistingKeys(keys: IDBValidKey[], backwards: boolean, callback: (key: IDBValidKey, pk: IDBValidKey) => boolean): Promise<void> { async findExistingKeys(keys: IDBValidKey[], backwards: boolean, callback: (key: IDBValidKey, pk: IDBValidKey) => boolean): Promise<void> {
const compareKeys = (a, b) => backwards ? -this.idbFactory.cmp(a, b) : this.idbFactory.cmp(a, b);
const sortedKeys = keys.slice().sort(compareKeys);
const firstKey = sortedKeys[0];
const lastKey = sortedKeys[sortedKeys.length - 1];
console.log(firstKey, lastKey, sortedKeys);
const direction = backwards ? "prev" : "next"; const direction = backwards ? "prev" : "next";
const sortedKeys = keys.slice().sort((a, b) => backwards ? -this.idbFactory.cmp(a, b) : this.idbFactory.cmp(a, b));
const firstKey = backwards ? sortedKeys[sortedKeys.length - 1] : sortedKeys[0];
const lastKey = backwards ? sortedKeys[0] : sortedKeys[sortedKeys.length - 1];
const cursor = this._target.openKeyCursor(this.IDBKeyRange.bound(firstKey, lastKey), direction); const cursor = this._target.openKeyCursor(this.IDBKeyRange.bound(firstKey, lastKey), direction);
let index = 0;
await iterateCursor(cursor, (value, key, cursor) => { await iterateCursor(cursor, (value, key, cursor) => {
while (index < sortedKeys.length && compareKeys(sortedKeys[index], key) < 0) {
index += 1;
}
let done = false;
if (sortedKeys[index] === key) {
const pk = cursor.primaryKey; const pk = cursor.primaryKey;
const done = callback(key, pk); done = callback(key, pk);
return done ? DONE : NOT_DONE; index += 1;
}
if (done || index >= sortedKeys.length) {
return DONE;
} else {
return {
done: false,
jumpTo: sortedKeys[index],
}
}
}); });
} }

View file

@ -316,3 +316,67 @@ export class TimelineEventStore {
this._timelineStore.delete(range); this._timelineStore.delete(range);
} }
} }
import {createMockStorage} from "../../../../mocks/Storage.js";
import {createEvent, withTextBody} from "../../../../mocks/event.js";
import {createEventEntry} from "../../../room/timeline/persistence/common.js";
export function tests() {
const sortedIds = [
"$2wZy1W-QdcwaAwz68nfz1oc-3SsZKVDy8d86ERP1Pm0",
"$4RWaZ5142grUgTnQyr_5qiPTOwzAOimt5MsXg6m1diM",
"$4izqHE2Wf5US_-e_za942pZ10CDNJjDncUMmhqBUVQw",
"$Oil2Afq2cBLqMAeJTAHjA3Is9T5Wmaa2ogVRlFJ_gzE",
"$Wyl-7u-YqnPJElkPufIRXRFTYP-eFxQ4iD-SmLQo2Rw",
"$b-eWaZtp22vL9mp0h7odbpphOZQ-rnp54qjyTQPARgo",
"$sS9rTv8u2m9o4RaMI2jGOnpMtb9t8_0euiQLhNFW380",
"$uZLkB9rzTKvJAK2QrQNX-prwQ2Niajdi0fvvRnyCtz8",
"$vGecIBZFex9_vlQf1E1LjtQXE3q5GwERIHMiy4mOWv0",
"$vdLgAnwjHj0cicU3MA4ynLHUBGOIFhvvksY3loqzjF",
];
const insertedIds = [
sortedIds[5],
sortedIds[3],
sortedIds[9],
sortedIds[7],
sortedIds[1],
];
const checkedIds = [
sortedIds[2],
sortedIds[4],
sortedIds[3],
sortedIds[0],
sortedIds[8],
sortedIds[9],
sortedIds[6],
];
const roomId = "!fjsdf423423jksdfdsf:hs.tld";
function createEventWithId(id) {
return withTextBody("hello", createEvent("m.room.message", id, "@alice:hs.tld"));
}
return {
"getEventKeysForIds": async assert => {
const storage = await createMockStorage();
const txn = await storage.readWriteTxn([storage.storeNames.timelineEvents]);
let eventKey = EventKey.defaultLiveKey;
for (const insertedId of insertedIds) {
assert(await txn.timelineEvents.tryInsert(createEventEntry(eventKey.nextKey(), roomId, createEventWithId(insertedId))));
eventKey = eventKey.nextKey();
}
const eventKeyMap = await txn.timelineEvents.getEventKeysForIds(roomId, checkedIds);
assert.equal(eventKeyMap.size, 2);
const eventKey1 = eventKeyMap.get("$Oil2Afq2cBLqMAeJTAHjA3Is9T5Wmaa2ogVRlFJ_gzE");
assert.equal(eventKey1.fragmentId, 0);
assert.equal(eventKey1.eventIndex, 80000001);
const eventKey2 = eventKeyMap.get("$vdLgAnwjHj0cicU3MA4ynLHUBGOIFhvvksY3loqzjF");
assert.equal(eventKey2.fragmentId, 0);
assert.equal(eventKey2.eventIndex, 80000002);
}
}
}