Skip to content

Commit

Permalink
fix: offset items after deletions during batch
Browse files Browse the repository at this point in the history
  • Loading branch information
maxnowack committed Dec 5, 2024
1 parent 3c91841 commit 62852a1
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
11 changes: 11 additions & 0 deletions packages/signaldb/__tests__/Collection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' }])
})
})
})
})
16 changes: 14 additions & 2 deletions packages/signaldb/src/Collection/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,18 @@ export default class Collection<T extends BaseItem<I> = 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<MemoryAdapter<T>>
}
Expand Down Expand Up @@ -584,7 +596,7 @@ export default class Collection<T extends BaseItem<I> = 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)
}
Expand All @@ -602,7 +614,7 @@ export default class Collection<T extends BaseItem<I> = 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()
})

Expand Down

0 comments on commit 62852a1

Please sign in to comment.