Skip to content

Commit 2169a30

Browse files
committed
added the ability to skip to a given object when searching the store by class, by reference to an object, etc.
1 parent 5d351cc commit 2169a30

File tree

4 files changed

+84
-6
lines changed

4 files changed

+84
-6
lines changed

src/storage/backends/Backend.ts

+15
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,25 @@ interface Backend {
3232

3333
loadTerminalOpsForMutable(hash: Hash) : Promise<{lastOp: Hash, terminalOps: Array<Hash>} | undefined>;
3434

35+
// The BackendSearchResults struct returned by the following three contains two strings, start & end, that can be used to
36+
// fetch more search results, for example by using the "end" string in params.start in another call to the search function.
37+
38+
// The common usage is then call searchBy___(...) first, using an arbitary size limit, and then repeatedly use the result.end
39+
// to make more calls like searcgBy___(... {start: result.end}) to get all the results in fixed-sized batches.
40+
41+
// These index values are always strings and can be compared lexicographically.
42+
3543
searchByClass(className: string, params? : BackendSearchParams) : Promise<BackendSearchResults>;
3644
searchByReference(referringPath: string, referencedHash: Hash, params? : BackendSearchParams) : Promise<BackendSearchResults>;
3745
searchByReferencingClass(referringClassName: string, referringPath: string, referencedHash: Hash, params? : BackendSearchParams) : Promise<BackendSearchResults>;
3846

47+
// the fowllowing 3 return the "start" parameter for the search functions above (the one that goes into params.start) so that
48+
// the results will fast forward to startObject, skipping all the previous entries
49+
50+
skipToObjectByClass(className: string, startObject: Hash) : Promise<string|undefined>;
51+
skipToObjectByReference(referringPath: string, referencedHash: Hash, startObject: Hash) : Promise<string|undefined>;
52+
skipToObjectByReferencingClass(referringClassName: string, referringPath: string, referencedHash: Hash, startObject: Hash) : Promise<string|undefined>;
53+
3954
close(): void;
4055

4156
setStoredObjectCallback(objectStoreCallback: (literal: Literal) => Promise<void>): void;

src/storage/backends/IdbBackend.ts

+15
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,21 @@ class IdbBackend implements Backend {
414414
async loadLastCheckpoint(): Promise<StateCheckpoint|undefined> {
415415
throw new Error('Method not implemented.');
416416
}
417+
418+
skipToObjectByClass(className: string, startObject: Hash): Promise<string | undefined> {
419+
className; startObject
420+
throw new Error('Method not implemented.');
421+
}
422+
423+
skipToObjectByReference(referringPath: string, referencedHash: string, startObject: Hash): Promise<string | undefined> {
424+
referringPath; referencedHash; startObject;
425+
throw new Error('Method not implemented.');
426+
}
427+
428+
skipToObjectByReferencingClass(referringClassName: string, referringPath: string, referencedHash: string, startObject: Hash): Promise<string | undefined> {
429+
referringClassName; referringPath; referencedHash; startObject;
430+
throw new Error('Method not implemented.');
431+
}
417432
}
418433

419434
Store.registerBackend(IdbBackend.backendName, (dbName: string) => new IdbBackend(dbName));

src/storage/backends/MemoryBackend.ts

+42-6
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,21 @@ class MemoryBackend implements Backend {
212212
return this.searchByIndex(key, this.repr.sortedReferencingClassIndex, params);
213213
}
214214

215+
skipToObjectByClass(className: string, startObject: Hash): Promise<string|undefined> {
216+
return this.skipToObjectByIndex(className, this.repr.sortedClassIndex, startObject);
217+
}
218+
219+
skipToObjectByReference(referringPath: string, referencedHash: string, startObject: Hash): Promise<string|undefined> {
220+
let key = referringPath + '#' + referencedHash;
221+
return this.skipToObjectByIndex(key, this.repr.sortedReferenceIndex, startObject);
222+
}
223+
224+
skipToObjectByReferencingClass(referringClassName: string, referringPath: string, referencedHash: string, startObject: Hash): Promise<string|undefined> {
225+
let key = referringClassName + '.' + referringPath + '#' + referencedHash;
226+
return this.skipToObjectByIndex(key, this.repr.sortedReferencingClassIndex, startObject);
227+
228+
}
229+
215230
async loadOpHeader(opHash: string): Promise<StoredOpHeader | undefined> {
216231
return this.repr.opCausalHistories.get(opHash);
217232
}
@@ -220,32 +235,45 @@ class MemoryBackend implements Backend {
220235
return this.repr.opCausalHistoriesByHash.get(causalHistoryHash);
221236
}
222237

238+
private async skipToObjectByIndex(key: string, sortedIndex: Map<string, Hash[]>, objectHash: Hash): Promise<string|undefined> {
239+
240+
let classHashes = sortedIndex.get(key);
241+
242+
if (classHashes !== undefined) {
243+
let idx = classHashes.indexOf(objectHash);
244+
245+
if (idx >= 0) {
246+
return MemoryBackend.toStringIndex(idx);
247+
}
248+
}
249+
250+
return undefined;
251+
252+
}
253+
223254
private async searchByIndex(key: string, sortedIndex: Map<string, Hash[]>, params?: BackendSearchParams | undefined): Promise<BackendSearchResults> {
224255

225256
let classHashes = sortedIndex.get(key);
226257

227-
228258
if (classHashes === undefined) {
229259
return { items: [], start: '', end: ''}
230260
} else {
231261
let order = (params === undefined || params.order === undefined) ? 'asc' : params.order.toLowerCase();
232262

233263
let segment;
234264

235-
236-
237265
if (order === 'desc') {
238266
classHashes.reverse();
239267
}
240268

241269
let start = 0;
242270

243271
if (params !== undefined && params.start !== undefined) {
244-
start = Number.parseInt(params.start);
272+
start = MemoryBackend.fromStringIndex(params.start);
245273
}
246274

247275
if (start >= classHashes.length) {
248-
return { items: [], start: classHashes.length.toString(), end: classHashes.length.toString()}
276+
return { items: [], start: MemoryBackend.toStringIndex(classHashes.length), end: MemoryBackend.toStringIndex(classHashes.length)}
249277
}
250278

251279
let end = classHashes.length
@@ -256,12 +284,20 @@ class MemoryBackend implements Backend {
256284

257285
let result:Literal[] = segment.map((hash: Hash) => this.repr.objects.get(hash)?.literal as Literal);
258286

259-
return { start: start.toString(), end: end.toString(), items: result };
287+
return { start: MemoryBackend.toStringIndex(start), end: MemoryBackend.toStringIndex(end), items: result };
260288

261289
}
262290

263291
}
264292

293+
private static toStringIndex(idx: number): string {
294+
return idx.toString(16).padStart(16, '0');
295+
}
296+
297+
private static fromStringIndex(idxString: string): number {
298+
return Number.parseInt(idxString, 16);
299+
}
300+
265301
async storeCheckpoint(checkpoint: StateCheckpoint): Promise<void> {
266302
this.repr.checkpoints.set(checkpoint.mutableObject, checkpoint);
267303
}

src/storage/store/Store.ts

+12
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,18 @@ class Store {
610610
return this.loadSearchResults(searchResults, context);
611611
}
612612

613+
async skipToObjectByClass(className: string, object: Hash): Promise<string|undefined> {
614+
return this.backend.skipToObjectByClass(className, object);
615+
}
616+
617+
async skipToObjectByReference(referringPath: string, referencedHash: Hash, object: Hash): Promise <string|undefined> {
618+
return this.backend.skipToObjectByReference(referringPath, referencedHash, object);
619+
}
620+
621+
async skipToObjectByReferencingClass(referringClassName: string, referringPath: string, referencedHash: Hash, object: Hash): Promise<string|undefined> {
622+
return this.backend.skipToObjectByReferencingClass(referringClassName, referringPath, referencedHash, object);
623+
}
624+
613625
async loadOpHeader(opHash: Hash): Promise<OpHeader | undefined> {
614626
const stored = await this.backend.loadOpHeader(opHash);
615627

0 commit comments

Comments
 (0)