@synchronized-console/objectloader2 2.25.7 → 2.31.14
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/{operations → core}/interfaces.d.ts +5 -7
- package/dist/commonjs/core/interfaces.d.ts.map +1 -0
- package/dist/commonjs/core/interfaces.js.map +1 -0
- package/dist/commonjs/{operations → core}/objectLoader2.d.ts +1 -1
- package/dist/commonjs/core/objectLoader2.d.ts.map +1 -0
- package/dist/commonjs/core/objectLoader2.js +120 -0
- package/dist/commonjs/core/objectLoader2.js.map +1 -0
- package/dist/{esm/operations → commonjs/core}/objectLoader2Factory.d.ts +10 -2
- package/dist/commonjs/core/objectLoader2Factory.d.ts.map +1 -0
- package/dist/commonjs/core/objectLoader2Factory.js +86 -0
- package/dist/commonjs/core/objectLoader2Factory.js.map +1 -0
- package/dist/commonjs/core/objectLoader2Factory.test.d.ts +2 -0
- package/dist/commonjs/core/objectLoader2Factory.test.d.ts.map +1 -0
- package/dist/commonjs/core/objectLoader2Factory.test.js +106 -0
- package/dist/commonjs/core/objectLoader2Factory.test.js.map +1 -0
- package/dist/{esm/operations → commonjs/core}/options.d.ts +4 -1
- package/dist/commonjs/core/options.d.ts.map +1 -0
- package/dist/commonjs/{operations → core}/options.js.map +1 -1
- package/dist/commonjs/core/stages/cacheReader.d.ts +18 -0
- package/dist/commonjs/core/stages/cacheReader.d.ts.map +1 -0
- package/dist/commonjs/core/stages/cacheReader.js +72 -0
- package/dist/commonjs/core/stages/cacheReader.js.map +1 -0
- package/dist/commonjs/core/stages/cacheWriter.d.ts +15 -0
- package/dist/commonjs/core/stages/cacheWriter.d.ts.map +1 -0
- package/dist/commonjs/core/stages/cacheWriter.js +50 -0
- package/dist/commonjs/core/stages/cacheWriter.js.map +1 -0
- package/dist/commonjs/core/stages/indexedDatabase.d.ts +34 -0
- package/dist/commonjs/core/stages/indexedDatabase.d.ts.map +1 -0
- package/dist/commonjs/core/stages/indexedDatabase.js +150 -0
- package/dist/commonjs/core/stages/indexedDatabase.js.map +1 -0
- package/dist/commonjs/core/stages/memory/memoryDatabase.d.ts +11 -0
- package/dist/commonjs/core/stages/memory/memoryDatabase.d.ts.map +1 -0
- package/dist/commonjs/{operations/databases → core/stages/memory}/memoryDatabase.js +6 -3
- package/dist/commonjs/core/stages/memory/memoryDatabase.js.map +1 -0
- package/dist/commonjs/{operations/downloaders → core/stages/memory}/memoryDownloader.d.ts +4 -4
- package/dist/commonjs/core/stages/memory/memoryDownloader.d.ts.map +1 -0
- package/dist/commonjs/{operations/downloaders → core/stages/memory}/memoryDownloader.js +1 -1
- package/dist/commonjs/core/stages/memory/memoryDownloader.js.map +1 -0
- package/dist/{esm/operations/downloaders → commonjs/core/stages}/serverDownloader.d.ts +8 -6
- package/dist/commonjs/core/stages/serverDownloader.d.ts.map +1 -0
- package/dist/commonjs/{operations/downloaders → core/stages}/serverDownloader.js +99 -50
- package/dist/commonjs/core/stages/serverDownloader.js.map +1 -0
- package/dist/commonjs/core/traverser.d.ts.map +1 -0
- package/dist/commonjs/{operations → core}/traverser.js +7 -7
- package/dist/commonjs/core/traverser.js.map +1 -0
- package/dist/commonjs/deferment/MemoryCache.d.ts +35 -0
- package/dist/commonjs/deferment/MemoryCache.d.ts.map +1 -0
- package/dist/commonjs/deferment/MemoryCache.js +162 -0
- package/dist/commonjs/deferment/MemoryCache.js.map +1 -0
- package/dist/commonjs/deferment/MemoryCache.test.d.ts +2 -0
- package/dist/commonjs/deferment/MemoryCache.test.d.ts.map +1 -0
- package/dist/commonjs/deferment/MemoryCache.test.js +153 -0
- package/dist/commonjs/deferment/MemoryCache.test.js.map +1 -0
- package/dist/commonjs/deferment/defermentManager.d.ts +32 -0
- package/dist/commonjs/deferment/defermentManager.d.ts.map +1 -0
- package/dist/commonjs/deferment/defermentManager.js +85 -0
- package/dist/commonjs/deferment/defermentManager.js.map +1 -0
- package/dist/commonjs/deferment/defermentManager.test.d.ts +2 -0
- package/dist/commonjs/deferment/defermentManager.test.d.ts.map +1 -0
- package/dist/commonjs/deferment/defermentManager.test.js +193 -0
- package/dist/commonjs/deferment/defermentManager.test.js.map +1 -0
- package/dist/commonjs/deferment/deferredBase.d.ts +12 -0
- package/dist/commonjs/deferment/deferredBase.d.ts.map +1 -0
- package/dist/commonjs/deferment/deferredBase.js +27 -0
- package/dist/commonjs/deferment/deferredBase.js.map +1 -0
- package/dist/commonjs/index.d.ts +4 -2
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +6 -3
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/{helpers → queues}/aggregateQueue.d.ts +2 -1
- package/dist/commonjs/queues/aggregateQueue.d.ts.map +1 -0
- package/dist/commonjs/{helpers → queues}/aggregateQueue.js +4 -0
- package/dist/commonjs/queues/aggregateQueue.js.map +1 -0
- package/dist/{esm/helpers → commonjs/queues}/asyncGeneratorQueue.d.ts +1 -1
- package/dist/commonjs/queues/asyncGeneratorQueue.d.ts.map +1 -0
- package/dist/commonjs/{helpers → queues}/asyncGeneratorQueue.js +2 -1
- package/dist/commonjs/queues/asyncGeneratorQueue.js.map +1 -0
- package/dist/commonjs/{helpers → queues}/batchingQueue.d.ts +4 -1
- package/dist/commonjs/queues/batchingQueue.d.ts.map +1 -0
- package/dist/commonjs/queues/batchingQueue.dispose.test.d.ts +2 -0
- package/dist/commonjs/queues/batchingQueue.dispose.test.d.ts.map +1 -0
- package/dist/commonjs/queues/batchingQueue.dispose.test.js +62 -0
- package/dist/commonjs/queues/batchingQueue.dispose.test.js.map +1 -0
- package/dist/commonjs/queues/batchingQueue.js +128 -0
- package/dist/commonjs/queues/batchingQueue.js.map +1 -0
- package/dist/commonjs/queues/batchingQueue.test.d.ts +2 -0
- package/dist/commonjs/queues/batchingQueue.test.d.ts.map +1 -0
- package/dist/commonjs/queues/batchingQueue.test.js +236 -0
- package/dist/commonjs/queues/batchingQueue.test.js.map +1 -0
- package/dist/{esm/helpers → commonjs/queues}/bufferQueue.d.ts +1 -0
- package/dist/commonjs/queues/bufferQueue.d.ts.map +1 -0
- package/dist/commonjs/{helpers → queues}/bufferQueue.js +3 -0
- package/dist/commonjs/queues/bufferQueue.js.map +1 -0
- package/dist/commonjs/{helpers → queues}/keyedQueue.d.ts +1 -0
- package/dist/commonjs/queues/keyedQueue.d.ts.map +1 -0
- package/dist/commonjs/{helpers → queues}/keyedQueue.js +11 -0
- package/dist/commonjs/queues/keyedQueue.js.map +1 -0
- package/dist/commonjs/queues/keyedQueue.test.d.ts +2 -0
- package/dist/commonjs/queues/keyedQueue.test.d.ts.map +1 -0
- package/dist/commonjs/queues/keyedQueue.test.js +118 -0
- package/dist/commonjs/queues/keyedQueue.test.js.map +1 -0
- package/dist/commonjs/queues/queue.d.ts +5 -0
- package/dist/commonjs/queues/queue.d.ts.map +1 -0
- package/dist/commonjs/{helpers → queues}/queue.js.map +1 -1
- package/dist/commonjs/types/functions.d.ts +21 -0
- package/dist/commonjs/types/functions.d.ts.map +1 -0
- package/dist/commonjs/types/functions.js +92 -0
- package/dist/commonjs/types/functions.js.map +1 -0
- package/dist/commonjs/types/types.d.ts +6 -7
- package/dist/commonjs/types/types.d.ts.map +1 -1
- package/dist/commonjs/types/types.js +0 -36
- package/dist/commonjs/types/types.js.map +1 -1
- package/dist/esm/{operations → core}/interfaces.d.ts +5 -7
- package/dist/esm/core/interfaces.d.ts.map +1 -0
- package/dist/esm/core/interfaces.js.map +1 -0
- package/dist/esm/{operations → core}/objectLoader2.d.ts +1 -1
- package/dist/esm/core/objectLoader2.d.ts.map +1 -0
- package/dist/esm/core/objectLoader2.js +113 -0
- package/dist/esm/core/objectLoader2.js.map +1 -0
- package/dist/{commonjs/operations → esm/core}/objectLoader2Factory.d.ts +10 -2
- package/dist/esm/core/objectLoader2Factory.d.ts.map +1 -0
- package/dist/esm/core/objectLoader2Factory.js +79 -0
- package/dist/esm/core/objectLoader2Factory.js.map +1 -0
- package/dist/esm/core/objectLoader2Factory.test.d.ts +2 -0
- package/dist/esm/core/objectLoader2Factory.test.d.ts.map +1 -0
- package/dist/esm/core/objectLoader2Factory.test.js +104 -0
- package/dist/esm/core/objectLoader2Factory.test.js.map +1 -0
- package/dist/{commonjs/operations → esm/core}/options.d.ts +4 -1
- package/dist/esm/core/options.d.ts.map +1 -0
- package/dist/esm/{operations → core}/options.js.map +1 -1
- package/dist/esm/core/stages/cacheReader.d.ts +18 -0
- package/dist/esm/core/stages/cacheReader.d.ts.map +1 -0
- package/dist/esm/core/stages/cacheReader.js +65 -0
- package/dist/esm/core/stages/cacheReader.js.map +1 -0
- package/dist/esm/core/stages/cacheWriter.d.ts +15 -0
- package/dist/esm/core/stages/cacheWriter.d.ts.map +1 -0
- package/dist/esm/core/stages/cacheWriter.js +43 -0
- package/dist/esm/core/stages/cacheWriter.js.map +1 -0
- package/dist/esm/core/stages/indexedDatabase.d.ts +34 -0
- package/dist/esm/core/stages/indexedDatabase.d.ts.map +1 -0
- package/dist/esm/core/stages/indexedDatabase.js +146 -0
- package/dist/esm/core/stages/indexedDatabase.js.map +1 -0
- package/dist/esm/core/stages/memory/memoryDatabase.d.ts +11 -0
- package/dist/esm/core/stages/memory/memoryDatabase.d.ts.map +1 -0
- package/dist/esm/{operations/databases → core/stages/memory}/memoryDatabase.js +6 -3
- package/dist/esm/core/stages/memory/memoryDatabase.js.map +1 -0
- package/dist/esm/{operations/downloaders → core/stages/memory}/memoryDownloader.d.ts +4 -4
- package/dist/esm/core/stages/memory/memoryDownloader.d.ts.map +1 -0
- package/dist/esm/{operations/downloaders → core/stages/memory}/memoryDownloader.js +1 -1
- package/dist/esm/core/stages/memory/memoryDownloader.js.map +1 -0
- package/dist/{commonjs/operations/downloaders → esm/core/stages}/serverDownloader.d.ts +8 -6
- package/dist/esm/core/stages/serverDownloader.d.ts.map +1 -0
- package/dist/esm/{operations/downloaders → core/stages}/serverDownloader.js +98 -49
- package/dist/esm/core/stages/serverDownloader.js.map +1 -0
- package/dist/esm/core/traverser.d.ts.map +1 -0
- package/dist/esm/{operations → core}/traverser.js +1 -1
- package/dist/esm/core/traverser.js.map +1 -0
- package/dist/esm/deferment/MemoryCache.d.ts +35 -0
- package/dist/esm/deferment/MemoryCache.d.ts.map +1 -0
- package/dist/esm/deferment/MemoryCache.js +157 -0
- package/dist/esm/deferment/MemoryCache.js.map +1 -0
- package/dist/esm/deferment/MemoryCache.test.d.ts +2 -0
- package/dist/esm/deferment/MemoryCache.test.d.ts.map +1 -0
- package/dist/esm/deferment/MemoryCache.test.js +151 -0
- package/dist/esm/deferment/MemoryCache.test.js.map +1 -0
- package/dist/esm/deferment/defermentManager.d.ts +32 -0
- package/dist/esm/deferment/defermentManager.d.ts.map +1 -0
- package/dist/esm/deferment/defermentManager.js +80 -0
- package/dist/esm/deferment/defermentManager.js.map +1 -0
- package/dist/esm/deferment/defermentManager.test.d.ts +2 -0
- package/dist/esm/deferment/defermentManager.test.d.ts.map +1 -0
- package/dist/esm/deferment/defermentManager.test.js +191 -0
- package/dist/esm/deferment/defermentManager.test.js.map +1 -0
- package/dist/esm/deferment/deferredBase.d.ts +12 -0
- package/dist/esm/deferment/deferredBase.d.ts.map +1 -0
- package/dist/esm/deferment/deferredBase.js +23 -0
- package/dist/esm/deferment/deferredBase.js.map +1 -0
- package/dist/esm/index.d.ts +4 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/{helpers → queues}/aggregateQueue.d.ts +2 -1
- package/dist/esm/queues/aggregateQueue.d.ts.map +1 -0
- package/dist/esm/{helpers → queues}/aggregateQueue.js +4 -0
- package/dist/esm/queues/aggregateQueue.js.map +1 -0
- package/dist/{commonjs/helpers → esm/queues}/asyncGeneratorQueue.d.ts +1 -1
- package/dist/esm/queues/asyncGeneratorQueue.d.ts.map +1 -0
- package/dist/esm/{helpers → queues}/asyncGeneratorQueue.js +2 -1
- package/dist/esm/queues/asyncGeneratorQueue.js.map +1 -0
- package/dist/esm/{helpers → queues}/batchingQueue.d.ts +4 -1
- package/dist/esm/queues/batchingQueue.d.ts.map +1 -0
- package/dist/esm/queues/batchingQueue.dispose.test.d.ts +2 -0
- package/dist/esm/queues/batchingQueue.dispose.test.d.ts.map +1 -0
- package/dist/esm/queues/batchingQueue.dispose.test.js +57 -0
- package/dist/esm/queues/batchingQueue.dispose.test.js.map +1 -0
- package/dist/esm/queues/batchingQueue.js +122 -0
- package/dist/esm/queues/batchingQueue.js.map +1 -0
- package/dist/esm/queues/batchingQueue.test.d.ts +2 -0
- package/dist/esm/queues/batchingQueue.test.d.ts.map +1 -0
- package/dist/esm/queues/batchingQueue.test.js +231 -0
- package/dist/esm/queues/batchingQueue.test.js.map +1 -0
- package/dist/{commonjs/helpers → esm/queues}/bufferQueue.d.ts +1 -0
- package/dist/esm/queues/bufferQueue.d.ts.map +1 -0
- package/dist/esm/{helpers → queues}/bufferQueue.js +3 -0
- package/dist/esm/queues/bufferQueue.js.map +1 -0
- package/dist/esm/{helpers → queues}/keyedQueue.d.ts +1 -0
- package/dist/esm/queues/keyedQueue.d.ts.map +1 -0
- package/dist/esm/{helpers → queues}/keyedQueue.js +11 -0
- package/dist/esm/queues/keyedQueue.js.map +1 -0
- package/dist/esm/queues/keyedQueue.test.d.ts +2 -0
- package/dist/esm/queues/keyedQueue.test.d.ts.map +1 -0
- package/dist/esm/queues/keyedQueue.test.js +113 -0
- package/dist/esm/queues/keyedQueue.test.js.map +1 -0
- package/dist/esm/queues/queue.d.ts +5 -0
- package/dist/esm/queues/queue.d.ts.map +1 -0
- package/dist/esm/{helpers → queues}/queue.js.map +1 -1
- package/dist/esm/types/functions.d.ts +21 -0
- package/dist/esm/types/functions.d.ts.map +1 -0
- package/dist/esm/types/functions.js +83 -0
- package/dist/esm/types/functions.js.map +1 -0
- package/dist/esm/types/types.d.ts +6 -7
- package/dist/esm/types/types.d.ts.map +1 -1
- package/dist/esm/types/types.js +1 -32
- package/dist/esm/types/types.js.map +1 -1
- package/package.json +5 -3
- package/src/{operations → core}/interfaces.ts +5 -5
- package/src/{operations → core}/objectLoader2.spec.ts +31 -11
- package/src/core/objectLoader2.ts +152 -0
- package/src/core/objectLoader2Factory.test.ts +135 -0
- package/src/core/objectLoader2Factory.ts +113 -0
- package/src/{operations → core}/options.ts +4 -1
- package/src/{operations/databases → core/stages}/__snapshots__/indexedDatabase.spec.ts.snap +4 -4
- package/src/{operations/downloaders → core/stages}/__snapshots__/serverDownloader.spec.ts.snap +25 -0
- package/src/{helpers → core/stages}/cacheReader.spec.ts +12 -7
- package/src/core/stages/cacheReader.ts +88 -0
- package/src/core/stages/cacheWriter.spec.ts +213 -0
- package/src/core/stages/cacheWriter.ts +64 -0
- package/src/{operations/databases → core/stages}/indexedDatabase.spec.ts +12 -8
- package/src/core/stages/indexedDatabase.ts +178 -0
- package/src/{operations/databases → core/stages/memory}/memoryDatabase.spec.ts +7 -7
- package/src/{operations/databases → core/stages/memory}/memoryDatabase.ts +9 -6
- package/src/{operations/downloaders → core/stages/memory}/memoryDownloader.spec.ts +5 -5
- package/src/{operations/downloaders → core/stages/memory}/memoryDownloader.ts +4 -4
- package/src/core/stages/serverDownloader.spec.ts +382 -0
- package/src/{operations/downloaders → core/stages}/serverDownloader.ts +115 -52
- package/src/{operations → core}/traverser.ts +2 -1
- package/src/deferment/MemoryCache.test.ts +187 -0
- package/src/deferment/MemoryCache.ts +189 -0
- package/src/deferment/defermentManager.test.ts +225 -0
- package/src/deferment/defermentManager.ts +95 -0
- package/src/deferment/deferredBase.ts +29 -0
- package/src/index.ts +4 -2
- package/src/{helpers → queues}/aggregateQueue.ts +5 -1
- package/src/{helpers → queues}/asyncGeneratorQueue.ts +2 -1
- package/src/queues/batchingQueue.dispose.test.ts +72 -0
- package/src/queues/batchingQueue.test.ts +270 -0
- package/src/queues/batchingQueue.ts +140 -0
- package/src/{helpers → queues}/bufferQueue.ts +3 -0
- package/src/queues/keyedQueue.test.ts +146 -0
- package/src/{helpers → queues}/keyedQueue.ts +12 -0
- package/src/{helpers → queues}/queue.ts +1 -0
- package/src/test/e2e.spec.ts +2 -2
- package/src/types/functions.spec.ts +155 -0
- package/src/types/functions.ts +116 -0
- package/src/types/types.ts +5 -50
- package/dist/commonjs/helpers/aggregateQueue.d.ts.map +0 -1
- package/dist/commonjs/helpers/aggregateQueue.js.map +0 -1
- package/dist/commonjs/helpers/asyncGeneratorQueue.d.ts.map +0 -1
- package/dist/commonjs/helpers/asyncGeneratorQueue.js.map +0 -1
- package/dist/commonjs/helpers/batchedPool.d.ts +0 -12
- package/dist/commonjs/helpers/batchedPool.d.ts.map +0 -1
- package/dist/commonjs/helpers/batchedPool.js +0 -45
- package/dist/commonjs/helpers/batchedPool.js.map +0 -1
- package/dist/commonjs/helpers/batchingQueue.d.ts.map +0 -1
- package/dist/commonjs/helpers/batchingQueue.js +0 -77
- package/dist/commonjs/helpers/batchingQueue.js.map +0 -1
- package/dist/commonjs/helpers/bufferQueue.d.ts.map +0 -1
- package/dist/commonjs/helpers/bufferQueue.js.map +0 -1
- package/dist/commonjs/helpers/cachePump.d.ts +0 -22
- package/dist/commonjs/helpers/cachePump.d.ts.map +0 -1
- package/dist/commonjs/helpers/cachePump.js +0 -86
- package/dist/commonjs/helpers/cachePump.js.map +0 -1
- package/dist/commonjs/helpers/cacheReader.d.ts +0 -14
- package/dist/commonjs/helpers/cacheReader.d.ts.map +0 -1
- package/dist/commonjs/helpers/cacheReader.js +0 -58
- package/dist/commonjs/helpers/cacheReader.js.map +0 -1
- package/dist/commonjs/helpers/defermentManager.d.ts +0 -28
- package/dist/commonjs/helpers/defermentManager.d.ts.map +0 -1
- package/dist/commonjs/helpers/defermentManager.js +0 -150
- package/dist/commonjs/helpers/defermentManager.js.map +0 -1
- package/dist/commonjs/helpers/deferredBase.d.ts +0 -19
- package/dist/commonjs/helpers/deferredBase.d.ts.map +0 -1
- package/dist/commonjs/helpers/deferredBase.js +0 -51
- package/dist/commonjs/helpers/deferredBase.js.map +0 -1
- package/dist/commonjs/helpers/keyedQueue.d.ts.map +0 -1
- package/dist/commonjs/helpers/keyedQueue.js.map +0 -1
- package/dist/commonjs/helpers/memoryPump.d.ts +0 -15
- package/dist/commonjs/helpers/memoryPump.d.ts.map +0 -1
- package/dist/commonjs/helpers/memoryPump.js +0 -34
- package/dist/commonjs/helpers/memoryPump.js.map +0 -1
- package/dist/commonjs/helpers/pump.d.ts +0 -8
- package/dist/commonjs/helpers/pump.d.ts.map +0 -1
- package/dist/commonjs/helpers/pump.js +0 -3
- package/dist/commonjs/helpers/pump.js.map +0 -1
- package/dist/commonjs/helpers/queue.d.ts +0 -4
- package/dist/commonjs/helpers/queue.d.ts.map +0 -1
- package/dist/commonjs/operations/databases/indexedDatabase.d.ts +0 -27
- package/dist/commonjs/operations/databases/indexedDatabase.d.ts.map +0 -1
- package/dist/commonjs/operations/databases/indexedDatabase.js +0 -98
- package/dist/commonjs/operations/databases/indexedDatabase.js.map +0 -1
- package/dist/commonjs/operations/databases/memoryDatabase.d.ts +0 -13
- package/dist/commonjs/operations/databases/memoryDatabase.d.ts.map +0 -1
- package/dist/commonjs/operations/databases/memoryDatabase.js.map +0 -1
- package/dist/commonjs/operations/downloaders/memoryDownloader.d.ts.map +0 -1
- package/dist/commonjs/operations/downloaders/memoryDownloader.js.map +0 -1
- package/dist/commonjs/operations/downloaders/serverDownloader.d.ts.map +0 -1
- package/dist/commonjs/operations/downloaders/serverDownloader.js.map +0 -1
- package/dist/commonjs/operations/interfaces.d.ts.map +0 -1
- package/dist/commonjs/operations/interfaces.js.map +0 -1
- package/dist/commonjs/operations/objectLoader2.d.ts.map +0 -1
- package/dist/commonjs/operations/objectLoader2.js +0 -101
- package/dist/commonjs/operations/objectLoader2.js.map +0 -1
- package/dist/commonjs/operations/objectLoader2Factory.d.ts.map +0 -1
- package/dist/commonjs/operations/objectLoader2Factory.js +0 -68
- package/dist/commonjs/operations/objectLoader2Factory.js.map +0 -1
- package/dist/commonjs/operations/options.d.ts.map +0 -1
- package/dist/commonjs/operations/traverser.d.ts.map +0 -1
- package/dist/commonjs/operations/traverser.js.map +0 -1
- package/dist/esm/helpers/aggregateQueue.d.ts.map +0 -1
- package/dist/esm/helpers/aggregateQueue.js.map +0 -1
- package/dist/esm/helpers/asyncGeneratorQueue.d.ts.map +0 -1
- package/dist/esm/helpers/asyncGeneratorQueue.js.map +0 -1
- package/dist/esm/helpers/batchedPool.d.ts +0 -12
- package/dist/esm/helpers/batchedPool.d.ts.map +0 -1
- package/dist/esm/helpers/batchedPool.js +0 -42
- package/dist/esm/helpers/batchedPool.js.map +0 -1
- package/dist/esm/helpers/batchingQueue.d.ts.map +0 -1
- package/dist/esm/helpers/batchingQueue.js +0 -71
- package/dist/esm/helpers/batchingQueue.js.map +0 -1
- package/dist/esm/helpers/bufferQueue.d.ts.map +0 -1
- package/dist/esm/helpers/bufferQueue.js.map +0 -1
- package/dist/esm/helpers/cachePump.d.ts +0 -22
- package/dist/esm/helpers/cachePump.d.ts.map +0 -1
- package/dist/esm/helpers/cachePump.js +0 -79
- package/dist/esm/helpers/cachePump.js.map +0 -1
- package/dist/esm/helpers/cacheReader.d.ts +0 -14
- package/dist/esm/helpers/cacheReader.d.ts.map +0 -1
- package/dist/esm/helpers/cacheReader.js +0 -51
- package/dist/esm/helpers/cacheReader.js.map +0 -1
- package/dist/esm/helpers/defermentManager.d.ts +0 -28
- package/dist/esm/helpers/defermentManager.d.ts.map +0 -1
- package/dist/esm/helpers/defermentManager.js +0 -146
- package/dist/esm/helpers/defermentManager.js.map +0 -1
- package/dist/esm/helpers/deferredBase.d.ts +0 -19
- package/dist/esm/helpers/deferredBase.d.ts.map +0 -1
- package/dist/esm/helpers/deferredBase.js +0 -47
- package/dist/esm/helpers/deferredBase.js.map +0 -1
- package/dist/esm/helpers/keyedQueue.d.ts.map +0 -1
- package/dist/esm/helpers/keyedQueue.js.map +0 -1
- package/dist/esm/helpers/memoryPump.d.ts +0 -15
- package/dist/esm/helpers/memoryPump.d.ts.map +0 -1
- package/dist/esm/helpers/memoryPump.js +0 -30
- package/dist/esm/helpers/memoryPump.js.map +0 -1
- package/dist/esm/helpers/pump.d.ts +0 -8
- package/dist/esm/helpers/pump.d.ts.map +0 -1
- package/dist/esm/helpers/pump.js +0 -2
- package/dist/esm/helpers/pump.js.map +0 -1
- package/dist/esm/helpers/queue.d.ts +0 -4
- package/dist/esm/helpers/queue.d.ts.map +0 -1
- package/dist/esm/operations/databases/indexedDatabase.d.ts +0 -27
- package/dist/esm/operations/databases/indexedDatabase.d.ts.map +0 -1
- package/dist/esm/operations/databases/indexedDatabase.js +0 -93
- package/dist/esm/operations/databases/indexedDatabase.js.map +0 -1
- package/dist/esm/operations/databases/memoryDatabase.d.ts +0 -13
- package/dist/esm/operations/databases/memoryDatabase.d.ts.map +0 -1
- package/dist/esm/operations/databases/memoryDatabase.js.map +0 -1
- package/dist/esm/operations/downloaders/memoryDownloader.d.ts.map +0 -1
- package/dist/esm/operations/downloaders/memoryDownloader.js.map +0 -1
- package/dist/esm/operations/downloaders/serverDownloader.d.ts.map +0 -1
- package/dist/esm/operations/downloaders/serverDownloader.js.map +0 -1
- package/dist/esm/operations/interfaces.d.ts.map +0 -1
- package/dist/esm/operations/interfaces.js.map +0 -1
- package/dist/esm/operations/objectLoader2.d.ts.map +0 -1
- package/dist/esm/operations/objectLoader2.js +0 -94
- package/dist/esm/operations/objectLoader2.js.map +0 -1
- package/dist/esm/operations/objectLoader2Factory.d.ts.map +0 -1
- package/dist/esm/operations/objectLoader2Factory.js +0 -61
- package/dist/esm/operations/objectLoader2Factory.js.map +0 -1
- package/dist/esm/operations/options.d.ts.map +0 -1
- package/dist/esm/operations/traverser.d.ts.map +0 -1
- package/dist/esm/operations/traverser.js.map +0 -1
- package/src/helpers/__snapshots__/cachePump.spec.ts.snap +0 -31
- package/src/helpers/__snapshots__/defermentManager.spec.ts.snap +0 -8
- package/src/helpers/batchedPool.ts +0 -56
- package/src/helpers/batchingQueue.ts +0 -85
- package/src/helpers/cachePump.disposal.spec.ts +0 -51
- package/src/helpers/cachePump.spec.ts +0 -104
- package/src/helpers/cachePump.ts +0 -107
- package/src/helpers/cacheReader.ts +0 -64
- package/src/helpers/defermentManager.defermentTotals.spec.ts +0 -53
- package/src/helpers/defermentManager.disposal.spec.ts +0 -28
- package/src/helpers/defermentManager.spec.ts +0 -37
- package/src/helpers/defermentManager.ts +0 -160
- package/src/helpers/deferredBase.ts +0 -55
- package/src/helpers/memoryPump.ts +0 -40
- package/src/helpers/pump.ts +0 -8
- package/src/operations/databases/indexedDatabase.ts +0 -126
- package/src/operations/downloaders/serverDownloader.spec.ts +0 -161
- package/src/operations/objectLoader2.ts +0 -119
- package/src/operations/objectLoader2Factory.ts +0 -78
- package/dist/commonjs/{operations → core}/interfaces.js +0 -0
- package/dist/commonjs/{operations → core}/options.js +0 -0
- package/dist/commonjs/{operations → core}/traverser.d.ts +0 -0
- package/dist/commonjs/{helpers → queues}/queue.js +0 -0
- package/dist/esm/{operations → core}/interfaces.js +0 -0
- package/dist/esm/{operations → core}/options.js +0 -0
- package/dist/esm/{operations → core}/traverser.d.ts +0 -0
- package/dist/esm/{helpers → queues}/queue.js +0 -0
- package/src/{operations → core}/__snapshots__/objectLoader2.spec.ts.snap +0 -0
- package/src/{operations → core}/__snapshots__/traverser.spec.ts.snap +0 -0
- package/src/{helpers → core/stages}/__snapshots__/cacheReader.spec.ts.snap +0 -0
- package/src/{operations/downloaders → core/stages/memory}/__snapshots__/memoryDownloader.spec.ts.snap +0 -0
- package/src/{operations → core}/traverser.spec.ts +1 -1
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
import createFetchMock from 'vitest-fetch-mock'
|
|
3
|
+
import { vi } from 'vitest'
|
|
4
|
+
import { Item } from '../../types/types.js'
|
|
5
|
+
import ServerDownloader from './serverDownloader.js'
|
|
6
|
+
import AsyncGeneratorQueue from '../../queues/asyncGeneratorQueue.js'
|
|
7
|
+
|
|
8
|
+
describe('downloader', () => {
|
|
9
|
+
test('download batch of one', async () => {
|
|
10
|
+
const fetchMocker = createFetchMock(vi)
|
|
11
|
+
const i: Item = { baseId: 'id', base: { id: 'id', synchronized_type: 'type' } }
|
|
12
|
+
fetchMocker.mockResponseOnce('id\t' + JSON.stringify(i.base) + '\n')
|
|
13
|
+
const gathered = new AsyncGeneratorQueue<Item>()
|
|
14
|
+
const downloader = new ServerDownloader({
|
|
15
|
+
serverUrl: 'http://synchronized.test',
|
|
16
|
+
streamId: 'streamId',
|
|
17
|
+
objectId: 'objectId',
|
|
18
|
+
token: 'token',
|
|
19
|
+
fetch: fetchMocker,
|
|
20
|
+
logger: (): void => {}
|
|
21
|
+
})
|
|
22
|
+
downloader.initialize({
|
|
23
|
+
results: gathered,
|
|
24
|
+
total: 1,
|
|
25
|
+
maxDownloadBatchWait: 200
|
|
26
|
+
})
|
|
27
|
+
downloader.add('id')
|
|
28
|
+
const r = []
|
|
29
|
+
for await (const x of gathered.consume()) {
|
|
30
|
+
r.push(x)
|
|
31
|
+
if (r.length >= 1) {
|
|
32
|
+
break
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
expect(r).toMatchSnapshot()
|
|
37
|
+
await downloader.disposeAsync()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('download batch of two', async () => {
|
|
41
|
+
const fetchMocker = createFetchMock(vi)
|
|
42
|
+
const i1: Item = { baseId: 'id1', base: { id: 'id1', synchronized_type: 'type' } }
|
|
43
|
+
const i2: Item = { baseId: 'id2', base: { id: 'id2', synchronized_type: 'type' } }
|
|
44
|
+
fetchMocker.mockResponseOnce(
|
|
45
|
+
'id1\t' + JSON.stringify(i1.base) + '\nid2\t' + JSON.stringify(i2.base) + '\n'
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
const gathered = new AsyncGeneratorQueue<Item>()
|
|
49
|
+
const downloader = new ServerDownloader({
|
|
50
|
+
serverUrl: 'http://synchronized.test',
|
|
51
|
+
streamId: 'streamId',
|
|
52
|
+
objectId: 'objectId',
|
|
53
|
+
token: 'token',
|
|
54
|
+
|
|
55
|
+
fetch: fetchMocker,
|
|
56
|
+
logger: (): void => {}
|
|
57
|
+
})
|
|
58
|
+
downloader.initialize({
|
|
59
|
+
results: gathered,
|
|
60
|
+
total: 2,
|
|
61
|
+
maxDownloadBatchWait: 200
|
|
62
|
+
})
|
|
63
|
+
downloader.add('id1')
|
|
64
|
+
downloader.add('id2')
|
|
65
|
+
await downloader.disposeAsync()
|
|
66
|
+
const r = []
|
|
67
|
+
for await (const x of gathered.consume()) {
|
|
68
|
+
r.push(x)
|
|
69
|
+
if (r.length >= 2) {
|
|
70
|
+
break
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
expect(r).toMatchSnapshot()
|
|
75
|
+
await downloader.disposeAsync()
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('download batch of three', async () => {
|
|
79
|
+
const fetchMocker = createFetchMock(vi)
|
|
80
|
+
const i1: Item = { baseId: 'id1', base: { id: 'id1', synchronized_type: 'type' } }
|
|
81
|
+
const i2: Item = { baseId: 'id2', base: { id: 'id2', synchronized_type: 'type' } }
|
|
82
|
+
const i3: Item = { baseId: 'id3', base: { id: 'id3', synchronized_type: 'type' } }
|
|
83
|
+
fetchMocker.mockResponseOnce(
|
|
84
|
+
'id1\t' +
|
|
85
|
+
JSON.stringify(i1.base) +
|
|
86
|
+
'\nid2\t' +
|
|
87
|
+
JSON.stringify(i2.base) +
|
|
88
|
+
'\nid3\t' +
|
|
89
|
+
JSON.stringify(i3.base) +
|
|
90
|
+
'\n'
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
const gathered = new AsyncGeneratorQueue<Item>()
|
|
94
|
+
const downloader = new ServerDownloader({
|
|
95
|
+
serverUrl: 'http://synchronized.test',
|
|
96
|
+
streamId: 'streamId',
|
|
97
|
+
objectId: 'objectId',
|
|
98
|
+
token: 'token',
|
|
99
|
+
|
|
100
|
+
fetch: fetchMocker,
|
|
101
|
+
logger: (): void => {}
|
|
102
|
+
})
|
|
103
|
+
downloader.initialize({
|
|
104
|
+
results: gathered,
|
|
105
|
+
total: 3,
|
|
106
|
+
maxDownloadBatchWait: 200
|
|
107
|
+
})
|
|
108
|
+
downloader.add('id1')
|
|
109
|
+
downloader.add('id2')
|
|
110
|
+
downloader.add('id3')
|
|
111
|
+
await downloader.disposeAsync()
|
|
112
|
+
const r = []
|
|
113
|
+
for await (const x of gathered.consume()) {
|
|
114
|
+
r.push(x)
|
|
115
|
+
if (r.length >= 3) {
|
|
116
|
+
break
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
expect(r).toMatchSnapshot()
|
|
121
|
+
await downloader.disposeAsync()
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
test('download batch of three with Objects.Other.RawEncoding', async () => {
|
|
125
|
+
const fetchMocker = createFetchMock(vi)
|
|
126
|
+
const i1: Item = { baseId: 'id1', base: { id: 'id1', synchronized_type: 'type' } }
|
|
127
|
+
const i2: Item = {
|
|
128
|
+
baseId: 'id2',
|
|
129
|
+
base: { id: 'id2', synchronized_type: 'Objects.Other.RawEncoding' }
|
|
130
|
+
}
|
|
131
|
+
const i3: Item = { baseId: 'id3', base: { id: 'id3', synchronized_type: 'type' } }
|
|
132
|
+
fetchMocker.mockResponseOnce(
|
|
133
|
+
'id1\t' +
|
|
134
|
+
JSON.stringify(i1.base) +
|
|
135
|
+
'\nid2\t' +
|
|
136
|
+
JSON.stringify(i2.base) +
|
|
137
|
+
'\nid3\t' +
|
|
138
|
+
JSON.stringify(i3.base) +
|
|
139
|
+
'\n'
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
const gathered = new AsyncGeneratorQueue<Item>()
|
|
143
|
+
const downloader = new ServerDownloader({
|
|
144
|
+
serverUrl: 'http://synchronized.test',
|
|
145
|
+
streamId: 'streamId',
|
|
146
|
+
objectId: 'objectId',
|
|
147
|
+
token: 'token',
|
|
148
|
+
|
|
149
|
+
fetch: fetchMocker,
|
|
150
|
+
logger: (): void => {}
|
|
151
|
+
})
|
|
152
|
+
downloader.initialize({
|
|
153
|
+
results: gathered,
|
|
154
|
+
total: 3,
|
|
155
|
+
maxDownloadBatchWait: 200
|
|
156
|
+
})
|
|
157
|
+
downloader.add('id1')
|
|
158
|
+
downloader.add('id2')
|
|
159
|
+
downloader.add('id3')
|
|
160
|
+
await downloader.disposeAsync()
|
|
161
|
+
const r = []
|
|
162
|
+
for await (const x of gathered.consume()) {
|
|
163
|
+
r.push(x)
|
|
164
|
+
if (r.length >= 3) {
|
|
165
|
+
break
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
expect(r).toMatchSnapshot()
|
|
170
|
+
await downloader.disposeAsync()
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
test("download Objects.Other.RawEncoding doesn't exist", async () => {
|
|
174
|
+
const fetchMocker = createFetchMock(vi)
|
|
175
|
+
const i: Item = {
|
|
176
|
+
baseId: 'id',
|
|
177
|
+
base: {
|
|
178
|
+
id: 'id',
|
|
179
|
+
synchronized_type: 'Objects.Other.RawEncoding',
|
|
180
|
+
__closure: { childIds: 1 }
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
fetchMocker.mockResponseOnce(JSON.stringify(i.base))
|
|
184
|
+
const downloader = new ServerDownloader({
|
|
185
|
+
serverUrl: 'http://synchronized.test',
|
|
186
|
+
streamId: 'streamId',
|
|
187
|
+
objectId: i.baseId,
|
|
188
|
+
token: 'token',
|
|
189
|
+
|
|
190
|
+
fetch: fetchMocker,
|
|
191
|
+
logger: (): void => {}
|
|
192
|
+
})
|
|
193
|
+
await expect(downloader.downloadSingle()).rejects.toThrow()
|
|
194
|
+
await downloader.disposeAsync()
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
test('download single exists', async () => {
|
|
198
|
+
const fetchMocker = createFetchMock(vi)
|
|
199
|
+
const i: Item = {
|
|
200
|
+
baseId: 'id',
|
|
201
|
+
base: { id: 'id', synchronized_type: 'type', __closure: { childIds: 1 } }
|
|
202
|
+
}
|
|
203
|
+
fetchMocker.mockResponseOnce(JSON.stringify(i.base))
|
|
204
|
+
const downloader = new ServerDownloader({
|
|
205
|
+
serverUrl: 'http://synchronized.test',
|
|
206
|
+
streamId: 'streamId',
|
|
207
|
+
objectId: i.baseId,
|
|
208
|
+
token: 'token',
|
|
209
|
+
|
|
210
|
+
fetch: fetchMocker,
|
|
211
|
+
logger: (): void => {}
|
|
212
|
+
})
|
|
213
|
+
const x = await downloader.downloadSingle()
|
|
214
|
+
expect(x).toMatchSnapshot()
|
|
215
|
+
await downloader.disposeAsync()
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
test('add extra header', async () => {
|
|
219
|
+
const fetchMocker = createFetchMock(vi)
|
|
220
|
+
const i: Item = {
|
|
221
|
+
baseId: 'id',
|
|
222
|
+
base: { id: 'id', synchronized_type: 'type', __closure: { childIds: 1 } }
|
|
223
|
+
}
|
|
224
|
+
fetchMocker.mockResponseIf(
|
|
225
|
+
(req) => req.headers.get('x-test') === 'asdf',
|
|
226
|
+
JSON.stringify(i.base)
|
|
227
|
+
)
|
|
228
|
+
const headers = new Headers()
|
|
229
|
+
headers.set('x-test', 'asdf')
|
|
230
|
+
const downloader = new ServerDownloader({
|
|
231
|
+
serverUrl: 'http://synchronized.test',
|
|
232
|
+
headers,
|
|
233
|
+
streamId: 'streamId',
|
|
234
|
+
objectId: i.baseId,
|
|
235
|
+
token: 'token',
|
|
236
|
+
|
|
237
|
+
fetch: fetchMocker,
|
|
238
|
+
logger: (): void => {}
|
|
239
|
+
})
|
|
240
|
+
const x = await downloader.downloadSingle()
|
|
241
|
+
expect(x).toMatchSnapshot()
|
|
242
|
+
await downloader.disposeAsync()
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
test('can dispose used', async () => {
|
|
246
|
+
const fetchMocker = createFetchMock(vi)
|
|
247
|
+
const headers = new Headers()
|
|
248
|
+
const downloader = new ServerDownloader({
|
|
249
|
+
serverUrl: 'http://synchronized.test',
|
|
250
|
+
headers,
|
|
251
|
+
streamId: 'streamId',
|
|
252
|
+
objectId: 'objectId',
|
|
253
|
+
token: 'token',
|
|
254
|
+
|
|
255
|
+
fetch: fetchMocker,
|
|
256
|
+
logger: (): void => {}
|
|
257
|
+
})
|
|
258
|
+
await downloader.disposeAsync()
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
test('nothing is frozen when validateResponse returns 403', async () => {
|
|
262
|
+
const fetchMocker = createFetchMock(vi)
|
|
263
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
264
|
+
|
|
265
|
+
// Mock a 403 Forbidden response
|
|
266
|
+
fetchMocker.mockResponseOnce('', { status: 403, statusText: 'Forbidden' })
|
|
267
|
+
|
|
268
|
+
const gathered = new AsyncGeneratorQueue<Item>()
|
|
269
|
+
const downloader = new ServerDownloader({
|
|
270
|
+
serverUrl: 'http://synchronized.test',
|
|
271
|
+
streamId: 'streamId',
|
|
272
|
+
objectId: 'objectId',
|
|
273
|
+
token: 'invalid-token',
|
|
274
|
+
fetch: fetchMocker,
|
|
275
|
+
logger: (): void => {}
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
downloader.initialize({
|
|
280
|
+
results: gathered,
|
|
281
|
+
total: 2,
|
|
282
|
+
maxDownloadBatchWait: 100
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
// Add items to trigger batch processing
|
|
286
|
+
downloader.add('id1')
|
|
287
|
+
downloader.add('id2')
|
|
288
|
+
|
|
289
|
+
// Wait for the batch to be processed and fail with 403
|
|
290
|
+
await new Promise((resolve) => setTimeout(resolve, 200))
|
|
291
|
+
|
|
292
|
+
// Verify that the error was logged (indicating the batch processing failed)
|
|
293
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
294
|
+
'Batch processing failed:',
|
|
295
|
+
expect.any(Error)
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
// The key test: verify we can still dispose the downloader properly
|
|
299
|
+
// This ensures the system isn't frozen and can clean up resources
|
|
300
|
+
const disposePromise = downloader.disposeAsync()
|
|
301
|
+
|
|
302
|
+
// Add a timeout to ensure disposal doesn't hang indefinitely
|
|
303
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
304
|
+
setTimeout(() => reject(new Error('Disposal timed out')), 5000)
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
// This should complete without timing out or throwing
|
|
308
|
+
await Promise.race([disposePromise, timeoutPromise])
|
|
309
|
+
|
|
310
|
+
// Additional verification: the batching queue should be marked as disposed
|
|
311
|
+
// We can't directly access the private field, but we can verify disposal completed
|
|
312
|
+
expect(true).toBe(true) // If we reach here, disposal succeeded
|
|
313
|
+
} finally {
|
|
314
|
+
consoleErrorSpy.mockRestore()
|
|
315
|
+
}
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
test('system remains functional after 403 error and can be properly cleaned up', async () => {
|
|
319
|
+
const fetchMocker = createFetchMock(vi)
|
|
320
|
+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
321
|
+
|
|
322
|
+
// First call returns 403, subsequent calls should not be made due to queue disposal
|
|
323
|
+
fetchMocker.mockResponseOnce('', { status: 403, statusText: 'Forbidden' })
|
|
324
|
+
|
|
325
|
+
const gathered = new AsyncGeneratorQueue<Item>()
|
|
326
|
+
const downloader = new ServerDownloader({
|
|
327
|
+
serverUrl: 'http://synchronized.test',
|
|
328
|
+
streamId: 'streamId',
|
|
329
|
+
objectId: 'objectId',
|
|
330
|
+
token: 'invalid-token',
|
|
331
|
+
fetch: fetchMocker,
|
|
332
|
+
logger: (): void => {}
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
try {
|
|
336
|
+
downloader.initialize({
|
|
337
|
+
results: gathered,
|
|
338
|
+
total: 5,
|
|
339
|
+
maxDownloadBatchWait: 50
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
// Add first batch that will trigger the 403 error
|
|
343
|
+
downloader.add('id1')
|
|
344
|
+
downloader.add('id2')
|
|
345
|
+
|
|
346
|
+
// Wait for first batch to fail
|
|
347
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
348
|
+
|
|
349
|
+
// Verify error was logged
|
|
350
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
351
|
+
'Batch processing failed:',
|
|
352
|
+
expect.any(Error)
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
// Try to add more items after the failure
|
|
356
|
+
// These should be ignored since the queue is now disposed
|
|
357
|
+
downloader.add('id3')
|
|
358
|
+
downloader.add('id4')
|
|
359
|
+
downloader.add('id5')
|
|
360
|
+
|
|
361
|
+
// Wait a bit more to ensure no additional processing attempts
|
|
362
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
363
|
+
|
|
364
|
+
// Note: The batching queue might make multiple attempts before disposal
|
|
365
|
+
// The key is that disposal should still work regardless of how many calls were made
|
|
366
|
+
expect(fetchMocker).toHaveBeenCalled()
|
|
367
|
+
|
|
368
|
+
// Critical test: disposal should complete without hanging
|
|
369
|
+
const start = Date.now()
|
|
370
|
+
await downloader.disposeAsync()
|
|
371
|
+
const elapsed = Date.now() - start
|
|
372
|
+
|
|
373
|
+
// Disposal should be quick (under 1 second) and not hang
|
|
374
|
+
expect(elapsed).toBeLessThan(1000)
|
|
375
|
+
|
|
376
|
+
// Verify that the results queue can also be disposed properly
|
|
377
|
+
await gathered.disposeAsync()
|
|
378
|
+
} finally {
|
|
379
|
+
consoleErrorSpy.mockRestore()
|
|
380
|
+
}
|
|
381
|
+
})
|
|
382
|
+
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Queue from '../../
|
|
1
|
+
import BatchingQueue from '../../queues/batchingQueue.js'
|
|
2
|
+
import Queue from '../../queues/queue.js'
|
|
3
3
|
import { ObjectLoaderRuntimeError } from '../../types/errors.js'
|
|
4
|
-
import { Fetcher,
|
|
4
|
+
import { CustomLogger, Fetcher, indexOf, isBase, take } from '../../types/functions.js'
|
|
5
|
+
import { Item, ObjectAttributeMask } from '../../types/types.js'
|
|
5
6
|
import { Downloader } from '../interfaces.js'
|
|
6
7
|
|
|
7
8
|
export interface ServerDownloaderOptions {
|
|
@@ -10,9 +11,14 @@ export interface ServerDownloaderOptions {
|
|
|
10
11
|
objectId: string
|
|
11
12
|
token?: string
|
|
12
13
|
headers?: Headers
|
|
14
|
+
logger: CustomLogger
|
|
13
15
|
fetch?: Fetcher
|
|
16
|
+
attributeMask?: ObjectAttributeMask
|
|
17
|
+
objectTypeMask?: string[] // Temporary until server filters are elevated and ready
|
|
14
18
|
}
|
|
15
19
|
|
|
20
|
+
const MAX_SAFARI_DECODE_BYTES = 2 * 1024 * 1024 * 1024 - 1024 * 1024 // 2GB minus a margin
|
|
21
|
+
|
|
16
22
|
export default class ServerDownloader implements Downloader {
|
|
17
23
|
#requestUrlRootObj: string
|
|
18
24
|
#requestUrlChildren: string
|
|
@@ -20,12 +26,19 @@ export default class ServerDownloader implements Downloader {
|
|
|
20
26
|
#options: ServerDownloaderOptions
|
|
21
27
|
#fetch: Fetcher
|
|
22
28
|
#results?: Queue<Item>
|
|
29
|
+
#total?: number
|
|
30
|
+
#logger: CustomLogger
|
|
31
|
+
|
|
32
|
+
#downloadQueue?: BatchingQueue<string>
|
|
33
|
+
#decoder = new TextDecoder('utf-8', { fatal: true })
|
|
34
|
+
#decodedBytesCount = 0
|
|
23
35
|
|
|
24
|
-
#
|
|
25
|
-
#
|
|
36
|
+
#rawStrings: Array<string> = []
|
|
37
|
+
#rawEncodings: Array<Uint8Array> = []
|
|
26
38
|
|
|
27
39
|
constructor(options: ServerDownloaderOptions) {
|
|
28
40
|
this.#options = options
|
|
41
|
+
this.#logger = options.logger
|
|
29
42
|
this.#fetch =
|
|
30
43
|
options.fetch ?? ((...args): Promise<Response> => globalThis.fetch(...args))
|
|
31
44
|
|
|
@@ -40,32 +53,34 @@ export default class ServerDownloader implements Downloader {
|
|
|
40
53
|
if (this.#options.token) {
|
|
41
54
|
this.#headers['Authorization'] = `Bearer ${this.#options.token}`
|
|
42
55
|
}
|
|
43
|
-
this.#requestUrlChildren = `${this.#options.serverUrl}/api/
|
|
56
|
+
this.#requestUrlChildren = `${this.#options.serverUrl}/api/v2/projects/${
|
|
44
57
|
this.#options.streamId
|
|
45
|
-
}
|
|
58
|
+
}/object-stream/`
|
|
59
|
+
|
|
46
60
|
this.#requestUrlRootObj = `${this.#options.serverUrl}/objects/${
|
|
47
61
|
this.#options.streamId
|
|
48
62
|
}/${this.#options.objectId}/single`
|
|
49
|
-
}
|
|
50
63
|
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
|
|
64
|
+
const encoder = new TextEncoder()
|
|
65
|
+
if (options.objectTypeMask) {
|
|
66
|
+
this.#rawStrings.push(...options.objectTypeMask)
|
|
67
|
+
this.#rawEncodings.push(
|
|
68
|
+
...options.objectTypeMask.map((val) => encoder.encode(val))
|
|
69
|
+
)
|
|
54
70
|
}
|
|
55
|
-
|
|
56
|
-
return [10000, 25000, 10000, 1000]
|
|
57
71
|
}
|
|
58
72
|
|
|
59
|
-
|
|
73
|
+
initialize(params: {
|
|
60
74
|
results: Queue<Item>
|
|
61
75
|
total: number
|
|
62
76
|
maxDownloadBatchWait?: number
|
|
63
77
|
}): void {
|
|
64
|
-
const { results, total } = params
|
|
78
|
+
const { results, total, maxDownloadBatchWait } = params
|
|
65
79
|
this.#results = results
|
|
66
|
-
this.#
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
this.#total = total
|
|
81
|
+
this.#downloadQueue = new BatchingQueue<string>({
|
|
82
|
+
batchSize: 15000, // 15k is a good number for most cases
|
|
83
|
+
maxWaitTime: maxDownloadBatchWait ?? 1000, // 1 second
|
|
69
84
|
processFunction: (batch: string[]): Promise<void> =>
|
|
70
85
|
this.downloadBatch({
|
|
71
86
|
batch,
|
|
@@ -75,46 +90,47 @@ export default class ServerDownloader implements Downloader {
|
|
|
75
90
|
})
|
|
76
91
|
}
|
|
77
92
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return this.#downloadQueue
|
|
81
|
-
}
|
|
82
|
-
throw new Error('Download pool is not initialized')
|
|
93
|
+
add(id: string): void {
|
|
94
|
+
this.#downloadQueue?.add(id, id)
|
|
83
95
|
}
|
|
84
96
|
|
|
85
|
-
|
|
86
|
-
|
|
97
|
+
/*
|
|
98
|
+
This is the most frequently reported and confirmed reason for this error in Safari. There's a known bug in WebKit (Safari's rendering engine) where TextDecoder can fail or throw a RangeError after decoding around 2GB of data. Chrome and other browsers handle much larger amounts of data without this specific limitation.
|
|
99
|
+
|
|
100
|
+
Why it happens: It seems to be an internal memory or indexing limitation within Safari's TextDecoder implementation. After a certain threshold of data has been processed by a TextDecoder instance, it starts throwing this error.
|
|
101
|
+
|
|
102
|
+
Chrome's behavior: Chrome generally handles larger data sizes without this specific RangeError. It might become slow or run out of general memory, but not typically with this specific error.
|
|
103
|
+
*/
|
|
104
|
+
decodeChunk(chunkBuffer: Uint8Array): string {
|
|
105
|
+
if (this.#decodedBytesCount + chunkBuffer.byteLength > MAX_SAFARI_DECODE_BYTES) {
|
|
106
|
+
// Safari is approaching its limit, create a new decoder
|
|
107
|
+
this.#decoder = new TextDecoder('utf-8', { fatal: true })
|
|
108
|
+
this.#decodedBytesCount = 0 // Reset counter for the new decoder
|
|
109
|
+
}
|
|
110
|
+
const decodedText = this.#decoder.decode(chunkBuffer)
|
|
111
|
+
this.#decodedBytesCount += chunkBuffer.byteLength
|
|
112
|
+
return decodedText
|
|
87
113
|
}
|
|
88
114
|
|
|
89
115
|
async disposeAsync(): Promise<void> {
|
|
90
116
|
await this.#downloadQueue?.disposeAsync()
|
|
91
117
|
}
|
|
92
118
|
|
|
93
|
-
#processJson(baseId: string, unparsedBase: string): Item {
|
|
94
|
-
let base: unknown
|
|
95
|
-
try {
|
|
96
|
-
base = JSON.parse(unparsedBase)
|
|
97
|
-
} catch (e: unknown) {
|
|
98
|
-
throw new Error(`Error parsing object ${baseId}: ${(e as Error).message}`)
|
|
99
|
-
}
|
|
100
|
-
if (isBase(base)) {
|
|
101
|
-
return { baseId, base }
|
|
102
|
-
} else {
|
|
103
|
-
throw new ObjectLoaderRuntimeError(`${baseId} is not a base`)
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
119
|
async downloadBatch(params: {
|
|
108
120
|
batch: string[]
|
|
109
121
|
url: string
|
|
110
122
|
headers: HeadersInit
|
|
111
123
|
}): Promise<void> {
|
|
112
124
|
const { batch, url, headers } = params
|
|
125
|
+
|
|
126
|
+
const start = performance.now()
|
|
127
|
+
this.#logger(`Downloading batch of ${batch.length} items...`)
|
|
128
|
+
const attributeMask = this.#options.attributeMask
|
|
113
129
|
const keys = new Set<string>(batch)
|
|
114
130
|
const response = await this.#fetch(url, {
|
|
115
131
|
method: 'POST',
|
|
116
132
|
headers: { ...headers, 'Content-Type': 'application/json' },
|
|
117
|
-
body: JSON.stringify({
|
|
133
|
+
body: JSON.stringify({ objectIds: batch, attributeMask })
|
|
118
134
|
})
|
|
119
135
|
|
|
120
136
|
this.#validateResponse(response)
|
|
@@ -130,7 +146,7 @@ export default class ServerDownloader implements Downloader {
|
|
|
130
146
|
const { done, value } = await reader.read()
|
|
131
147
|
if (done) break
|
|
132
148
|
|
|
133
|
-
leftover = await this
|
|
149
|
+
leftover = await this.#processArray(leftover, value, keys, async () => {
|
|
134
150
|
count++
|
|
135
151
|
if (count % 1000 === 0) {
|
|
136
152
|
await new Promise((resolve) => setTimeout(resolve, 100)) //allow other stuff to happen
|
|
@@ -142,16 +158,23 @@ export default class ServerDownloader implements Downloader {
|
|
|
142
158
|
'Items requested were not downloaded: ' + take(keys.values(), 10).join(',')
|
|
143
159
|
)
|
|
144
160
|
}
|
|
161
|
+
count += keys.size // count the leftovers
|
|
162
|
+
if (count >= this.#total!) {
|
|
163
|
+
await this.#results?.disposeAsync() // mark the queue as done
|
|
164
|
+
}
|
|
165
|
+
this.#logger(
|
|
166
|
+
`Downloaded batch of ${batch.length} items in ${performance.now() - start}ms`
|
|
167
|
+
)
|
|
145
168
|
}
|
|
146
169
|
|
|
147
|
-
async processArray(
|
|
170
|
+
async #processArray(
|
|
148
171
|
leftover: Uint8Array,
|
|
149
172
|
value: Uint8Array,
|
|
150
173
|
keys: Set<string>,
|
|
151
174
|
callback: () => Promise<void>
|
|
152
175
|
): Promise<Uint8Array> {
|
|
153
176
|
//this concat will allocate a new array
|
|
154
|
-
const combined = this
|
|
177
|
+
const combined = this.#concatUint8Arrays(leftover, value)
|
|
155
178
|
let start = 0
|
|
156
179
|
|
|
157
180
|
//subarray doesn't allocate
|
|
@@ -159,34 +182,68 @@ export default class ServerDownloader implements Downloader {
|
|
|
159
182
|
if (combined[i] === 0x0a) {
|
|
160
183
|
const line = combined.subarray(start, i) // line without \n
|
|
161
184
|
//strings are allocated here
|
|
162
|
-
const item = this
|
|
163
|
-
this.#results?.add(item)
|
|
185
|
+
const item = this.#processLine(line)
|
|
164
186
|
start = i + 1
|
|
165
187
|
await callback()
|
|
166
188
|
keys.delete(item.baseId)
|
|
189
|
+
this.#results?.add(item)
|
|
167
190
|
}
|
|
168
191
|
}
|
|
169
192
|
return combined.subarray(start) // carry over remainder
|
|
170
193
|
}
|
|
171
194
|
|
|
172
|
-
processLine(line: Uint8Array): Item {
|
|
195
|
+
#processLine(line: Uint8Array): Item {
|
|
173
196
|
for (let i = 0; i < line.length; i++) {
|
|
174
197
|
if (line[i] === 0x09) {
|
|
175
198
|
//this is a tab
|
|
176
|
-
const baseId = this
|
|
177
|
-
const
|
|
178
|
-
|
|
199
|
+
const baseId = this.decodeChunk(line.subarray(0, i))
|
|
200
|
+
const jsonBytes = line.subarray(i + 1)
|
|
201
|
+
|
|
202
|
+
if (!this.#isValidBytes(jsonBytes)) {
|
|
203
|
+
return { baseId, base: undefined }
|
|
204
|
+
}
|
|
205
|
+
const base = this.decodeChunk(jsonBytes)
|
|
179
206
|
const item = this.#processJson(baseId, base)
|
|
180
|
-
item.size =
|
|
207
|
+
item.size = jsonBytes.length
|
|
181
208
|
return item
|
|
182
209
|
}
|
|
183
210
|
}
|
|
184
211
|
throw new ObjectLoaderRuntimeError(
|
|
185
|
-
'Invalid line format: ' + this
|
|
212
|
+
'Invalid line format in response: ' + this.decodeChunk(line)
|
|
186
213
|
)
|
|
187
214
|
}
|
|
188
215
|
|
|
189
|
-
|
|
216
|
+
#processJson(baseId: string, unparsedBase: string): Item {
|
|
217
|
+
let base: unknown
|
|
218
|
+
try {
|
|
219
|
+
base = JSON.parse(unparsedBase)
|
|
220
|
+
} catch (e: unknown) {
|
|
221
|
+
throw new Error(`Error parsing object ${baseId}: ${(e as Error).message}`)
|
|
222
|
+
}
|
|
223
|
+
if (isBase(base)) {
|
|
224
|
+
return { baseId, base }
|
|
225
|
+
} else {
|
|
226
|
+
throw new ObjectLoaderRuntimeError(`${baseId} is not a base`)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
#isValidString(json: string): boolean {
|
|
231
|
+
for (const rawString of this.#rawStrings)
|
|
232
|
+
if (json.includes(rawString)) {
|
|
233
|
+
return false
|
|
234
|
+
}
|
|
235
|
+
return true
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
#isValidBytes(json: Uint8Array): boolean {
|
|
239
|
+
for (const rawEncoding of this.#rawEncodings)
|
|
240
|
+
if (indexOf(json, rawEncoding) !== -1) {
|
|
241
|
+
return false
|
|
242
|
+
}
|
|
243
|
+
return true
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
#concatUint8Arrays(a: Uint8Array, b: Uint8Array): Uint8Array {
|
|
190
247
|
const c = new Uint8Array(a.length + b.length)
|
|
191
248
|
c.set(a, 0)
|
|
192
249
|
c.set(b, a.length)
|
|
@@ -199,7 +256,13 @@ export default class ServerDownloader implements Downloader {
|
|
|
199
256
|
})
|
|
200
257
|
this.#validateResponse(response)
|
|
201
258
|
const responseText = await response.text()
|
|
259
|
+
if (!this.#isValidString(responseText)) {
|
|
260
|
+
throw new ObjectLoaderRuntimeError('Invalid base object')
|
|
261
|
+
}
|
|
202
262
|
const item = this.#processJson(this.#options.objectId, responseText)
|
|
263
|
+
if (!item.base) {
|
|
264
|
+
throw new ObjectLoaderRuntimeError('Invalid base object')
|
|
265
|
+
}
|
|
203
266
|
item.size = 0
|
|
204
267
|
return item
|
|
205
268
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isScalar, isBase, isReference } from '../types/functions.js'
|
|
2
|
+
import { Base, DataChunk } from '../types/types.js'
|
|
2
3
|
import { ObjectLoader2 } from './objectLoader2.js'
|
|
3
4
|
|
|
4
5
|
export type ProgressStage = 'download' | 'construction'
|