OL2 (fix): undefer on write (#5127)

* undefer only on write, not download

* fix test and format
This commit is contained in:
Adam Hathcock
2025-07-22 11:41:03 +01:00
committed by GitHub
parent b5e5652843
commit cc54b42a70
6 changed files with 34 additions and 16 deletions
@@ -58,7 +58,14 @@ export class ObjectLoader2 {
this.#downloader = options.downloader
this.#cacheReader = new CacheReader(this.#database, this.#deferments, cacheOptions)
this.#cacheReader.initializeQueue(this.#gathered, this.#downloader)
this.#cacheWriter = new CacheWriter(this.#database, cacheOptions)
this.#cacheWriter = new CacheWriter(
this.#database,
cacheOptions,
this.#deferments,
(id: string) => {
this.#cacheReader.requestItem(id)
}
)
}
async disposeAsync(): Promise<void> {
@@ -126,7 +133,6 @@ export class ObjectLoader2 {
this.#cacheReader.requestAll(children)
let count = 0
for await (const item of this.#gathered.consume()) {
this.#deferments.undefer(item, (id: string) => this.#cacheReader.requestItem(id))
yield item.base! //always defined, as we add it to the queue
count++
if (count >= total) {
@@ -3,12 +3,14 @@ import { DefermentManager } from '../../deferment/defermentManager.js'
import { Item, Base } from '../../types/types.js'
import { CacheReader } from './cacheReader.js'
import { MemoryDatabase } from './memory/memoryDatabase.js'
import { MemoryCache } from '../../deferment/MemoryCache.js'
describe('CacheReader testing', () => {
test('deferred getObject', async () => {
const i1: Item = { baseId: 'id1', base: { id: 'id', speckle_type: 'type' } }
const deferments = new DefermentManager({ maxSizeInMb: 1, ttlms: 1 })
const cache = new MemoryCache({ maxSizeInMb: 1, ttlms: 1 }, () => {})
const deferments = new DefermentManager(cache, () => {})
const cacheReader = new CacheReader(
new MemoryDatabase({
items: new Map<string, Base>([[i1.baseId, i1.base!]])
@@ -26,7 +28,9 @@ describe('CacheReader testing', () => {
const objPromise = cacheReader.getObject({
id: i1.baseId
})
deferments.undefer(i1)
deferments.undefer(i1, (id: string) => {
throw new Error(`Requesting item ${id} not implemented`)
})
const base = await objPromise
expect(base).toMatchSnapshot()
@@ -1,3 +1,4 @@
import { DefermentManager } from '../../deferment/defermentManager.js'
import BatchingQueue from '../../queues/batchingQueue.js'
import Queue from '../../queues/queue.js'
import { CustomLogger } from '../../types/functions.js'
@@ -8,14 +9,23 @@ import { CacheOptions } from '../options.js'
export class CacheWriter implements Queue<Item> {
#writeQueue: BatchingQueue<Item> | undefined
#database: Database
#defermentManager: DefermentManager
#requestItem: (id: string) => void
#logger: CustomLogger
#options: CacheOptions
#disposed = false
constructor(database: Database, options: CacheOptions) {
constructor(
database: Database,
options: CacheOptions,
defermentManager: DefermentManager,
requestItem: (id: string) => void
) {
this.#database = database
this.#options = options
this.#logger = options.logger || ((): void => {})
this.#defermentManager = defermentManager
this.#requestItem = requestItem
}
add(item: Item): void {
@@ -29,6 +39,7 @@ export class CacheWriter implements Queue<Item> {
})
}
this.#writeQueue.add(item.baseId, item)
this.#defermentManager.undefer(item, this.#requestItem)
}
async writeAll(items: Item[]): Promise<void> {
@@ -130,7 +130,7 @@ describe('MemoryCache', () => {
const now = 1
cache.add(item1, requestItem, now - 200)
cache.cleanDeferments(now)
cache.cleanCache(now)
cache.add(item2, requestItem, now + 100)
expect(cache.get('1')).toBeUndefined()
@@ -116,7 +116,7 @@ export class MemoryCache {
private resetGlobalTimer(): void {
const run = (): void => {
this.cleanDeferments()
this.cleanCache()
this.timer = setTimeout(run, this.options.ttlms)
}
this.timer = setTimeout(run, this.options.ttlms)
@@ -126,13 +126,11 @@ export class MemoryCache {
return Date.now()
}
cleanDeferments(testNow?: number): void {
cleanCache(testNow?: number): void {
const maxSizeBytes = this.options.maxSizeInMb * 1024 * 1024
if (this.currentSize < maxSizeBytes) {
this.logger(
'deferments size is ok, no need to clean',
this.currentSize,
maxSizeBytes
`cache size (${this.currentSize} < ${maxSizeBytes}) is ok, no need to clean`
)
return
}
@@ -161,10 +159,9 @@ export class MemoryCache {
}
}
this.logger(
'cleaned deferments: cleaned, cached, time',
cleaned,
this.cache.size,
performance.now() - start
`cleaned cache: cleaned ${cleaned}, cached ${this.cache.size}, time ${
performance.now() - start
}`
)
return
}
@@ -138,7 +138,7 @@ describe('BatchingQueue', () => {
expect(processSpy).toHaveBeenCalledTimes(1)
expect(processSpy).toHaveBeenCalledWith(['item1', 'item2'])
await new Promise((resolve) => setTimeout(resolve, 200))
await new Promise((resolve) => setTimeout(resolve, 500))
expect(processSpy).toHaveBeenCalledTimes(2)
expect(processSpy).toHaveBeenCalledWith(['item3'])