Skip to content

Commit

Permalink
fix(gatsby): use lmdb.removeSync so getNode can't return deleted nodes (
Browse files Browse the repository at this point in the history
#33554) (#33633)

Co-authored-by: Ward Peeters <ward@coding-tech.com>
(cherry picked from commit 98a843c)

# Conflicts:
#	packages/gatsby/src/datastore/lmdb/lmdb-datastore.ts

Co-authored-by: Kyle Mathews <mathews.kyle@gmail.com>
  • Loading branch information
vladar and KyleAMathews authored Oct 22, 2021
1 parent c692e1f commit d4cf891
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 14 deletions.
49 changes: 35 additions & 14 deletions packages/gatsby/src/datastore/lmdb/lmdb-datastore.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RootDatabase, open } from "lmdb-store"
import { RootDatabase, open, ArrayLikeIterable } from "lmdb-store"
// import { performance } from "perf_hooks"
import { ActionsUnion, IGatsbyNode } from "../../redux/types"
import { updateNodes } from "./updates/nodes"
Expand Down Expand Up @@ -27,6 +27,8 @@ const lmdbDatastore = {
getNodesByType,
}

const preSyncDeletedNodeIdsCache = new Set()

function getDefaultDbPath(): string {
const dbFileName =
process.env.NODE_ENV === `test`
Expand Down Expand Up @@ -122,10 +124,8 @@ function iterateNodes(): GatsbyIterable<IGatsbyNode> {
return new GatsbyIterable(
nodesDb
.getKeys({ snapshot: false })
.map(
nodeId => (typeof nodeId === `string` ? getNode(nodeId) : undefined)!
)
.filter(Boolean)
.map(nodeId => (typeof nodeId === `string` ? getNode(nodeId) : undefined))
.filter(Boolean) as ArrayLikeIterable<IGatsbyNode>
)
}

Expand All @@ -134,13 +134,16 @@ function iterateNodesByType(type: string): GatsbyIterable<IGatsbyNode> {
return new GatsbyIterable(
nodesByType
.getValues(type)
.map(nodeId => getNode(nodeId)!)
.filter(Boolean)
.map(nodeId => getNode(nodeId))
.filter(Boolean) as ArrayLikeIterable<IGatsbyNode>
)
}

function getNode(id: string): IGatsbyNode | undefined {
if (!id) return undefined
if (!id || preSyncDeletedNodeIdsCache.has(id)) {
return undefined
}

const { nodes } = getDatabases()
return nodes.get(id)
}
Expand All @@ -151,9 +154,11 @@ function getTypes(): Array<string> {

function countNodes(typeName?: string): number {
if (!typeName) {
const stats = getDatabases().nodes.getStats()
// @ts-ignore
return Number(stats.entryCount || 0) // FIXME: add -1 when restoring shared structures key
const stats = getDatabases().nodes.getStats() as { entryCount: number }
return Math.max(
Number(stats.entryCount) - preSyncDeletedNodeIdsCache.size,
0
) // FIXME: add -1 when restoring shared structures key
}

const { nodesByType } = getDatabases()
Expand Down Expand Up @@ -192,14 +197,30 @@ function updateDataStore(action: ActionsUnion): void {
break
}
case `CREATE_NODE`:
case `DELETE_NODE`:
case `ADD_FIELD_TO_NODE`:
case `ADD_CHILD_NODE_TO_PARENT_NODE`:
case `DELETE_NODE`: {
case `ADD_CHILD_NODE_TO_PARENT_NODE`: {
const dbs = getDatabases()
lastOperationPromise = Promise.all([
const operationPromise = Promise.all([
updateNodes(dbs.nodes, action),
updateNodesByType(dbs.nodesByType, action),
])
lastOperationPromise = operationPromise

// if create is used in the same transaction as delete we should remove it from cache
if (action.type === `CREATE_NODE`) {
preSyncDeletedNodeIdsCache.delete(action.payload.id)
}

if (action.type === `DELETE_NODE` && action.payload?.id) {
preSyncDeletedNodeIdsCache.add(action.payload.id)
operationPromise.then(() => {
// only clear if no other operations have been done in the meantime
if (lastOperationPromise === operationPromise) {
preSyncDeletedNodeIdsCache.clear()
}
})
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/gatsby/src/datastore/lmdb/updates/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export function updateNodes(
if (action.payload) {
return nodesDb.remove(action.payload.id)
}

return false
}
}
Expand Down

0 comments on commit d4cf891

Please sign in to comment.