(OL2) move files around to make more sense (#4950)
* Rename to saveBatch * forgot a file * first pass of cacheReader * OL2 tests have infinite timeout * OL2 refactor works * fix for tests * moved/removed types to make a more logical structure * fixed imports * rework loop to be in async generator for the expected count * get rid of pumps and fix test * lint fix * redo mermaid diagrams * add readme section on deferment * always return root first * fix linting * revert the counting * merge fixes * remove unused var
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
import Queue from '../helpers/queue.js'
|
||||
import Queue from '../queues/queue.js'
|
||||
import { Item } from '../types/types.js'
|
||||
|
||||
export interface Downloader extends Queue<string> {
|
||||
+14
-5
@@ -1,10 +1,10 @@
|
||||
import { describe, expect, test } from 'vitest'
|
||||
import { ObjectLoader2 } from './objectLoader2.js'
|
||||
import { describe, test, expect } from 'vitest'
|
||||
import { Base, Item } from '../types/types.js'
|
||||
import { MemoryDownloader } from './downloaders/memoryDownloader.js'
|
||||
import { ObjectLoader2 } from './objectLoader2.js'
|
||||
import IndexedDatabase from './stages/indexedDatabase.js'
|
||||
import { IDBFactory, IDBKeyRange } from 'fake-indexeddb'
|
||||
import { MemoryDatabase } from './databases/memoryDatabase.js'
|
||||
import IndexedDatabase from './databases/indexedDatabase.js'
|
||||
import { MemoryDatabase } from './stages/memory/memoryDatabase.js'
|
||||
import { MemoryDownloader } from './stages/memory/memoryDownloader.js'
|
||||
|
||||
describe('objectloader2', () => {
|
||||
test('can get a root object from cache', async () => {
|
||||
@@ -66,6 +66,9 @@ describe('objectloader2', () => {
|
||||
const r = []
|
||||
for await (const x of loader.getObjectIterator()) {
|
||||
r.push(x)
|
||||
if (r.length >= 1) {
|
||||
break
|
||||
}
|
||||
}
|
||||
await loader.disposeAsync()
|
||||
|
||||
@@ -101,6 +104,9 @@ describe('objectloader2', () => {
|
||||
const obj = loader.getObject({ id: child1.baseId })
|
||||
for await (const x of loader.getObjectIterator()) {
|
||||
r.push(x)
|
||||
if (r.length >= 2) {
|
||||
break
|
||||
}
|
||||
}
|
||||
await loader.disposeAsync()
|
||||
|
||||
@@ -139,6 +145,9 @@ describe('objectloader2', () => {
|
||||
const obj = loader.getObject({ id: child1.baseId })
|
||||
for await (const x of loader.getObjectIterator()) {
|
||||
r.push(x)
|
||||
if (r.length >= 2) {
|
||||
break
|
||||
}
|
||||
}
|
||||
await loader.disposeAsync()
|
||||
|
||||
+11
-10
@@ -1,12 +1,13 @@
|
||||
import AsyncGeneratorQueue from '../helpers/asyncGeneratorQueue.js'
|
||||
import { Downloader, Database } from './interfaces.js'
|
||||
import { CustomLogger, Base, Item } from '../types/types.js'
|
||||
import { CacheOptions, ObjectLoader2Options } from './options.js'
|
||||
import { DefermentManager } from '../helpers/defermentManager.js'
|
||||
import { CacheReader } from '../helpers/cacheReader.js'
|
||||
import AggregateQueue from '../helpers/aggregateQueue.js'
|
||||
import { DefermentManager } from '../deferment/defermentManager.js'
|
||||
import AggregateQueue from '../queues/aggregateQueue.js'
|
||||
import AsyncGeneratorQueue from '../queues/asyncGeneratorQueue.js'
|
||||
import { CustomLogger } from '../types/functions.js'
|
||||
import { Item, Base } from '../types/types.js'
|
||||
import { Database, Downloader } from './interfaces.js'
|
||||
import { ObjectLoader2Factory } from './objectLoader2Factory.js'
|
||||
import { CacheWriter } from '../helpers/cacheWriter.js'
|
||||
import { ObjectLoader2Options, CacheOptions } from './options.js'
|
||||
import { CacheReader } from './stages/cacheReader.js'
|
||||
import { CacheWriter } from './stages/cacheWriter.js'
|
||||
|
||||
export class ObjectLoader2 {
|
||||
#rootId: string
|
||||
@@ -52,8 +53,8 @@ export class ObjectLoader2 {
|
||||
}
|
||||
|
||||
async disposeAsync(): Promise<void> {
|
||||
this.#gathered.dispose()
|
||||
await Promise.all([
|
||||
this.#gathered.disposeAsync(),
|
||||
this.#downloader.disposeAsync(),
|
||||
this.#cacheReader.disposeAsync(),
|
||||
this.#cacheWriter.disposeAsync()
|
||||
@@ -93,7 +94,7 @@ export class ObjectLoader2 {
|
||||
}
|
||||
|
||||
//sort the closures by their values descending
|
||||
const sortedClosures = Object.entries(rootItem.base.__closure).sort(
|
||||
const sortedClosures = Object.entries(rootItem.base.__closure ?? []).sort(
|
||||
(a, b) => b[1] - a[1]
|
||||
)
|
||||
const children = sortedClosures.map((x) => x[0])
|
||||
+6
-5
@@ -1,9 +1,10 @@
|
||||
import { Base, CustomLogger } from '../types/types.js'
|
||||
import IndexedDatabase from './databases/indexedDatabase.js'
|
||||
import { MemoryDatabase } from './databases/memoryDatabase.js'
|
||||
import { MemoryDownloader } from './downloaders/memoryDownloader.js'
|
||||
import ServerDownloader from './downloaders/serverDownloader.js'
|
||||
import { CustomLogger } from '../types/functions.js'
|
||||
import { Base } from '../types/types.js'
|
||||
import { ObjectLoader2 } from './objectLoader2.js'
|
||||
import IndexedDatabase from './stages/indexedDatabase.js'
|
||||
import { MemoryDatabase } from './stages/memory/memoryDatabase.js'
|
||||
import { MemoryDownloader } from './stages/memory/memoryDownloader.js'
|
||||
import ServerDownloader from './stages/serverDownloader.js'
|
||||
|
||||
export interface ObjectLoader2FactoryOptions {
|
||||
useMemoryCache?: boolean
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
import { Base, CustomLogger } from '../types/types.js'
|
||||
import { CustomLogger } from '../types/functions.js'
|
||||
import { Base } from '../types/types.js'
|
||||
import { Downloader, Database } from './interfaces.js'
|
||||
|
||||
export interface ObjectLoader2Options {
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
import { describe, expect, test } from 'vitest'
|
||||
import { Base, Item } from '../types/types.js'
|
||||
import { DefermentManager } from './defermentManager.js'
|
||||
import { describe, test, expect } from 'vitest'
|
||||
import { DefermentManager } from '../../deferment/defermentManager.js'
|
||||
import { Item, Base } from '../../types/types.js'
|
||||
import { CacheReader } from './cacheReader.js'
|
||||
import { MemoryDatabase } from '../operations/databases/memoryDatabase.js'
|
||||
import { MemoryDatabase } from './memory/memoryDatabase.js'
|
||||
|
||||
describe('CacheReader testing', () => {
|
||||
test('deferred getObject', async () => {
|
||||
+7
-6
@@ -1,9 +1,10 @@
|
||||
import { Database } from '../operations/interfaces.js'
|
||||
import { CacheOptions } from '../operations/options.js'
|
||||
import { Base, CustomLogger, Item } from '../types/types.js'
|
||||
import BatchingQueue from './batchingQueue.js'
|
||||
import { DefermentManager } from './defermentManager.js'
|
||||
import Queue from './queue.js'
|
||||
import { DefermentManager } from '../../deferment/defermentManager.js'
|
||||
import BatchingQueue from '../../queues/batchingQueue.js'
|
||||
import Queue from '../../queues/queue.js'
|
||||
import { CustomLogger } from '../../types/functions.js'
|
||||
import { Item, Base } from '../../types/types.js'
|
||||
import { Database } from '../interfaces.js'
|
||||
import { CacheOptions } from '../options.js'
|
||||
|
||||
export class CacheReader {
|
||||
#database: Database
|
||||
@@ -0,0 +1,49 @@
|
||||
import { DefermentManager } from '../../deferment/defermentManager.js'
|
||||
import BatchingQueue from '../../queues/batchingQueue.js'
|
||||
import Queue from '../../queues/queue.js'
|
||||
import { CustomLogger } from '../../types/functions.js'
|
||||
import { Item } from '../../types/types.js'
|
||||
import { Database } from '../interfaces.js'
|
||||
import { CacheOptions } from '../options.js'
|
||||
|
||||
export class CacheWriter implements Queue<Item> {
|
||||
#writeQueue: BatchingQueue<Item> | undefined
|
||||
#database: Database
|
||||
#defermentManager: DefermentManager
|
||||
#logger: CustomLogger
|
||||
#options: CacheOptions
|
||||
#disposed = false
|
||||
|
||||
constructor(
|
||||
database: Database,
|
||||
defermentManager: DefermentManager,
|
||||
options: CacheOptions
|
||||
) {
|
||||
this.#database = database
|
||||
this.#defermentManager = defermentManager
|
||||
this.#options = options
|
||||
this.#logger = options.logger || ((): void => {})
|
||||
}
|
||||
|
||||
add(item: Item): void {
|
||||
if (!this.#writeQueue) {
|
||||
this.#writeQueue = new BatchingQueue({
|
||||
batchSize: this.#options.maxCacheWriteSize,
|
||||
maxWaitTime: this.#options.maxCacheBatchWriteWait,
|
||||
processFunction: (batch: Item[]): Promise<void> =>
|
||||
this.#database.saveBatch({ batch })
|
||||
})
|
||||
}
|
||||
this.#defermentManager.undefer(item)
|
||||
this.#writeQueue.add(item.baseId, item)
|
||||
}
|
||||
|
||||
async disposeAsync(): Promise<void> {
|
||||
await this.#writeQueue?.disposeAsync()
|
||||
this.#disposed = true
|
||||
}
|
||||
|
||||
get isDisposed(): boolean {
|
||||
return this.#disposed
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
||||
import { IDBFactory, IDBKeyRange } from 'fake-indexeddb'
|
||||
import IndexedDatabase, { IndexedDatabaseOptions } from './indexedDatabase.js'
|
||||
|
||||
import { Item, Base } from '../../types/types.js'
|
||||
import { Base, Item } from '../../types/types.js'
|
||||
import IndexedDatabase, { IndexedDatabaseOptions } from './indexedDatabase.js'
|
||||
|
||||
// Mock Item
|
||||
const defaultItem = (id: string): Item => ({
|
||||
+3
-2
@@ -1,9 +1,10 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
|
||||
import BatchingQueue from '../../helpers/batchingQueue.js'
|
||||
import { CustomLogger, Item } from '../../types/types.js'
|
||||
import { CustomLogger } from '../../types/functions.js'
|
||||
import { Item } from '../../types/types.js'
|
||||
import { isSafari } from '@speckle/shared'
|
||||
import { Dexie, DexieOptions, Table } from 'dexie'
|
||||
import { Database } from '../interfaces.js'
|
||||
import BatchingQueue from '../../queues/batchingQueue.js'
|
||||
|
||||
export class ObjectStore extends Dexie {
|
||||
static #databaseName: string = 'speckle-cache'
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest'
|
||||
import { Item, Base } from '../../../types/types.js'
|
||||
import { MemoryDatabase } from './memoryDatabase.js'
|
||||
import { Base, Item } from '../../types/types.js'
|
||||
|
||||
const makeItem = (id: string, foo = 'bar'): Item => ({
|
||||
baseId: id,
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import { Base, Item } from '../../types/types.js'
|
||||
import { Database } from '../interfaces.js'
|
||||
import { MemoryDatabaseOptions } from '../options.js'
|
||||
import { Base, Item } from '../../../types/types.js'
|
||||
import { Database } from '../../interfaces.js'
|
||||
import { MemoryDatabaseOptions } from '../../options.js'
|
||||
|
||||
export class MemoryDatabase implements Database {
|
||||
private items: Map<string, Base>
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest'
|
||||
import { MemoryDownloader } from './memoryDownloader.js'
|
||||
import { Base, Item } from '../../types/types.js'
|
||||
import Queue from '../../helpers/queue.js'
|
||||
import BufferQueue from '../../helpers/bufferQueue.js'
|
||||
import BufferQueue from '../../../queues/bufferQueue.js'
|
||||
import Queue from '../../../queues/queue.js'
|
||||
import { Base, Item } from '../../../types/types.js'
|
||||
|
||||
const makeBase = (foo: string): Base => ({ foo } as unknown as Base)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import Queue from '../../helpers/queue.js'
|
||||
import { Base, Item } from '../../types/types.js'
|
||||
import { Downloader } from '../interfaces.js'
|
||||
import Queue from '../../../queues/queue.js'
|
||||
import { Base, Item } from '../../../types/types.js'
|
||||
import { Downloader } from '../../interfaces.js'
|
||||
|
||||
export class MemoryDownloader implements Downloader {
|
||||
#items: Map<string, Base>
|
||||
+4
-11
@@ -3,7 +3,7 @@ import createFetchMock from 'vitest-fetch-mock'
|
||||
import { vi } from 'vitest'
|
||||
import { Item } from '../../types/types.js'
|
||||
import ServerDownloader from './serverDownloader.js'
|
||||
import AsyncGeneratorQueue from '../../helpers/asyncGeneratorQueue.js'
|
||||
import AsyncGeneratorQueue from '../../queues/asyncGeneratorQueue.js'
|
||||
|
||||
describe('downloader', () => {
|
||||
test('download batch of one', async () => {
|
||||
@@ -24,13 +24,10 @@ describe('downloader', () => {
|
||||
maxDownloadBatchWait: 200
|
||||
})
|
||||
downloader.add('id')
|
||||
await downloader.disposeAsync()
|
||||
const r = []
|
||||
let count = 0
|
||||
for await (const x of gathered.consume()) {
|
||||
r.push(x)
|
||||
count++
|
||||
if (count >= 1) {
|
||||
if (r.length >= 1) {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -65,11 +62,9 @@ describe('downloader', () => {
|
||||
downloader.add('id2')
|
||||
await downloader.disposeAsync()
|
||||
const r = []
|
||||
let count = 0
|
||||
for await (const x of gathered.consume()) {
|
||||
r.push(x)
|
||||
count++
|
||||
if (count >= 2) {
|
||||
if (r.length >= 2) {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -112,11 +107,9 @@ describe('downloader', () => {
|
||||
downloader.add('id3')
|
||||
await downloader.disposeAsync()
|
||||
const r = []
|
||||
let count = 0
|
||||
for await (const x of gathered.consume()) {
|
||||
r.push(x)
|
||||
count++
|
||||
if (count >= 3) {
|
||||
if (r.length >= 3) {
|
||||
break
|
||||
}
|
||||
}
|
||||
+24
-17
@@ -1,7 +1,8 @@
|
||||
import BatchedPool from '../../helpers/batchedPool.js'
|
||||
import Queue from '../../helpers/queue.js'
|
||||
import BatchedPool from '../../queues/batchedPool.js'
|
||||
import Queue from '../../queues/queue.js'
|
||||
import { ObjectLoaderRuntimeError } from '../../types/errors.js'
|
||||
import { Fetcher, isBase, Item, take } from '../../types/types.js'
|
||||
import { Fetcher, isBase, take } from '../../types/functions.js'
|
||||
import { Item } from '../../types/types.js'
|
||||
import { Downloader } from '../interfaces.js'
|
||||
|
||||
export interface ServerDownloaderOptions {
|
||||
@@ -20,6 +21,7 @@ export default class ServerDownloader implements Downloader {
|
||||
#options: ServerDownloaderOptions
|
||||
#fetch: Fetcher
|
||||
#results?: Queue<Item>
|
||||
#total?: number
|
||||
|
||||
#downloadQueue?: BatchedPool<string>
|
||||
#decoder = new TextDecoder()
|
||||
@@ -63,6 +65,7 @@ export default class ServerDownloader implements Downloader {
|
||||
}): void {
|
||||
const { results, total } = params
|
||||
this.#results = results
|
||||
this.#total = total
|
||||
this.#downloadQueue = new BatchedPool<string>({
|
||||
concurrencyAndSizes: this.#getDownloadCountAndSizes(total),
|
||||
maxWaitTime: params.maxDownloadBatchWait,
|
||||
@@ -90,20 +93,6 @@ export default class ServerDownloader implements Downloader {
|
||||
await this.#downloadQueue?.disposeAsync()
|
||||
}
|
||||
|
||||
#processJson(baseId: string, unparsedBase: string): Item {
|
||||
let base: unknown
|
||||
try {
|
||||
base = JSON.parse(unparsedBase)
|
||||
} catch (e: unknown) {
|
||||
throw new Error(`Error parsing object ${baseId}: ${(e as Error).message}`)
|
||||
}
|
||||
if (isBase(base)) {
|
||||
return { baseId, base }
|
||||
} else {
|
||||
throw new ObjectLoaderRuntimeError(`${baseId} is not a base`)
|
||||
}
|
||||
}
|
||||
|
||||
async downloadBatch(params: {
|
||||
batch: string[]
|
||||
url: string
|
||||
@@ -142,6 +131,10 @@ export default class ServerDownloader implements Downloader {
|
||||
'Items requested were not downloaded: ' + take(keys.values(), 10).join(',')
|
||||
)
|
||||
}
|
||||
count += keys.size // count the leftovers
|
||||
if (count >= this.#total!) {
|
||||
await this.#results?.disposeAsync() // mark the queue as done
|
||||
}
|
||||
}
|
||||
|
||||
async processArray(
|
||||
@@ -186,6 +179,20 @@ export default class ServerDownloader implements Downloader {
|
||||
)
|
||||
}
|
||||
|
||||
#processJson(baseId: string, unparsedBase: string): Item {
|
||||
let base: unknown
|
||||
try {
|
||||
base = JSON.parse(unparsedBase)
|
||||
} catch (e: unknown) {
|
||||
throw new Error(`Error parsing object ${baseId}: ${(e as Error).message}`)
|
||||
}
|
||||
if (isBase(base)) {
|
||||
return { baseId, base }
|
||||
} else {
|
||||
throw new ObjectLoaderRuntimeError(`${baseId} is not a base`)
|
||||
}
|
||||
}
|
||||
|
||||
concatUint8Arrays(a: Uint8Array, b: Uint8Array): Uint8Array {
|
||||
const c = new Uint8Array(a.length + b.length)
|
||||
c.set(a, 0)
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, test } from 'vitest'
|
||||
import { Base } from '../types/types.js'
|
||||
import { ObjectLoader2 } from './objectLoader2.js'
|
||||
import Traverser from './traverser.js'
|
||||
import { Base } from '../types/types.js'
|
||||
|
||||
describe('Traverser', () => {
|
||||
test('root and two children with referenceId', async () => {
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
import { Base, DataChunk, isBase, isReference, isScalar } from '../types/types.js'
|
||||
import { isScalar, isBase, isReference } from '../types/functions.js'
|
||||
import { Base, DataChunk } from '../types/types.js'
|
||||
import { ObjectLoader2 } from './objectLoader2.js'
|
||||
|
||||
export type ProgressStage = 'download' | 'construction'
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { describe, test, expect, beforeEach } from 'vitest'
|
||||
import { DefermentManager } from './defermentManager.js'
|
||||
import { DefermentManagerOptions } from '../operations/options.js'
|
||||
import { DefermentManagerOptions } from '../core/options.js'
|
||||
import { Base, Item } from '../types/types.js'
|
||||
|
||||
const makeItem = (id: string, size = 1): Item => ({
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { DefermentManager } from './defermentManager.js'
|
||||
import { DefermentManagerOptions } from '../operations/options.js'
|
||||
import { DefermentManagerOptions } from '../core/options.js'
|
||||
import { Item } from '../types/types.js'
|
||||
|
||||
describe('DefermentManager disposal', () => {
|
||||
+3
-2
@@ -1,6 +1,7 @@
|
||||
import { DeferredBase } from './deferredBase.js'
|
||||
import { Base, CustomLogger, Item } from '../types/types.js'
|
||||
import { DefermentManagerOptions } from '../operations/options.js'
|
||||
import { CustomLogger } from '../types/functions.js'
|
||||
import { Item, Base } from '../types/types.js'
|
||||
import { DefermentManagerOptions } from '../core/options.js'
|
||||
|
||||
export class DefermentManager {
|
||||
private deferments: Map<string, DeferredBase> = new Map()
|
||||
@@ -1,2 +1,2 @@
|
||||
export { ObjectLoader2 } from './operations/objectLoader2.js'
|
||||
export { ObjectLoader2Factory } from './operations/objectLoader2Factory.js'
|
||||
export { ObjectLoader2 } from './core/objectLoader2.js'
|
||||
export { ObjectLoader2Factory } from './core/objectLoader2Factory.js'
|
||||
|
||||
+5
-1
@@ -8,13 +8,17 @@ export default class AggregateQueue<T> implements Queue<T> {
|
||||
this.#queue1 = queue1
|
||||
this.#queue2 = queue2
|
||||
}
|
||||
async disposeAsync(): Promise<void> {
|
||||
await this.#queue1.disposeAsync()
|
||||
await this.#queue2.disposeAsync()
|
||||
}
|
||||
|
||||
add(value: T): void {
|
||||
this.#queue1.add(value)
|
||||
this.#queue2.add(value)
|
||||
}
|
||||
|
||||
values(): T[] {
|
||||
values(): never {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -29,7 +29,8 @@ export default class AsyncGeneratorQueue<T> implements Queue<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
dispose(): void {
|
||||
disposeAsync(): Promise<void> {
|
||||
this.#finished = true
|
||||
return Promise.resolve()
|
||||
}
|
||||
}
|
||||
+3
@@ -9,4 +9,7 @@ export default class BufferQueue<T> implements Queue<T> {
|
||||
values(): T[] {
|
||||
return this.#buffer
|
||||
}
|
||||
disposeAsync(): Promise<void> {
|
||||
return Promise.resolve()
|
||||
}
|
||||
}
|
||||
+4
-6
@@ -1,15 +1,14 @@
|
||||
import { Database } from '../operations/interfaces.js'
|
||||
import { CacheOptions } from '../operations/options.js'
|
||||
import { CustomLogger, Item } from '../types/types.js'
|
||||
import { Database } from '../core/interfaces.js'
|
||||
import { CacheOptions } from '../core/options.js'
|
||||
import { DefermentManager } from '../deferment/defermentManager.js'
|
||||
import { Item } from '../types/types.js'
|
||||
import BatchingQueue from './batchingQueue.js'
|
||||
import { DefermentManager } from './defermentManager.js'
|
||||
import Queue from './queue.js'
|
||||
|
||||
export class CacheWriter implements Queue<Item> {
|
||||
#writeQueue: BatchingQueue<Item> | undefined
|
||||
#database: Database
|
||||
#defermentManager: DefermentManager
|
||||
#logger: CustomLogger
|
||||
#options: CacheOptions
|
||||
#disposed = false
|
||||
|
||||
@@ -21,7 +20,6 @@ export class CacheWriter implements Queue<Item> {
|
||||
this.#database = database
|
||||
this.#defermentManager = defermentManager
|
||||
this.#options = options
|
||||
this.#logger = options.logger || ((): void => {})
|
||||
}
|
||||
|
||||
add(item: Item): void {
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
export default interface Queue<T> {
|
||||
add(value: T): void
|
||||
disposeAsync(): Promise<void>
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import { describe, test, expect } from 'vitest'
|
||||
import { IDBFactory, IDBKeyRange } from 'fake-indexeddb'
|
||||
import { Base } from '../types/types.js'
|
||||
import { TIME_MS } from '@speckle/shared'
|
||||
import { ObjectLoader2Factory } from '../operations/objectLoader2Factory.js'
|
||||
import { ObjectLoader2Factory } from '../core/objectLoader2Factory.js'
|
||||
import { Base } from '../types/types.js'
|
||||
|
||||
describe('e2e', () => {
|
||||
test(
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import { Base, Reference } from './types.js'
|
||||
|
||||
export type CustomLogger = (message?: string, ...optionalParams: unknown[]) => void
|
||||
|
||||
export type Fetcher = (
|
||||
input: string | URL | Request,
|
||||
init?: RequestInit
|
||||
) => Promise<Response>
|
||||
|
||||
export function isBase(maybeBase?: unknown): maybeBase is Base {
|
||||
return (
|
||||
maybeBase !== null &&
|
||||
typeof maybeBase === 'object' &&
|
||||
'id' in maybeBase &&
|
||||
typeof maybeBase.id === 'string'
|
||||
)
|
||||
}
|
||||
|
||||
export function isReference(maybeRef?: unknown): maybeRef is Reference {
|
||||
return (
|
||||
maybeRef !== null &&
|
||||
typeof maybeRef === 'object' &&
|
||||
'referencedId' in maybeRef &&
|
||||
typeof maybeRef.referencedId === 'string'
|
||||
)
|
||||
}
|
||||
|
||||
export function isScalar(
|
||||
value: unknown
|
||||
): value is string | number | boolean | bigint | symbol | undefined {
|
||||
const type = typeof value
|
||||
return (
|
||||
value === null ||
|
||||
type === 'string' ||
|
||||
type === 'number' ||
|
||||
type === 'boolean' ||
|
||||
type === 'bigint' ||
|
||||
type === 'symbol' ||
|
||||
type === 'undefined'
|
||||
)
|
||||
}
|
||||
|
||||
export function take<T>(it: Iterator<T>, count: number): T[] {
|
||||
const result: T[] = []
|
||||
for (let i = 0; i < count; i++) {
|
||||
const itr = it.next()
|
||||
if (itr.done) break
|
||||
result.push(itr.value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -1,10 +1,3 @@
|
||||
export type CustomLogger = (message?: string, ...optionalParams: unknown[]) => void
|
||||
|
||||
export type Fetcher = (
|
||||
input: string | URL | Request,
|
||||
init?: RequestInit
|
||||
) => Promise<Response>
|
||||
|
||||
export interface Item {
|
||||
baseId: string
|
||||
base?: Base
|
||||
@@ -26,46 +19,3 @@ export interface Reference {
|
||||
export interface DataChunk extends Base {
|
||||
data?: Base[]
|
||||
}
|
||||
|
||||
export function isBase(maybeBase?: unknown): maybeBase is Base {
|
||||
return (
|
||||
maybeBase !== null &&
|
||||
typeof maybeBase === 'object' &&
|
||||
'id' in maybeBase &&
|
||||
typeof maybeBase.id === 'string'
|
||||
)
|
||||
}
|
||||
|
||||
export function isReference(maybeRef?: unknown): maybeRef is Reference {
|
||||
return (
|
||||
maybeRef !== null &&
|
||||
typeof maybeRef === 'object' &&
|
||||
'referencedId' in maybeRef &&
|
||||
typeof maybeRef.referencedId === 'string'
|
||||
)
|
||||
}
|
||||
|
||||
export function isScalar(
|
||||
value: unknown
|
||||
): value is string | number | boolean | bigint | symbol | undefined {
|
||||
const type = typeof value
|
||||
return (
|
||||
value === null ||
|
||||
type === 'string' ||
|
||||
type === 'number' ||
|
||||
type === 'boolean' ||
|
||||
type === 'bigint' ||
|
||||
type === 'symbol' ||
|
||||
type === 'undefined'
|
||||
)
|
||||
}
|
||||
|
||||
export function take<T>(it: Iterator<T>, count: number): T[] {
|
||||
const result: T[] = []
|
||||
for (let i = 0; i < count; i++) {
|
||||
const itr = it.next()
|
||||
if (itr.done) break
|
||||
result.push(itr.value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user