Skip to content
This repository has been archived by the owner on Jun 3, 2022. It is now read-only.

Commit

Permalink
chore(database): check index is modified before deleting for better p…
Browse files Browse the repository at this point in the history
…erformance (#733)
  • Loading branch information
fuxingloh authored Jan 31, 2022
1 parent 349876d commit 65c78aa
Showing 1 changed file with 42 additions and 4 deletions.
46 changes: 42 additions & 4 deletions src/module.database/provider.level/level.database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,24 @@ export abstract class LevelUpDatabase extends Database {
}

async put<M extends Model> (mapping: ModelMapping<M>, model: M): Promise<void> {
// TODO(fuxingloh): check before deleting for better performance
// TODO(fuxingloh): block writing race condition
await this.delete(mapping, model.id)
const indexes = Object.values(mapping.index)
const persisted = await this.get(mapping, model.id) as M

if (persisted !== undefined) {
// Check before deleting for better performance, only delete secondary indexes that won't be present anymore
for (const index of indexes) {
if (isIndexModified(index, persisted, model)) {
const subIndex = this.subIndex(index, index.partition.key(persisted))
const key = index.sort !== undefined ? index.sort.key(persisted) : index.partition.key(persisted)
await subIndex.del(key)
}
}
}

const subRoot = this.subRoot(mapping)
await subRoot.put(model.id, model)

for (const index of Object.values(mapping.index)) {
for (const index of indexes) {
const subIndex = this.subIndex(index, index.partition.key(model))
const key = index.sort !== undefined ? index.sort.key(model) : index.partition.key(model)
await subIndex.put(key, model)
Expand All @@ -141,6 +151,34 @@ export abstract class LevelUpDatabase extends Database {
}
}

/**
* Given the current persisted and soon to be overridden data, is the index we are writing to modified?
*
* If it's modified, we need to delete the previously indexed data. (delete and put)
* If it's not modified, we can just replace it via a simple put. (put)
*
* @param {ModelIndex<M>} index to write data into
* @param {M} persisted currently persisted
* @param {M} override to be overridden with
*/
function isIndexModified<M extends Model> (index: ModelIndex<M>, persisted: M, override: M): boolean {
const persistedPartitionKey = index.partition.key(persisted)
const overridePartitionKey = index.partition.key(override)

if (persistedPartitionKey !== overridePartitionKey) {
return true
}

if (index.sort === undefined) {
return false
}

const persistedSortKey = index.sort.key(persisted)
const overrideSortKey = index.sort.key(override)

return persistedSortKey !== overrideSortKey
}

/**
* LevelDatabase uses [Level/level](https://github.com/Level/level) with a LevelDB instances under the hood.
* [Level/subleveldown](https://github.com/Level/subleveldown) is used to divide key spaces into
Expand Down

0 comments on commit 65c78aa

Please sign in to comment.