Skip to content
This repository was archived by the owner on Oct 25, 2023. It is now read-only.

Commit fd6f178

Browse files
committed
implement iterate
1 parent cd5c704 commit fd6f178

File tree

3 files changed

+96
-34
lines changed

3 files changed

+96
-34
lines changed

archaeologist/src/storage_api_local.ts

Lines changed: 94 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,11 @@ type GenericLav<Kind extends string, Value> = {
6262
}
6363
}
6464

65-
type NidYek = GenericYek<'nid', Nid>
66-
type NidLav = GenericLav<'nid', TNodeJson>
65+
type AllNidsYek = GenericYek<'all-nids', undefined>
66+
type AllNidsLav = GenericLav<'all-nids', Nid[]>
67+
68+
type NidToNodeYek = GenericYek<'nid->node', Nid>
69+
type NidToNodeLav = GenericLav<'nid->node', TNodeJson>
6770

6871
type OriginToNidYek = GenericYek<'origin->nid', OriginId>
6972
type OriginToNidLav = GenericLav<'origin->nid', Nid[]>
@@ -74,28 +77,32 @@ type NidToEdgeLav = GenericLav<'nid->edge', TEdgeJson[]>
7477
type OriginToActivityYek = GenericYek<'origin->activity', OriginId>
7578
type OriginToActivityLav = GenericLav<'origin->activity', TotalUserActivity>
7679

77-
type ExtPipelineYek = GenericYek<'ext-pipe', UserExternalPipelineId>
80+
type ExtPipelineYek = GenericYek<'ext-pipe->progress', UserExternalPipelineId>
7881
type ExtPipelineLav = GenericLav<
79-
'ext-pipe',
82+
'ext-pipe->progress',
8083
Omit<UserExternalPipelineIngestionProgress, 'epid'>
8184
>
8285

8386
type Yek =
84-
| NidYek
87+
| AllNidsYek
88+
| NidToNodeYek
8589
| OriginToNidYek
8690
| NidToEdgeYek
8791
| OriginToActivityYek
8892
| ExtPipelineYek
8993
type Lav =
90-
| NidLav
94+
| AllNidsLav
95+
| NidToNodeLav
9196
| OriginToNidLav
9297
| NidToEdgeLav
9398
| OriginToActivityLav
9499
| ExtPipelineLav
95100

96101
type YekLav = { yek: Yek; lav: Lav }
97102

98-
function isOfArrayKind(lav: Lav): lav is OriginToNidLav | NidToEdgeLav {
103+
function isOfArrayKind(
104+
lav: Lav
105+
): lav is OriginToNidLav | NidToEdgeLav | AllNidsLav {
99106
return Array.isArray(lav.lav.value)
100107
}
101108

@@ -129,10 +136,11 @@ class YekLavStore {
129136
return this.store.set(records)
130137
}
131138

132-
get(yek: NidYek): Promise<NidLav | undefined>
139+
get(yek: AllNidsYek): Promise<AllNidsLav | undefined>
140+
get(yek: NidToNodeYek): Promise<NidToNodeLav | undefined>
133141
get(yek: OriginToNidYek): Promise<OriginToNidLav | undefined>
134142
get(yek: NidToEdgeYek): Promise<NidToEdgeLav | undefined>
135-
get(yek: NidYek[]): Promise<NidLav[]>
143+
get(yek: NidToNodeYek[]): Promise<NidToNodeLav[]>
136144
get(yek: OriginToActivityYek): Promise<OriginToActivityLav | undefined>
137145
get(yek: ExtPipelineYek): Promise<ExtPipelineLav | undefined>
138146
get(yek: Yek): Promise<Lav | undefined>
@@ -163,6 +171,13 @@ class YekLavStore {
163171

164172
// TODO[snikitin@outlook.com] Explain that this method is a poor man's attempt
165173
// to increase atomicity of data insertion
174+
async prepareAppend(
175+
yek: AllNidsYek,
176+
lav: AllNidsLav
177+
): Promise<{
178+
yek: AllNidsYek
179+
lav: AllNidsLav
180+
}>
166181
async prepareAppend(
167182
yek: OriginToNidYek,
168183
lav: OriginToNidLav
@@ -206,15 +221,17 @@ class YekLavStore {
206221

207222
private stringify(yek: Yek): string {
208223
switch (yek.yek.kind) {
209-
case 'nid':
210-
return 'nid:' + yek.yek.key
224+
case 'all-nids':
225+
return 'all-nids'
226+
case 'nid->node':
227+
return 'nid->node:' + yek.yek.key
211228
case 'origin->nid':
212229
return 'origin->nid:' + yek.yek.key.id
213230
case 'nid->edge':
214231
return 'nid->edge:' + yek.yek.key
215232
case 'origin->activity':
216233
return 'origin->activity:' + yek.yek.key.id
217-
case 'ext-pipe':
234+
case 'ext-pipe->progress':
218235
return 'ext-pipe:' + yek.yek.key.pipeline_key
219236
}
220237
}
@@ -264,10 +281,14 @@ async function createNode(
264281
updated_at: createdAt,
265282
}
266283

267-
let records: { yek: Yek; lav: Lav }[] = [
284+
let records: YekLav[] = [
285+
await store.prepareAppend(
286+
{ yek: { kind: 'all-nids', key: undefined } },
287+
{ lav: { kind: 'all-nids', value: [node.nid] } }
288+
),
268289
{
269-
yek: { yek: { kind: 'nid', key: node.nid } },
270-
lav: { lav: { kind: 'nid', value: node } },
290+
yek: { yek: { kind: 'nid->node', key: node.nid } },
291+
lav: { lav: { kind: 'nid->node', value: node } },
271292
},
272293
]
273294

@@ -329,8 +350,8 @@ async function getNode({
329350
store: YekLavStore
330351
nid: Nid
331352
}): Promise<TNode> {
332-
const yek: NidYek = { yek: { kind: 'nid', key: nid } }
333-
const lav: NidLav | undefined = await store.get(yek)
353+
const yek: NidToNodeYek = { yek: { kind: 'nid->node', key: nid } }
354+
const lav: NidToNodeLav | undefined = await store.get(yek)
334355
if (lav == null) {
335356
throw new Error(`Failed to get node ${nid} because it wasn't found`)
336357
}
@@ -351,30 +372,32 @@ async function getNodesByOrigin({
351372
return []
352373
}
353374
const value: Nid[] = lav.lav.value
354-
const nidYeks: NidYek[] = value.map((nid: Nid): NidYek => {
355-
return { yek: { kind: 'nid', key: nid } }
375+
const nidYeks: NidToNodeYek[] = value.map((nid: Nid): NidToNodeYek => {
376+
return { yek: { kind: 'nid->node', key: nid } }
356377
})
357-
const nidLavs: NidLav[] = await store.get(nidYeks)
358-
return nidLavs.map((lav: NidLav) => NodeUtil.fromJson(lav.lav.value))
378+
const nidLavs: NidToNodeLav[] = await store.get(nidYeks)
379+
return nidLavs.map((lav: NidToNodeLav) => NodeUtil.fromJson(lav.lav.value))
359380
}
360381

361382
async function getNodeBatch(
362383
store: YekLavStore,
363384
req: NodeBatchRequestBody
364385
): Promise<NodeBatch> {
365-
const yeks: NidYek[] = req.nids.map((nid: Nid): NidYek => {
366-
return { yek: { kind: 'nid', key: nid } }
386+
const yeks: NidToNodeYek[] = req.nids.map((nid: Nid): NidToNodeYek => {
387+
return { yek: { kind: 'nid->node', key: nid } }
367388
})
368-
const lavs: NidLav[] = await store.get(yeks)
369-
return { nodes: lavs.map((lav: NidLav) => NodeUtil.fromJson(lav.lav.value)) }
389+
const lavs: NidToNodeLav[] = await store.get(yeks)
390+
return {
391+
nodes: lavs.map((lav: NidToNodeLav) => NodeUtil.fromJson(lav.lav.value)),
392+
}
370393
}
371394

372395
async function updateNode(
373396
store: YekLavStore,
374397
args: { nid: Nid } & NodePatchRequest
375398
): Promise<Ack> {
376-
const yek: NidYek = { yek: { kind: 'nid', key: args.nid } }
377-
const lav: NidLav | undefined = await store.get(yek)
399+
const yek: NidToNodeYek = { yek: { kind: 'nid->node', key: args.nid } }
400+
const lav: NidToNodeLav | undefined = await store.get(yek)
378401
if (lav == null) {
379402
throw new Error(`Failed to update node ${args.nid} because it wasn't found`)
380403
}
@@ -389,6 +412,46 @@ async function updateNode(
389412
return { ack: true }
390413
}
391414

415+
class Iterator implements INodeIterator {
416+
private store: YekLavStore
417+
private nids: Promise<Nid[]>
418+
private index: number
419+
420+
constructor(store: YekLavStore) {
421+
this.store = store
422+
this.index = 0
423+
424+
const yek: AllNidsYek = {
425+
yek: { kind: 'all-nids', key: undefined },
426+
}
427+
this.nids = store
428+
.get(yek)
429+
.then((lav: AllNidsLav | undefined) => lav?.lav.value ?? [])
430+
}
431+
432+
async next(): Promise<TNode | null> {
433+
const nids = await this.nids
434+
if (this.index >= nids.length) {
435+
return null
436+
}
437+
const nid: Nid = nids[this.index]
438+
const yek: NidToNodeYek = { yek: { kind: 'nid->node', key: nid } }
439+
const lav: NidToNodeLav | undefined = await this.store.get(yek)
440+
if (lav == null) {
441+
throw new Error(`Failed to find node for nid ${nid}`)
442+
}
443+
++this.index
444+
return NodeUtil.fromJson(lav.lav.value)
445+
}
446+
total(): number {
447+
return this.index
448+
}
449+
abort(): void {
450+
this.index = 0
451+
this.nids = Promise.resolve([])
452+
}
453+
}
454+
392455
async function createEdge(
393456
store: YekLavStore,
394457
args: CreateEdgeArgs
@@ -507,7 +570,7 @@ async function getUserIngestionProgress(
507570
epid: UserExternalPipelineId
508571
): Promise<UserExternalPipelineIngestionProgress> {
509572
const yek: ExtPipelineYek = {
510-
yek: { kind: 'ext-pipe', key: epid },
573+
yek: { kind: 'ext-pipe->progress', key: epid },
511574
}
512575
const lav: ExtPipelineLav | undefined = await store.get(yek)
513576
if (lav == null) {
@@ -533,10 +596,10 @@ async function advanceUserIngestionProgress(
533596
progress.ingested_until = new_progress.ingested_until
534597

535598
const yek: ExtPipelineYek = {
536-
yek: { kind: 'ext-pipe', key: epid },
599+
yek: { kind: 'ext-pipe->progress', key: epid },
537600
}
538601
const lav: ExtPipelineLav = {
539-
lav: { kind: 'ext-pipe', value: progress },
602+
lav: { kind: 'ext-pipe->progress', value: progress },
540603
}
541604
await store.set([{ yek, lav }])
542605
return { ack: true }
@@ -567,7 +630,7 @@ export function makeLocalStorageApi(
567630
) => updateNode(store, args),
568631
create: (args: CreateNodeArgs, _signal?: AbortSignal) =>
569632
createNode(store, args),
570-
iterate: throwUnimplementedError('node.iterate'),
633+
iterate: () => new Iterator(store),
571634
delete: throwUnimplementedError('node.delete'),
572635
bulkDelete: throwUnimplementedError('node.bulkdDelete'),
573636
batch: {

elementary/src/grid/SearchGrid.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@ const SearchGridScroll = ({
150150
setFetching(true)
151151
try {
152152
while (isScrolledToBottom()) {
153-
const node = await iter.next()
153+
const node = await (await iter).next()
154154
if (node == null) {
155-
iter.abort()
155+
;(await iter).abort()
156156
break
157157
}
158158
if (beagle.searchNode(node) != null) {

smuggler-api/src/node_slice_iterator.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type { Optional } from 'armoury'
44
export interface INodeIterator {
55
next: () => Promise<Optional<TNode>>
66
total: () => number
7-
exhausted: () => boolean
87
abort: () => void
98
}
109

0 commit comments

Comments
 (0)