@speckle/objectloader2 2.25.9 → 2.26.1

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.
Files changed (92) hide show
  1. package/dist/commonjs/core/interfaces.d.ts +4 -6
  2. package/dist/commonjs/core/interfaces.d.ts.map +1 -1
  3. package/dist/commonjs/core/objectLoader2.js +2 -2
  4. package/dist/commonjs/core/objectLoader2.js.map +1 -1
  5. package/dist/commonjs/core/objectLoader2Factory.d.ts.map +1 -1
  6. package/dist/commonjs/core/objectLoader2Factory.js +4 -3
  7. package/dist/commonjs/core/objectLoader2Factory.js.map +1 -1
  8. package/dist/commonjs/core/stages/cacheWriter.js +1 -1
  9. package/dist/commonjs/core/stages/cacheWriter.js.map +1 -1
  10. package/dist/commonjs/core/stages/indexedDatabase.d.ts +20 -6
  11. package/dist/commonjs/core/stages/indexedDatabase.d.ts.map +1 -1
  12. package/dist/commonjs/core/stages/indexedDatabase.js +138 -19
  13. package/dist/commonjs/core/stages/indexedDatabase.js.map +1 -1
  14. package/dist/commonjs/core/stages/memory/memoryDatabase.d.ts +2 -4
  15. package/dist/commonjs/core/stages/memory/memoryDatabase.d.ts.map +1 -1
  16. package/dist/commonjs/core/stages/memory/memoryDatabase.js +3 -3
  17. package/dist/commonjs/core/stages/memory/memoryDatabase.js.map +1 -1
  18. package/dist/commonjs/core/stages/memory/memoryDownloader.d.ts +1 -1
  19. package/dist/commonjs/core/stages/memory/memoryDownloader.d.ts.map +1 -1
  20. package/dist/commonjs/core/stages/memory/memoryDownloader.js +1 -1
  21. package/dist/commonjs/core/stages/memory/memoryDownloader.js.map +1 -1
  22. package/dist/commonjs/core/stages/serverDownloader.d.ts +3 -2
  23. package/dist/commonjs/core/stages/serverDownloader.d.ts.map +1 -1
  24. package/dist/commonjs/core/stages/serverDownloader.js +12 -19
  25. package/dist/commonjs/core/stages/serverDownloader.js.map +1 -1
  26. package/dist/commonjs/queues/keyedQueue.test.d.ts +2 -0
  27. package/dist/commonjs/queues/keyedQueue.test.d.ts.map +1 -0
  28. package/dist/commonjs/queues/keyedQueue.test.js +118 -0
  29. package/dist/commonjs/queues/keyedQueue.test.js.map +1 -0
  30. package/dist/esm/core/interfaces.d.ts +4 -6
  31. package/dist/esm/core/interfaces.d.ts.map +1 -1
  32. package/dist/esm/core/objectLoader2.js +2 -2
  33. package/dist/esm/core/objectLoader2.js.map +1 -1
  34. package/dist/esm/core/objectLoader2Factory.d.ts.map +1 -1
  35. package/dist/esm/core/objectLoader2Factory.js +3 -2
  36. package/dist/esm/core/objectLoader2Factory.js.map +1 -1
  37. package/dist/esm/core/stages/cacheWriter.js +1 -1
  38. package/dist/esm/core/stages/cacheWriter.js.map +1 -1
  39. package/dist/esm/core/stages/indexedDatabase.d.ts +20 -6
  40. package/dist/esm/core/stages/indexedDatabase.d.ts.map +1 -1
  41. package/dist/esm/core/stages/indexedDatabase.js +140 -22
  42. package/dist/esm/core/stages/indexedDatabase.js.map +1 -1
  43. package/dist/esm/core/stages/memory/memoryDatabase.d.ts +2 -4
  44. package/dist/esm/core/stages/memory/memoryDatabase.d.ts.map +1 -1
  45. package/dist/esm/core/stages/memory/memoryDatabase.js +3 -3
  46. package/dist/esm/core/stages/memory/memoryDatabase.js.map +1 -1
  47. package/dist/esm/core/stages/memory/memoryDownloader.d.ts +1 -1
  48. package/dist/esm/core/stages/memory/memoryDownloader.d.ts.map +1 -1
  49. package/dist/esm/core/stages/memory/memoryDownloader.js +1 -1
  50. package/dist/esm/core/stages/memory/memoryDownloader.js.map +1 -1
  51. package/dist/esm/core/stages/serverDownloader.d.ts +3 -2
  52. package/dist/esm/core/stages/serverDownloader.d.ts.map +1 -1
  53. package/dist/esm/core/stages/serverDownloader.js +12 -19
  54. package/dist/esm/core/stages/serverDownloader.js.map +1 -1
  55. package/dist/esm/queues/keyedQueue.test.d.ts +2 -0
  56. package/dist/esm/queues/keyedQueue.test.d.ts.map +1 -0
  57. package/dist/esm/queues/keyedQueue.test.js +113 -0
  58. package/dist/esm/queues/keyedQueue.test.js.map +1 -0
  59. package/package.json +2 -2
  60. package/src/core/interfaces.ts +4 -4
  61. package/src/core/objectLoader2.spec.ts +1 -1
  62. package/src/core/objectLoader2.ts +2 -2
  63. package/src/core/objectLoader2Factory.ts +3 -2
  64. package/src/core/stages/cacheWriter.spec.ts +4 -4
  65. package/src/core/stages/cacheWriter.ts +1 -1
  66. package/src/core/stages/indexedDatabase.spec.ts +6 -6
  67. package/src/core/stages/indexedDatabase.ts +154 -25
  68. package/src/core/stages/memory/memoryDatabase.spec.ts +6 -6
  69. package/src/core/stages/memory/memoryDatabase.ts +3 -3
  70. package/src/core/stages/memory/memoryDownloader.spec.ts +2 -2
  71. package/src/core/stages/memory/memoryDownloader.ts +1 -1
  72. package/src/core/stages/serverDownloader.spec.ts +20 -12
  73. package/src/core/stages/serverDownloader.ts +18 -24
  74. package/src/queues/keyedQueue.test.ts +146 -0
  75. package/dist/commonjs/core/stages/ItemStore.d.ts +0 -37
  76. package/dist/commonjs/core/stages/ItemStore.d.ts.map +0 -1
  77. package/dist/commonjs/core/stages/ItemStore.js +0 -167
  78. package/dist/commonjs/core/stages/ItemStore.js.map +0 -1
  79. package/dist/commonjs/queues/batchedPool.d.ts +0 -13
  80. package/dist/commonjs/queues/batchedPool.d.ts.map +0 -1
  81. package/dist/commonjs/queues/batchedPool.js +0 -45
  82. package/dist/commonjs/queues/batchedPool.js.map +0 -1
  83. package/dist/esm/core/stages/ItemStore.d.ts +0 -37
  84. package/dist/esm/core/stages/ItemStore.d.ts.map +0 -1
  85. package/dist/esm/core/stages/ItemStore.js +0 -163
  86. package/dist/esm/core/stages/ItemStore.js.map +0 -1
  87. package/dist/esm/queues/batchedPool.d.ts +0 -13
  88. package/dist/esm/queues/batchedPool.d.ts.map +0 -1
  89. package/dist/esm/queues/batchedPool.js +0 -42
  90. package/dist/esm/queues/batchedPool.js.map +0 -1
  91. package/src/core/stages/ItemStore.ts +0 -196
  92. package/src/queues/batchedPool.ts +0 -58
@@ -22,7 +22,7 @@ export class MemoryDatabase implements Database {
22
22
  return Promise.resolve(found)
23
23
  }
24
24
 
25
- saveBatch({ batch }: { batch: Item[] }): Promise<void> {
25
+ putAll(batch: Item[]): Promise<void> {
26
26
  for (const item of batch) {
27
27
  if (!item.baseId || !item.base) {
28
28
  throw new Error('Item must have a baseId and base')
@@ -32,7 +32,7 @@ export class MemoryDatabase implements Database {
32
32
  return Promise.resolve()
33
33
  }
34
34
 
35
- disposeAsync(): Promise<void> {
36
- return Promise.resolve()
35
+ dispose(): void {
36
+ this.items.clear()
37
37
  }
38
38
  }
@@ -33,13 +33,13 @@ describe('MemoryDownloader', () => {
33
33
  })
34
34
 
35
35
  it('should add found item to results queue', () => {
36
- downloader.initializePool({ results, total: 2 })
36
+ downloader.initialize({ results, total: 2 })
37
37
  downloader.add('id2')
38
38
  expect(items).toMatchSnapshot()
39
39
  })
40
40
 
41
41
  it('should throw if added item is missing', () => {
42
- downloader.initializePool({ results, total: 2 })
42
+ downloader.initialize({ results, total: 2 })
43
43
  expect(() => downloader.add('missing')).toThrow()
44
44
  })
45
45
 
@@ -11,7 +11,7 @@ export class MemoryDownloader implements Downloader {
11
11
  this.#rootId = rootId
12
12
  this.#items = items
13
13
  }
14
- initializePool(params: {
14
+ initialize(params: {
15
15
  results: Queue<Item>
16
16
  total: number
17
17
  maxDownloadBatchWait?: number
@@ -16,9 +16,10 @@ describe('downloader', () => {
16
16
  streamId: 'streamId',
17
17
  objectId: 'objectId',
18
18
  token: 'token',
19
- fetch: fetchMocker
19
+ fetch: fetchMocker,
20
+ logger: (): void => {}
20
21
  })
21
- downloader.initializePool({
22
+ downloader.initialize({
22
23
  results: gathered,
23
24
  total: 1,
24
25
  maxDownloadBatchWait: 200
@@ -51,9 +52,10 @@ describe('downloader', () => {
51
52
  objectId: 'objectId',
52
53
  token: 'token',
53
54
 
54
- fetch: fetchMocker
55
+ fetch: fetchMocker,
56
+ logger: (): void => {}
55
57
  })
56
- downloader.initializePool({
58
+ downloader.initialize({
57
59
  results: gathered,
58
60
  total: 2,
59
61
  maxDownloadBatchWait: 200
@@ -95,9 +97,10 @@ describe('downloader', () => {
95
97
  objectId: 'objectId',
96
98
  token: 'token',
97
99
 
98
- fetch: fetchMocker
100
+ fetch: fetchMocker,
101
+ logger: (): void => {}
99
102
  })
100
- downloader.initializePool({
103
+ downloader.initialize({
101
104
  results: gathered,
102
105
  total: 3,
103
106
  maxDownloadBatchWait: 200
@@ -143,9 +146,10 @@ describe('downloader', () => {
143
146
  objectId: 'objectId',
144
147
  token: 'token',
145
148
 
146
- fetch: fetchMocker
149
+ fetch: fetchMocker,
150
+ logger: (): void => {}
147
151
  })
148
- downloader.initializePool({
152
+ downloader.initialize({
149
153
  results: gathered,
150
154
  total: 3,
151
155
  maxDownloadBatchWait: 200
@@ -183,7 +187,8 @@ describe('downloader', () => {
183
187
  objectId: i.baseId,
184
188
  token: 'token',
185
189
 
186
- fetch: fetchMocker
190
+ fetch: fetchMocker,
191
+ logger: (): void => {}
187
192
  })
188
193
  await expect(downloader.downloadSingle()).rejects.toThrow()
189
194
  await downloader.disposeAsync()
@@ -202,7 +207,8 @@ describe('downloader', () => {
202
207
  objectId: i.baseId,
203
208
  token: 'token',
204
209
 
205
- fetch: fetchMocker
210
+ fetch: fetchMocker,
211
+ logger: (): void => {}
206
212
  })
207
213
  const x = await downloader.downloadSingle()
208
214
  expect(x).toMatchSnapshot()
@@ -228,7 +234,8 @@ describe('downloader', () => {
228
234
  objectId: i.baseId,
229
235
  token: 'token',
230
236
 
231
- fetch: fetchMocker
237
+ fetch: fetchMocker,
238
+ logger: (): void => {}
232
239
  })
233
240
  const x = await downloader.downloadSingle()
234
241
  expect(x).toMatchSnapshot()
@@ -245,7 +252,8 @@ describe('downloader', () => {
245
252
  objectId: 'objectId',
246
253
  token: 'token',
247
254
 
248
- fetch: fetchMocker
255
+ fetch: fetchMocker,
256
+ logger: (): void => {}
249
257
  })
250
258
  await downloader.disposeAsync()
251
259
  })
@@ -1,7 +1,7 @@
1
- import BatchedPool from '../../queues/batchedPool.js'
1
+ import BatchingQueue from '../../queues/batchingQueue.js'
2
2
  import Queue from '../../queues/queue.js'
3
3
  import { ObjectLoaderRuntimeError } from '../../types/errors.js'
4
- import { Fetcher, indexOf, isBase, take } from '../../types/functions.js'
4
+ import { CustomLogger, Fetcher, indexOf, isBase, take } from '../../types/functions.js'
5
5
  import { Item } from '../../types/types.js'
6
6
  import { Downloader } from '../interfaces.js'
7
7
 
@@ -11,6 +11,7 @@ export interface ServerDownloaderOptions {
11
11
  objectId: string
12
12
  token?: string
13
13
  headers?: Headers
14
+ logger: CustomLogger
14
15
  fetch?: Fetcher
15
16
  }
16
17
 
@@ -24,8 +25,9 @@ export default class ServerDownloader implements Downloader {
24
25
  #fetch: Fetcher
25
26
  #results?: Queue<Item>
26
27
  #total?: number
28
+ #logger: CustomLogger
27
29
 
28
- #downloadQueue?: BatchedPool<string>
30
+ #downloadQueue?: BatchingQueue<string>
29
31
  #decoder = new TextDecoder('utf-8', { fatal: true })
30
32
  #decodedBytesCount = 0
31
33
 
@@ -34,6 +36,7 @@ export default class ServerDownloader implements Downloader {
34
36
 
35
37
  constructor(options: ServerDownloaderOptions) {
36
38
  this.#options = options
39
+ this.#logger = options.logger
37
40
  this.#fetch =
38
41
  options.fetch ?? ((...args): Promise<Response> => globalThis.fetch(...args))
39
42
 
@@ -59,25 +62,17 @@ export default class ServerDownloader implements Downloader {
59
62
  this.#rawEncoding = encoder.encode(this.#rawString)
60
63
  }
61
64
 
62
- #getDownloadCountAndSizes(total: number): number[] {
63
- if (total <= 50) {
64
- return [total]
65
- }
66
-
67
- return [10000, 25000, 10000, 1000]
68
- }
69
-
70
- initializePool(params: {
65
+ initialize(params: {
71
66
  results: Queue<Item>
72
67
  total: number
73
68
  maxDownloadBatchWait?: number
74
69
  }): void {
75
- const { results, total } = params
70
+ const { results, total, maxDownloadBatchWait } = params
76
71
  this.#results = results
77
72
  this.#total = total
78
- this.#downloadQueue = new BatchedPool<string>({
79
- concurrencyAndSizes: this.#getDownloadCountAndSizes(total),
80
- maxWaitTime: params.maxDownloadBatchWait,
73
+ this.#downloadQueue = new BatchingQueue<string>({
74
+ batchSize: 15000, // 15k is a good number for most cases
75
+ maxWaitTime: maxDownloadBatchWait ?? 1000, // 1 second
81
76
  processFunction: (batch: string[]): Promise<void> =>
82
77
  this.downloadBatch({
83
78
  batch,
@@ -87,15 +82,8 @@ export default class ServerDownloader implements Downloader {
87
82
  })
88
83
  }
89
84
 
90
- #getPool(): BatchedPool<string> {
91
- if (this.#downloadQueue) {
92
- return this.#downloadQueue
93
- }
94
- throw new Error('Download pool is not initialized')
95
- }
96
-
97
85
  add(id: string): void {
98
- this.#getPool().add(id)
86
+ this.#downloadQueue?.add(id, id)
99
87
  }
100
88
 
101
89
  /*
@@ -126,6 +114,9 @@ Chrome's behavior: Chrome generally handles larger data sizes without this speci
126
114
  headers: HeadersInit
127
115
  }): Promise<void> {
128
116
  const { batch, url, headers } = params
117
+
118
+ const start = performance.now()
119
+ this.#logger(`Downloading batch of ${batch.length} items...`)
129
120
  const keys = new Set<string>(batch)
130
121
  const response = await this.#fetch(url, {
131
122
  method: 'POST',
@@ -162,6 +153,9 @@ Chrome's behavior: Chrome generally handles larger data sizes without this speci
162
153
  if (count >= this.#total!) {
163
154
  await this.#results?.disposeAsync() // mark the queue as done
164
155
  }
156
+ this.#logger(
157
+ `Downloaded batch of ${batch.length} items in ${performance.now() - start}ms`
158
+ )
165
159
  }
166
160
 
167
161
  async #processArray(
@@ -0,0 +1,146 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest'
2
+ import KeyedQueue from './keyedQueue.js'
3
+
4
+ describe('KeyedQueue', () => {
5
+ let queue: KeyedQueue<string, number>
6
+
7
+ beforeEach(() => {
8
+ queue = new KeyedQueue<string, number>()
9
+ })
10
+
11
+ describe('enqueue', () => {
12
+ it('should add a key-value pair to the queue', () => {
13
+ const result = queue.enqueue('key1', 1)
14
+
15
+ expect(result).toBe(true)
16
+ expect(queue.size).toBe(1)
17
+ expect(queue.get('key1')).toBe(1)
18
+ })
19
+
20
+ it('should return false when trying to add a key that already exists', () => {
21
+ queue.enqueue('key1', 1)
22
+ const result = queue.enqueue('key1', 2)
23
+
24
+ expect(result).toBe(false)
25
+ expect(queue.size).toBe(1)
26
+ expect(queue.get('key1')).toBe(1) // Value should not be updated
27
+ })
28
+ })
29
+
30
+ describe('enqueueAll', () => {
31
+ it('should add multiple key-value pairs to the queue', () => {
32
+ const keys = ['key1', 'key2', 'key3']
33
+ const values = [1, 2, 3]
34
+
35
+ const count = queue.enqueueAll(keys, values)
36
+
37
+ expect(count).toBe(3)
38
+ expect(queue.size).toBe(3)
39
+ expect(queue.get('key1')).toBe(1)
40
+ expect(queue.get('key2')).toBe(2)
41
+ expect(queue.get('key3')).toBe(3)
42
+ })
43
+
44
+ it('should skip keys that already exist and return the count of added items', () => {
45
+ queue.enqueue('key1', 1)
46
+
47
+ const keys = ['key1', 'key2', 'key3']
48
+ const values = [10, 2, 3]
49
+
50
+ const count = queue.enqueueAll(keys, values)
51
+
52
+ expect(count).toBe(2)
53
+ expect(queue.size).toBe(3)
54
+ expect(queue.get('key1')).toBe(1) // Original value preserved
55
+ expect(queue.get('key2')).toBe(2)
56
+ expect(queue.get('key3')).toBe(3)
57
+ })
58
+ })
59
+
60
+ describe('get', () => {
61
+ it('should return the value for a given key', () => {
62
+ queue.enqueue('key1', 1)
63
+
64
+ expect(queue.get('key1')).toBe(1)
65
+ })
66
+
67
+ it('should return undefined for a non-existent key', () => {
68
+ expect(queue.get('nonexistent')).toBeUndefined()
69
+ })
70
+ })
71
+
72
+ describe('has', () => {
73
+ it('should return true if the key exists', () => {
74
+ queue.enqueue('key1', 1)
75
+
76
+ expect(queue.has('key1')).toBe(true)
77
+ })
78
+
79
+ it('should return false if the key does not exist', () => {
80
+ expect(queue.has('nonexistent')).toBe(false)
81
+ })
82
+ })
83
+
84
+ describe('size', () => {
85
+ it('should return the number of items in the queue', () => {
86
+ expect(queue.size).toBe(0)
87
+
88
+ queue.enqueue('key1', 1)
89
+ expect(queue.size).toBe(1)
90
+
91
+ queue.enqueue('key2', 2)
92
+ expect(queue.size).toBe(2)
93
+ })
94
+ })
95
+
96
+ describe('spliceValues', () => {
97
+ it('should remove and return values from the queue', () => {
98
+ queue.enqueue('key1', 1)
99
+ queue.enqueue('key2', 2)
100
+ queue.enqueue('key3', 3)
101
+ queue.enqueue('key4', 4)
102
+
103
+ const result = queue.spliceValues(1, 2)
104
+
105
+ expect(result).toEqual([2, 3])
106
+ expect(queue.size).toBe(2)
107
+ expect(queue.has('key1')).toBe(true)
108
+ expect(queue.has('key2')).toBe(false)
109
+ expect(queue.has('key3')).toBe(false)
110
+ expect(queue.has('key4')).toBe(true)
111
+ })
112
+
113
+ it('should handle splicing at the beginning of the queue', () => {
114
+ queue.enqueue('key1', 1)
115
+ queue.enqueue('key2', 2)
116
+
117
+ const result = queue.spliceValues(0, 1)
118
+
119
+ expect(result).toEqual([1])
120
+ expect(queue.size).toBe(1)
121
+ expect(queue.has('key1')).toBe(false)
122
+ expect(queue.has('key2')).toBe(true)
123
+ })
124
+
125
+ it('should handle splicing at the end of the queue', () => {
126
+ queue.enqueue('key1', 1)
127
+ queue.enqueue('key2', 2)
128
+
129
+ const result = queue.spliceValues(1, 1)
130
+
131
+ expect(result).toEqual([2])
132
+ expect(queue.size).toBe(1)
133
+ expect(queue.has('key1')).toBe(true)
134
+ expect(queue.has('key2')).toBe(false)
135
+ })
136
+
137
+ it('should return an empty array when deleting zero elements', () => {
138
+ queue.enqueue('key1', 1)
139
+
140
+ const result = queue.spliceValues(0, 0)
141
+
142
+ expect(result).toEqual([])
143
+ expect(queue.size).toBe(1)
144
+ })
145
+ })
146
+ })
@@ -1,37 +0,0 @@
1
- import { Item } from '../../types/types.js';
2
- /**
3
- * A wrapper class for IndexedDB to simplify common database operations.
4
- */
5
- export interface ItemStoreOptions {
6
- indexedDB?: IDBFactory;
7
- keyRange?: {
8
- bound: Function;
9
- lowerBound: Function;
10
- upperBound: Function;
11
- };
12
- }
13
- export declare class ItemStore {
14
- #private;
15
- constructor(options: ItemStoreOptions, dbName: string, storeName: string);
16
- /**
17
- * Initializes the database connection and creates the object store if needed.
18
- * This must be called before any other database operations.
19
- */
20
- init(): Promise<void>;
21
- /**
22
- * Inserts or updates an array of items in a single transaction.
23
- * @param data The array of items to insert.
24
- */
25
- bulkInsert(data: Item[]): Promise<void>;
26
- /**
27
- * Retrieves an array of items from the object store based on their IDs.
28
- * @param ids The array of IDs to retrieve.
29
- */
30
- bulkGet(ids: string[]): Promise<(Item | undefined)[]>;
31
- /**
32
- * Retrieves all items from the object store.
33
- */
34
- getAll(): Promise<Item[]>;
35
- close(): void;
36
- }
37
- //# sourceMappingURL=ItemStore.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ItemStore.d.ts","sourceRoot":"","sources":["../../../../src/core/stages/ItemStore.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAE3C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,UAAU,CAAA;IACtB,QAAQ,CAAC,EAAE;QACT,KAAK,EAAE,QAAQ,CAAA;QACf,UAAU,EAAE,QAAQ,CAAA;QACpB,UAAU,EAAE,QAAQ,CAAA;KACrB,CAAA;CACF;AACD,qBAAa,SAAS;;gBAOR,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAMxE;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwE3B;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBvC;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IAmCrD;;OAEG;IACH,MAAM,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAezB,KAAK,IAAI,IAAI;CAKd"}
@@ -1,167 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ItemStore = void 0;
4
- /* eslint-disable @typescript-eslint/no-base-to-string */
5
- /* eslint-disable @typescript-eslint/prefer-promise-reject-errors */
6
- /* eslint-disable @typescript-eslint/no-explicit-any */
7
- /* eslint-disable @typescript-eslint/no-unsafe-function-type */
8
- const shared_1 = require("@speckle/shared");
9
- class ItemStore {
10
- #options;
11
- #db = undefined;
12
- #dbName;
13
- #storeName;
14
- constructor(options, dbName, storeName) {
15
- this.#options = options;
16
- this.#dbName = dbName;
17
- this.#storeName = storeName;
18
- }
19
- /**
20
- * Initializes the database connection and creates the object store if needed.
21
- * This must be called before any other database operations.
22
- */
23
- async init() {
24
- if (this.#db)
25
- return;
26
- await this.#safariFix();
27
- return this.#openDatabase();
28
- }
29
- /**
30
- * Opens the database, and if there's an error, deletes the database and tries again.
31
- */
32
- async #openDatabase() {
33
- const idb = this.#options.indexedDB ?? indexedDB;
34
- return new Promise((resolve, reject) => {
35
- const request = idb.open(this.#dbName, 1);
36
- request.onerror = () => {
37
- console.warn(`Failed to open database: ${this.#dbName}, deleting and trying again`);
38
- // Delete the database and try again
39
- const deleteRequest = idb.deleteDatabase(this.#dbName);
40
- deleteRequest.onsuccess = () => {
41
- // Try opening again after deletion
42
- void this.#openDatabase().then(resolve).catch(reject);
43
- };
44
- deleteRequest.onerror = () => {
45
- reject(`Failed to delete and reopen database: ${this.#dbName}`);
46
- };
47
- };
48
- request.onupgradeneeded = (event) => {
49
- const db = event.target.result;
50
- if (db.objectStoreNames.contains(this.#storeName)) {
51
- db.deleteObjectStore(this.#storeName);
52
- }
53
- db.createObjectStore(this.#storeName, { keyPath: 'baseId' });
54
- };
55
- request.onsuccess = (event) => {
56
- this.#db = event.target.result;
57
- resolve();
58
- };
59
- });
60
- }
61
- #getDB() {
62
- if (!this.#db) {
63
- throw new Error('Database not initialized. Call init() first.');
64
- }
65
- return this.#db;
66
- }
67
- /**
68
- * Fixes a Safari bug where IndexedDB requests get lost and never resolve - invoke before you use IndexedDB
69
- * @link Credits and more info: https://github.com/jakearchibald/safari-14-idb-fix
70
- */
71
- async #safariFix() {
72
- // No point putting other browsers or older versions of Safari through this mess.
73
- if (!(0, shared_1.isSafari)() || !this.#options.indexedDB?.databases)
74
- return Promise.resolve();
75
- let intervalId;
76
- return new Promise((resolve) => {
77
- const tryIdb = () => this.#options.indexedDB?.databases().finally(resolve);
78
- intervalId = setInterval(() => {
79
- void tryIdb();
80
- }, 100);
81
- void tryIdb();
82
- }).finally(() => clearInterval(intervalId));
83
- }
84
- /**
85
- * Inserts or updates an array of items in a single transaction.
86
- * @param data The array of items to insert.
87
- */
88
- bulkInsert(data) {
89
- return new Promise((resolve, reject) => {
90
- try {
91
- const transaction = this.#getDB().transaction(this.#storeName, 'readwrite', {
92
- durability: 'relaxed'
93
- });
94
- const store = transaction.objectStore(this.#storeName);
95
- transaction.onerror = () => {
96
- reject(`Transaction error: ${transaction.error}`);
97
- };
98
- transaction.oncomplete = () => {
99
- resolve();
100
- };
101
- data.forEach((item) => store.put(item));
102
- }
103
- catch (error) {
104
- reject(error);
105
- }
106
- });
107
- }
108
- /**
109
- * Retrieves an array of items from the object store based on their IDs.
110
- * @param ids The array of IDs to retrieve.
111
- */
112
- bulkGet(ids) {
113
- return new Promise((resolve, reject) => {
114
- if (ids.length === 0) {
115
- return resolve([]);
116
- }
117
- try {
118
- const transaction = this.#getDB().transaction(this.#storeName, 'readonly', {
119
- durability: 'relaxed'
120
- });
121
- const store = transaction.objectStore(this.#storeName);
122
- const promises = [];
123
- for (const id of ids) {
124
- promises.push(new Promise((resolveGet, rejectGet) => {
125
- const request = store.get(id);
126
- request.onerror = () => rejectGet(`Request error for id ${id}: ${request.error}`);
127
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
128
- request.onsuccess = () => resolveGet(request.result);
129
- }));
130
- }
131
- Promise.all(promises)
132
- .then((results) => {
133
- resolve(results);
134
- })
135
- .catch(reject);
136
- }
137
- catch (error) {
138
- reject(error);
139
- }
140
- });
141
- }
142
- /**
143
- * Retrieves all items from the object store.
144
- */
145
- getAll() {
146
- return new Promise((resolve, reject) => {
147
- try {
148
- const transaction = this.#getDB().transaction(this.#storeName, 'readonly');
149
- const store = transaction.objectStore(this.#storeName);
150
- const request = store.getAll();
151
- request.onerror = () => reject(`Request error: ${request.error}`);
152
- request.onsuccess = () => resolve(request.result);
153
- }
154
- catch (error) {
155
- reject(error);
156
- }
157
- });
158
- }
159
- close() {
160
- if (!this.#db)
161
- return;
162
- this.#db.close();
163
- this.#db = undefined;
164
- }
165
- }
166
- exports.ItemStore = ItemStore;
167
- //# sourceMappingURL=ItemStore.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ItemStore.js","sourceRoot":"","sources":["../../../../src/core/stages/ItemStore.ts"],"names":[],"mappings":"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"}
@@ -1,13 +0,0 @@
1
- import Queue from './queue.js';
2
- export default class BatchedPool<T> implements Queue<T> {
3
- #private;
4
- constructor(params: {
5
- concurrencyAndSizes: number[];
6
- maxWaitTime?: number;
7
- processFunction: (batch: T[]) => Promise<void>;
8
- });
9
- add(item: T): void;
10
- getBatch(batchSize: number): T[];
11
- disposeAsync(): Promise<void>;
12
- }
13
- //# sourceMappingURL=batchedPool.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"batchedPool.d.ts","sourceRoot":"","sources":["../../../src/queues/batchedPool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAA;AAE9B,MAAM,CAAC,OAAO,OAAO,WAAW,CAAC,CAAC,CAAE,YAAW,KAAK,CAAC,CAAC,CAAC;;gBAUzC,MAAM,EAAE;QAClB,mBAAmB,EAAE,MAAM,EAAE,CAAA;QAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,eAAe,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAC/C;IAOD,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAIlB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,CAAC,EAAE;IAc1B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAgBpC"}
@@ -1,45 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- class BatchedPool {
4
- #queue = [];
5
- #concurrencyAndSizes;
6
- #processFunction;
7
- #baseInterval;
8
- #processingLoop;
9
- #disposed = false;
10
- constructor(params) {
11
- this.#concurrencyAndSizes = params.concurrencyAndSizes;
12
- this.#baseInterval = Math.min(params.maxWaitTime ?? 200, 200); // Initial batch time (ms)
13
- this.#processFunction = params.processFunction;
14
- this.#processingLoop = this.#loop();
15
- }
16
- add(item) {
17
- this.#queue.push(item);
18
- }
19
- getBatch(batchSize) {
20
- return this.#queue.splice(0, Math.min(batchSize, this.#queue.length));
21
- }
22
- async #runWorker(batchSize) {
23
- while (!this.#disposed || this.#queue.length > 0) {
24
- if (this.#queue.length > 0) {
25
- const batch = this.getBatch(batchSize);
26
- await this.#processFunction(batch);
27
- }
28
- await this.#delay(this.#baseInterval);
29
- }
30
- }
31
- async disposeAsync() {
32
- this.#disposed = true;
33
- await this.#processingLoop;
34
- }
35
- async #loop() {
36
- // Initialize workers
37
- const workers = Array.from(this.#concurrencyAndSizes, (batchSize) => this.#runWorker(batchSize));
38
- await Promise.all(workers);
39
- }
40
- #delay(ms) {
41
- return new Promise((resolve) => setTimeout(resolve, ms));
42
- }
43
- }
44
- exports.default = BatchedPool;
45
- //# sourceMappingURL=batchedPool.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"batchedPool.js","sourceRoot":"","sources":["../../../src/queues/batchedPool.ts"],"names":[],"mappings":";;AAEA,MAAqB,WAAW;IAC9B,MAAM,GAAQ,EAAE,CAAA;IAChB,oBAAoB,CAAU;IAC9B,gBAAgB,CAA+B;IAE/C,aAAa,CAAQ;IAErB,eAAe,CAAe;IAC9B,SAAS,GAAG,KAAK,CAAA;IAEjB,YAAY,MAIX;QACC,IAAI,CAAC,oBAAoB,GAAG,MAAM,CAAC,mBAAmB,CAAA;QACtD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,GAAG,EAAE,GAAG,CAAC,CAAA,CAAC,0BAA0B;QACxF,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,eAAe,CAAA;QAC9C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;IACrC,CAAC;IAED,GAAG,CAAC,IAAO;QACT,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC;IAED,QAAQ,CAAC,SAAiB;QACxB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;IACvE,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB;QAChC,OAAO,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjD,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;gBACtC,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAA;YACpC,CAAC;YACD,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QACrB,MAAM,IAAI,CAAC,eAAe,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,qBAAqB;QACrB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,SAAiB,EAAE,EAAE,CAC1E,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAC3B,CAAA;QACD,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IAED,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;IAC1D,CAAC;CACF;AAvDD,8BAuDC"}