diff --git a/packages/signaldb/__tests__/Collection.spec.ts b/packages/signaldb/__tests__/Collection.spec.ts index 0297380d..65673520 100644 --- a/packages/signaldb/__tests__/Collection.spec.ts +++ b/packages/signaldb/__tests__/Collection.spec.ts @@ -649,5 +649,16 @@ describe('Collection', () => { await col.dispose() expect(unregister).toHaveBeenCalledOnce() }) + + it('should not fail if id index gets modified during batch operation', () => { + const col = new Collection<{ id: string, name: string }>() + col.insert({ id: '1', name: 'John' }) + col.insert({ id: '2', name: 'Jane' }) + col.batch(() => { + col.removeOne({ id: '1' }) + + expect(col.find({ id: '2' }).fetch()).toEqual([{ id: '2', name: 'Jane' }]) + }) + }) }) }) diff --git a/packages/signaldb/src/Collection/index.ts b/packages/signaldb/src/Collection/index.ts index 0797e8f2..67e05627 100644 --- a/packages/signaldb/src/Collection/index.ts +++ b/packages/signaldb/src/Collection/index.ts @@ -396,6 +396,18 @@ export default class Collection = BaseItem, I = any, U = T return { item, index } } + private deleteFromIdIndex(id: I, index: number) { + this.idIndex.delete(serializeValue(id)) + + // offset all indices after the deleted item -1, but only during batch operations + if (!this.batchOperationInProgress) return + this.idIndex.forEach(([currenIndex], key) => { + if (currenIndex > index) { + this.idIndex.set(key, new Set([currenIndex - 1])) + } + }) + } + private memory() { return this.options.memory as NonNullable> } @@ -584,7 +596,7 @@ export default class Collection = BaseItem, I = any, U = T const { item, index } = this.getItemAndIndex(selector) if (item != null) { this.memory().splice(index, 1) - this.idIndex.delete(serializeValue(item.id)) + this.deleteFromIdIndex(item.id, index) this.rebuildIndices() this.emit('removed', item) } @@ -602,7 +614,7 @@ export default class Collection = BaseItem, I = any, U = T const index = this.memory().findIndex(doc => doc === item) if (index === -1) throw new Error('Cannot resolve index for item') this.memory().splice(index, 1) - this.idIndex.delete(serializeValue(item.id)) + this.deleteFromIdIndex(item.id, index) this.rebuildIndices() })