@speckle/objectloader2 2.25.4 → 2.25.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commonjs/helpers/cachePump.d.ts +1 -0
- package/dist/commonjs/helpers/cachePump.d.ts.map +1 -1
- package/dist/commonjs/helpers/cachePump.js +7 -1
- package/dist/commonjs/helpers/cachePump.js.map +1 -1
- package/dist/commonjs/helpers/defermentManager.d.ts +2 -0
- package/dist/commonjs/helpers/defermentManager.d.ts.map +1 -1
- package/dist/commonjs/helpers/defermentManager.js +20 -1
- package/dist/commonjs/helpers/defermentManager.js.map +1 -1
- package/dist/commonjs/index.d.ts +0 -1
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +1 -3
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/operations/databases/indexedDatabase.d.ts +6 -4
- package/dist/commonjs/operations/databases/indexedDatabase.d.ts.map +1 -1
- package/dist/commonjs/operations/databases/indexedDatabase.js +2 -21
- package/dist/commonjs/operations/databases/indexedDatabase.js.map +1 -1
- package/dist/commonjs/operations/databases/memoryDatabase.d.ts +0 -3
- package/dist/commonjs/operations/databases/memoryDatabase.d.ts.map +1 -1
- package/dist/commonjs/operations/databases/memoryDatabase.js +0 -7
- package/dist/commonjs/operations/databases/memoryDatabase.js.map +1 -1
- package/dist/commonjs/operations/downloaders/memoryDownloader.js +1 -1
- package/dist/commonjs/operations/downloaders/memoryDownloader.js.map +1 -1
- package/dist/commonjs/operations/downloaders/serverDownloader.js +1 -1
- package/dist/commonjs/operations/interfaces.d.ts +0 -3
- package/dist/commonjs/operations/interfaces.d.ts.map +1 -1
- package/dist/commonjs/operations/objectLoader2.d.ts.map +1 -1
- package/dist/commonjs/operations/objectLoader2.js +10 -4
- package/dist/commonjs/operations/objectLoader2.js.map +1 -1
- package/dist/commonjs/operations/objectLoader2Factory.d.ts +11 -7
- package/dist/commonjs/operations/objectLoader2Factory.d.ts.map +1 -1
- package/dist/commonjs/operations/objectLoader2Factory.js +33 -15
- package/dist/commonjs/operations/objectLoader2Factory.js.map +1 -1
- package/dist/esm/helpers/cachePump.d.ts +1 -0
- package/dist/esm/helpers/cachePump.d.ts.map +1 -1
- package/dist/esm/helpers/cachePump.js +7 -1
- package/dist/esm/helpers/cachePump.js.map +1 -1
- package/dist/esm/helpers/defermentManager.d.ts +2 -0
- package/dist/esm/helpers/defermentManager.d.ts.map +1 -1
- package/dist/esm/helpers/defermentManager.js +20 -1
- package/dist/esm/helpers/defermentManager.js.map +1 -1
- package/dist/esm/index.d.ts +0 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +0 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/operations/databases/indexedDatabase.d.ts +6 -4
- package/dist/esm/operations/databases/indexedDatabase.d.ts.map +1 -1
- package/dist/esm/operations/databases/indexedDatabase.js +1 -22
- package/dist/esm/operations/databases/indexedDatabase.js.map +1 -1
- package/dist/esm/operations/databases/memoryDatabase.d.ts +0 -3
- package/dist/esm/operations/databases/memoryDatabase.d.ts.map +1 -1
- package/dist/esm/operations/databases/memoryDatabase.js +0 -7
- package/dist/esm/operations/databases/memoryDatabase.js.map +1 -1
- package/dist/esm/operations/downloaders/memoryDownloader.js +1 -1
- package/dist/esm/operations/downloaders/memoryDownloader.js.map +1 -1
- package/dist/esm/operations/downloaders/serverDownloader.js +1 -1
- package/dist/esm/operations/interfaces.d.ts +0 -3
- package/dist/esm/operations/interfaces.d.ts.map +1 -1
- package/dist/esm/operations/objectLoader2.d.ts.map +1 -1
- package/dist/esm/operations/objectLoader2.js +10 -4
- package/dist/esm/operations/objectLoader2.js.map +1 -1
- package/dist/esm/operations/objectLoader2Factory.d.ts +11 -7
- package/dist/esm/operations/objectLoader2Factory.d.ts.map +1 -1
- package/dist/esm/operations/objectLoader2Factory.js +33 -15
- package/dist/esm/operations/objectLoader2Factory.js.map +1 -1
- package/package.json +2 -2
- package/src/helpers/cachePump.disposal.spec.ts +3 -1
- package/src/helpers/cachePump.spec.ts +2 -1
- package/src/helpers/cachePump.ts +9 -1
- package/src/helpers/defermentManager.defermentTotals.spec.ts +53 -0
- package/src/helpers/defermentManager.ts +20 -1
- package/src/index.ts +0 -1
- package/src/operations/databases/__snapshots__/indexedDatabase.spec.ts.snap +13 -26
- package/src/operations/databases/indexedDatabase.spec.ts +23 -27
- package/src/operations/databases/indexedDatabase.ts +1 -25
- package/src/operations/databases/memoryDatabase.spec.ts +48 -0
- package/src/operations/databases/memoryDatabase.ts +0 -8
- package/src/operations/downloaders/__snapshots__/memoryDownloader.spec.ts.snap +12 -0
- package/src/operations/downloaders/memoryDownloader.spec.ts +49 -0
- package/src/operations/downloaders/memoryDownloader.ts +1 -1
- package/src/operations/downloaders/serverDownloader.ts +1 -1
- package/src/operations/interfaces.ts +0 -1
- package/src/operations/objectLoader2.ts +12 -4
- package/src/operations/objectLoader2Factory.ts +40 -18
- package/src/test/e2e.spec.ts +4 -2
|
@@ -8,6 +8,9 @@ export class DefermentManager {
|
|
|
8
8
|
private logger: CustomLogger
|
|
9
9
|
private currentSize = 0
|
|
10
10
|
private disposed = false
|
|
11
|
+
//tracks total deferment requests for each id
|
|
12
|
+
//this is used to prevent cleaning up deferments that are still being requested
|
|
13
|
+
private totalDefermentRequests: Map<string, number> = new Map()
|
|
11
14
|
|
|
12
15
|
constructor(private options: DefermentManagerOptions) {
|
|
13
16
|
this.resetGlobalTimer()
|
|
@@ -29,6 +32,7 @@ export class DefermentManager {
|
|
|
29
32
|
|
|
30
33
|
async defer(params: { id: string }): Promise<Base> {
|
|
31
34
|
if (this.disposed) throw new Error('DefermentManager is disposed')
|
|
35
|
+
this.trackDefermentRequest(params.id)
|
|
32
36
|
const now = this.now()
|
|
33
37
|
const deferredBase = this.deferments.get(params.id)
|
|
34
38
|
if (deferredBase) {
|
|
@@ -44,6 +48,15 @@ export class DefermentManager {
|
|
|
44
48
|
return notYetFound.getPromise()
|
|
45
49
|
}
|
|
46
50
|
|
|
51
|
+
private trackDefermentRequest(id: string): void {
|
|
52
|
+
const request = this.totalDefermentRequests.get(id)
|
|
53
|
+
if (request) {
|
|
54
|
+
this.totalDefermentRequests.set(id, request + 1)
|
|
55
|
+
} else {
|
|
56
|
+
this.totalDefermentRequests.set(id, 1)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
47
60
|
undefer(item: Item): void {
|
|
48
61
|
if (this.disposed) throw new Error('DefermentManager is disposed')
|
|
49
62
|
const now = this.now()
|
|
@@ -108,6 +121,12 @@ export class DefermentManager {
|
|
|
108
121
|
.filter((x) => x.isExpired(now))
|
|
109
122
|
.sort((a, b) => this.compareMaybeBasesBySize(a.getItem(), b.getItem()))) {
|
|
110
123
|
if (deferredBase.done(now)) {
|
|
124
|
+
//if the deferment is done but has been requested multiple times,
|
|
125
|
+
//we do not clean it up to allow the requests to resolve
|
|
126
|
+
const requestCount = this.totalDefermentRequests.get(deferredBase.getId())
|
|
127
|
+
if (requestCount && requestCount > 1) {
|
|
128
|
+
return
|
|
129
|
+
}
|
|
111
130
|
this.currentSize -= deferredBase.getItem()?.size || 0
|
|
112
131
|
this.deferments.delete(deferredBase.getId())
|
|
113
132
|
cleaned++
|
|
@@ -117,7 +136,7 @@ export class DefermentManager {
|
|
|
117
136
|
}
|
|
118
137
|
}
|
|
119
138
|
this.logger(
|
|
120
|
-
'cleaned deferments
|
|
139
|
+
'cleaned deferments: cleaned, left, time',
|
|
121
140
|
cleaned,
|
|
122
141
|
this.deferments.size,
|
|
123
142
|
performance.now() - start
|
package/src/index.ts
CHANGED
|
@@ -1,31 +1,18 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
|
-
exports[`
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
"
|
|
3
|
+
exports[`IndexedDatabase > should add and get multiple items 1`] = `
|
|
4
|
+
[
|
|
5
|
+
{
|
|
6
|
+
"baseId": "id1",
|
|
7
|
+
"item": {
|
|
8
|
+
"foo": "bar",
|
|
9
|
+
},
|
|
8
10
|
},
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
{
|
|
15
|
-
"base": {
|
|
16
|
-
"id": "id",
|
|
17
|
-
"speckle_type": "type",
|
|
18
|
-
},
|
|
19
|
-
"baseId": "id1",
|
|
20
|
-
}
|
|
21
|
-
`;
|
|
22
|
-
|
|
23
|
-
exports[`database cache > write two items to queue use getItem 2`] = `
|
|
24
|
-
{
|
|
25
|
-
"base": {
|
|
26
|
-
"id": "id",
|
|
27
|
-
"speckle_type": "type",
|
|
11
|
+
{
|
|
12
|
+
"baseId": "id2",
|
|
13
|
+
"item": {
|
|
14
|
+
"foo": "bar",
|
|
15
|
+
},
|
|
28
16
|
},
|
|
29
|
-
|
|
30
|
-
}
|
|
17
|
+
]
|
|
31
18
|
`;
|
|
@@ -1,37 +1,33 @@
|
|
|
1
|
-
import { describe, expect,
|
|
2
|
-
import IndexedDatabase from './indexedDatabase.js'
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
|
3
2
|
import { IDBFactory, IDBKeyRange } from 'fake-indexeddb'
|
|
3
|
+
import IndexedDatabase, { IndexedDatabaseOptions } from './indexedDatabase.js'
|
|
4
4
|
import { Item } from '../../types/types.js'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const i: Item = { baseId: 'id', base: { id: 'id', speckle_type: 'type' } }
|
|
9
|
-
const database = new IndexedDatabase({
|
|
10
|
-
indexedDB: new IDBFactory(),
|
|
11
|
-
keyRange: IDBKeyRange
|
|
12
|
-
})
|
|
13
|
-
await database.add(i)
|
|
14
|
-
await database.disposeAsync()
|
|
6
|
+
// Mock Item
|
|
7
|
+
const defaultItem = (id: string): Item => ({ baseId: id, item: { foo: 'bar' } })
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
describe('IndexedDatabase', () => {
|
|
10
|
+
let db: IndexedDatabase
|
|
11
|
+
let options: IndexedDatabaseOptions
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
options = { indexedDB: new IDBFactory(), keyRange: IDBKeyRange }
|
|
15
|
+
db = new IndexedDatabase(options)
|
|
18
16
|
})
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const database = new IndexedDatabase({
|
|
24
|
-
indexedDB: new IDBFactory(),
|
|
25
|
-
keyRange: IDBKeyRange
|
|
26
|
-
})
|
|
27
|
-
await database.add(i1)
|
|
28
|
-
await database.add(i2)
|
|
29
|
-
await database.disposeAsync()
|
|
18
|
+
afterEach(async () => {
|
|
19
|
+
await db.disposeAsync()
|
|
20
|
+
})
|
|
30
21
|
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
it('should add and get multiple items', async () => {
|
|
23
|
+
const items = [defaultItem('id1'), defaultItem('id2')]
|
|
24
|
+
await db.cacheSaveBatch({ batch: items })
|
|
25
|
+
const result = await db.getAll(['id1', 'id2'])
|
|
26
|
+
expect(result).toMatchSnapshot()
|
|
27
|
+
expect(result).toEqual(items)
|
|
28
|
+
})
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
expect(
|
|
30
|
+
it('should dispose without error', async () => {
|
|
31
|
+
await expect(db.disposeAsync()).resolves.not.toThrow()
|
|
36
32
|
})
|
|
37
33
|
})
|
|
@@ -5,7 +5,7 @@ import { isSafari } from '@speckle/shared'
|
|
|
5
5
|
import { Dexie, DexieOptions, Table } from 'dexie'
|
|
6
6
|
import { Database } from '../interfaces.js'
|
|
7
7
|
|
|
8
|
-
class ObjectStore extends Dexie {
|
|
8
|
+
export class ObjectStore extends Dexie {
|
|
9
9
|
static #databaseName: string = 'speckle-cache'
|
|
10
10
|
objects!: Table<Item, string> // Table type: <entity, primaryKey>
|
|
11
11
|
|
|
@@ -83,30 +83,6 @@ export default class IndexedDatabase implements Database {
|
|
|
83
83
|
this.#cacheDB = await this.#openDatabase()
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
//this is for testing only - in the real world we will not use this
|
|
87
|
-
async add(item: Item): Promise<void> {
|
|
88
|
-
await this.#setupCacheDb()
|
|
89
|
-
await this.#cacheDB!.transaction('rw', this.#cacheDB!.objects, async () => {
|
|
90
|
-
return await this.#cacheDB?.objects.add(item)
|
|
91
|
-
})
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async getItem(params: { id: string }): Promise<Item | undefined> {
|
|
95
|
-
const { id } = params
|
|
96
|
-
await this.#setupCacheDb()
|
|
97
|
-
//might not be in the real DB yet, so check the write queue first
|
|
98
|
-
if (this.#writeQueue) {
|
|
99
|
-
const item = this.#writeQueue.get(id)
|
|
100
|
-
if (item) {
|
|
101
|
-
return item
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return this.#cacheDB!.transaction('r', this.#cacheDB!.objects, async () => {
|
|
106
|
-
return await this.#cacheDB?.objects.get(id)
|
|
107
|
-
})
|
|
108
|
-
}
|
|
109
|
-
|
|
110
86
|
async cacheSaveBatch(params: { batch: Item[] }): Promise<void> {
|
|
111
87
|
await this.#setupCacheDb()
|
|
112
88
|
const { batch } = params
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest'
|
|
2
|
+
import { MemoryDatabase } from './memoryDatabase.js'
|
|
3
|
+
import { Base, Item } from '../../types/types.js'
|
|
4
|
+
|
|
5
|
+
const makeItem = (id: string, foo = 'bar'): Item => ({
|
|
6
|
+
baseId: id,
|
|
7
|
+
base: { foo } as unknown as Base
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
describe('MemoryDatabase', () => {
|
|
11
|
+
let db: MemoryDatabase
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
db = new MemoryDatabase()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('should return undefined for missing keys', async () => {
|
|
18
|
+
const result = await db.getAll(['missing'])
|
|
19
|
+
expect(result).toEqual([undefined])
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('should add and retrieve a single item', async () => {
|
|
23
|
+
const item = makeItem('id1')
|
|
24
|
+
await db.cacheSaveBatch({ batch: [item] })
|
|
25
|
+
const result = await db.getAll(['id1'])
|
|
26
|
+
expect(result).toEqual([item])
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should add and retrieve multiple items', async () => {
|
|
30
|
+
const items = [makeItem('id1'), makeItem('id2', 'baz')]
|
|
31
|
+
await db.cacheSaveBatch({ batch: items })
|
|
32
|
+
const result = await db.getAll(['id1', 'id2'])
|
|
33
|
+
expect(result).toEqual(items)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('should overwrite items with the same key', async () => {
|
|
37
|
+
const item1 = makeItem('id1', 'foo')
|
|
38
|
+
const item2 = makeItem('id1', 'bar')
|
|
39
|
+
await db.cacheSaveBatch({ batch: [item1] })
|
|
40
|
+
await db.cacheSaveBatch({ batch: [item2] })
|
|
41
|
+
const result = await db.getAll(['id1'])
|
|
42
|
+
expect(result).toEqual([item2])
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('disposeAsync should resolve', async () => {
|
|
46
|
+
await expect(db.disposeAsync()).resolves.not.toThrow()
|
|
47
|
+
})
|
|
48
|
+
})
|
|
@@ -29,14 +29,6 @@ export class MemoryDatabase implements Database {
|
|
|
29
29
|
return Promise.resolve()
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
getItem(params: { id: string }): Promise<Item | undefined> {
|
|
33
|
-
const item = this.items.get(params.id)
|
|
34
|
-
if (item) {
|
|
35
|
-
return Promise.resolve({ baseId: params.id, base: item })
|
|
36
|
-
}
|
|
37
|
-
return Promise.resolve(undefined)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
32
|
disposeAsync(): Promise<void> {
|
|
41
33
|
return Promise.resolve()
|
|
42
34
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest'
|
|
2
|
+
import { MemoryDownloader } from './memoryDownloader.js'
|
|
3
|
+
import { Base, Item } from '../../types/types.js'
|
|
4
|
+
import Queue from '../../helpers/queue.js'
|
|
5
|
+
import BufferQueue from '../../helpers/bufferQueue.js'
|
|
6
|
+
|
|
7
|
+
const makeBase = (foo: string): Base => ({ foo } as unknown as Base)
|
|
8
|
+
|
|
9
|
+
describe('MemoryDownloader', () => {
|
|
10
|
+
let items: Map<string, Base>
|
|
11
|
+
let downloader: MemoryDownloader
|
|
12
|
+
let results: Queue<Item>
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
items = new Map([
|
|
16
|
+
['id1', makeBase('foo')],
|
|
17
|
+
['id2', makeBase('bar')]
|
|
18
|
+
])
|
|
19
|
+
downloader = new MemoryDownloader('id1', items)
|
|
20
|
+
results = new BufferQueue<Item>()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('should download the root item', async () => {
|
|
24
|
+
const item = await downloader.downloadSingle()
|
|
25
|
+
expect(item).toEqual({ baseId: 'id1', base: { foo: 'foo' } })
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('should throw if root item is missing', async () => {
|
|
29
|
+
const missingDownloader = new MemoryDownloader('missing', items)
|
|
30
|
+
await expect(missingDownloader.downloadSingle()).rejects.toThrow(
|
|
31
|
+
'Method not implemented.'
|
|
32
|
+
)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('should add found item to results queue', () => {
|
|
36
|
+
downloader.initializePool({ results, total: 2 })
|
|
37
|
+
downloader.add('id2')
|
|
38
|
+
expect(items).toMatchSnapshot()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should throw if added item is missing', () => {
|
|
42
|
+
downloader.initializePool({ results, total: 2 })
|
|
43
|
+
expect(() => downloader.add('missing')).toThrow()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('disposeAsync should resolve', async () => {
|
|
47
|
+
await expect(downloader.disposeAsync()).resolves.not.toThrow()
|
|
48
|
+
})
|
|
49
|
+
})
|
|
@@ -23,7 +23,7 @@ export class MemoryDownloader implements Downloader {
|
|
|
23
23
|
if (root) {
|
|
24
24
|
return Promise.resolve({ baseId: this.#rootId, base: root })
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
return Promise.reject(new Error('Method not implemented.'))
|
|
27
27
|
}
|
|
28
28
|
disposeAsync(): Promise<void> {
|
|
29
29
|
return Promise.resolve()
|
|
@@ -13,7 +13,6 @@ export interface Downloader extends Queue<string> {
|
|
|
13
13
|
|
|
14
14
|
export interface Database {
|
|
15
15
|
getAll(keys: string[]): Promise<(Item | undefined)[]>
|
|
16
|
-
getItem(params: { id: string }): Promise<Item | undefined>
|
|
17
16
|
cacheSaveBatch(params: { batch: Item[] }): Promise<void>
|
|
18
17
|
disposeAsync(): Promise<void>
|
|
19
18
|
}
|
|
@@ -41,7 +41,7 @@ export class ObjectLoader2 {
|
|
|
41
41
|
this.#database = options.database
|
|
42
42
|
this.#deferments = new DefermentManager({
|
|
43
43
|
maxSizeInMb: 2_000, // 2 GBs
|
|
44
|
-
ttlms:
|
|
44
|
+
ttlms: 15_000, // 15 seconds
|
|
45
45
|
logger: this.#logger
|
|
46
46
|
})
|
|
47
47
|
this.#cache = new CacheReader(this.#database, this.#deferments, cacheOptions)
|
|
@@ -55,13 +55,17 @@ export class ObjectLoader2 {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
async disposeAsync(): Promise<void> {
|
|
58
|
-
await Promise.all([
|
|
58
|
+
await Promise.all([
|
|
59
|
+
this.#downloader.disposeAsync(),
|
|
60
|
+
this.#cache.disposeAsync(),
|
|
61
|
+
this.#pump.disposeAsync()
|
|
62
|
+
])
|
|
59
63
|
this.#deferments.dispose()
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
async getRootObject(): Promise<Item | undefined> {
|
|
63
67
|
if (!this.#root) {
|
|
64
|
-
this.#root = await this.#database.
|
|
68
|
+
this.#root = (await this.#database.getAll([this.#rootId]))[0]
|
|
65
69
|
if (!this.#root) {
|
|
66
70
|
this.#root = await this.#downloader.downloadSingle()
|
|
67
71
|
}
|
|
@@ -90,7 +94,11 @@ export class ObjectLoader2 {
|
|
|
90
94
|
yield rootItem.base
|
|
91
95
|
if (!rootItem.base.__closure) return
|
|
92
96
|
|
|
93
|
-
|
|
97
|
+
//sort the closures by their values descending
|
|
98
|
+
const sortedClosures = Object.entries(rootItem.base.__closure).sort(
|
|
99
|
+
(a, b) => b[1] - a[1]
|
|
100
|
+
)
|
|
101
|
+
const children = sortedClosures.map((x) => x[0])
|
|
94
102
|
const total = children.length
|
|
95
103
|
this.#downloader.initializePool({
|
|
96
104
|
results: new AggregateQueue(this.#gathered, this.#pump),
|
|
@@ -5,6 +5,14 @@ import { MemoryDownloader } from './downloaders/memoryDownloader.js'
|
|
|
5
5
|
import ServerDownloader from './downloaders/serverDownloader.js'
|
|
6
6
|
import { ObjectLoader2 } from './objectLoader2.js'
|
|
7
7
|
|
|
8
|
+
export interface ObjectLoader2FactoryOptions {
|
|
9
|
+
useMemoryCache?: boolean
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
11
|
+
keyRange?: { bound: Function; lowerBound: Function; upperBound: Function }
|
|
12
|
+
indexedDB?: IDBFactory
|
|
13
|
+
logger?: CustomLogger
|
|
14
|
+
}
|
|
15
|
+
|
|
8
16
|
export class ObjectLoader2Factory {
|
|
9
17
|
static createFromObjects(objects: Base[]): ObjectLoader2 {
|
|
10
18
|
const root = objects[0]
|
|
@@ -31,26 +39,40 @@ export class ObjectLoader2Factory {
|
|
|
31
39
|
objectId: string
|
|
32
40
|
token?: string
|
|
33
41
|
headers?: Headers
|
|
34
|
-
|
|
35
|
-
keyRange?: { bound: Function; lowerBound: Function; upperBound: Function }
|
|
36
|
-
indexedDB?: IDBFactory
|
|
37
|
-
logger?: CustomLogger
|
|
42
|
+
options?: ObjectLoader2FactoryOptions
|
|
38
43
|
}): ObjectLoader2 {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
let loader: ObjectLoader2
|
|
45
|
+
if (params.options?.useMemoryCache) {
|
|
46
|
+
loader = new ObjectLoader2({
|
|
47
|
+
rootId: params.objectId,
|
|
48
|
+
downloader: new ServerDownloader({
|
|
49
|
+
serverUrl: params.serverUrl,
|
|
50
|
+
streamId: params.streamId,
|
|
51
|
+
objectId: params.objectId,
|
|
52
|
+
token: params.token,
|
|
53
|
+
headers: params.headers
|
|
54
|
+
}),
|
|
55
|
+
database: new MemoryDatabase({
|
|
56
|
+
items: new Map<string, Base>()
|
|
57
|
+
})
|
|
52
58
|
})
|
|
53
|
-
}
|
|
59
|
+
} else {
|
|
60
|
+
loader = new ObjectLoader2({
|
|
61
|
+
rootId: params.objectId,
|
|
62
|
+
downloader: new ServerDownloader({
|
|
63
|
+
serverUrl: params.serverUrl,
|
|
64
|
+
streamId: params.streamId,
|
|
65
|
+
objectId: params.objectId,
|
|
66
|
+
token: params.token,
|
|
67
|
+
headers: params.headers
|
|
68
|
+
}),
|
|
69
|
+
database: new IndexedDatabase({
|
|
70
|
+
logger: params.options?.logger,
|
|
71
|
+
indexedDB: params.options?.indexedDB,
|
|
72
|
+
keyRange: params.options?.keyRange
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
}
|
|
54
76
|
return loader
|
|
55
77
|
}
|
|
56
78
|
}
|
package/src/test/e2e.spec.ts
CHANGED
|
@@ -14,8 +14,10 @@ describe('e2e', () => {
|
|
|
14
14
|
serverUrl: 'https://app.speckle.systems',
|
|
15
15
|
streamId: 'da9e320dad',
|
|
16
16
|
objectId: '31d10c0cea569a1e26809658ed27e281',
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
options: {
|
|
18
|
+
indexedDB: new IDBFactory(),
|
|
19
|
+
keyRange: IDBKeyRange
|
|
20
|
+
}
|
|
19
21
|
})
|
|
20
22
|
|
|
21
23
|
const getObjectPromise = loader.getObject({
|