Skip to content

Commit

Permalink
tmp: onCreatePage transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
pieh committed Dec 4, 2024
1 parent 14c7ff7 commit 370b4b2
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -209,5 +209,25 @@ exports.createResolvers = ({ createResolvers }) => {
emitter.on(`DELETE_PAGE`, action => {
const nodeId = createPageId(action.payload.path)
const node = getNode(nodeId)
store.dispatch(actions.deleteNode(node))
let deleteNodeActions = actions.deleteNode(node)
if (action.transactionId) {
function swapToStagedDelete(action) {
return {
...action,
type: `DELETE_NODE_STAGING`,
transactionId: action.transactionId,
}
}

deleteNodeActions = Array.isArray(deleteNodeActions)
? deleteNodeActions.map(swapToStagedDelete)
: swapToStagedDelete(deleteNodeActions)
}

console.log(`deletePage stuff`, {
transactionId: action.transactionId,
deleteNodeActions,
})

store.dispatch(deleteNodeActions)
})
64 changes: 64 additions & 0 deletions packages/gatsby/src/redux/actions/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
ICreatePageDependencyActionPayloadType,
IDeleteNodeManifests,
IClearGatsbyImageSourceUrlAction,
ActionsUnion,
} from "../types"

import { gatsbyConfigSchema } from "../../joi-schemas/joi"
Expand All @@ -38,6 +39,9 @@ import {
getInProcessJobPromise,
} from "../../utils/jobs/manager"
import { getEngineContext } from "../../utils/engine-context"
import { store } from "../index"

import { getNode } from "../../datastore"

/**
* Create a dependency between a page and data. Probably for
Expand Down Expand Up @@ -445,3 +449,63 @@ export const clearGatsbyImageSourceUrls =
type: `CLEAR_GATSBY_IMAGE_SOURCE_URL`,
}
}

let publicActions
export const setPublicActions = (actions): void => {
publicActions = actions
}

export const commitStagingNodes = (
transactionId: string
): Array<ActionsUnion> => {
const transaction = store
.getState()
.nodesStaging.transactions.get(transactionId)
if (!transaction) {
return []
}

const actions: Array<ActionsUnion> = [
{
type: `COMMIT_STAGING_NODES`,
payload: {
transactionId,
},
},
]

const nodesState = new Map()
for (const action of transaction) {
if (action.type === `CREATE_NODE_STAGING`) {
nodesState.set(action.payload.id, action)
} else if (action.type === `DELETE_NODE_STAGING` && action.payload?.id) {
nodesState.set(action.payload.id, undefined)
}
}

function sanitizeNode(node: any): any {
return {
...node,
internal: {
...node.internal,
owner: undefined,
},
}
}

for (const [id, actionOrDelete] of nodesState.entries()) {
if (actionOrDelete) {
actions.push(
publicActions.createNode(
sanitizeNode(actionOrDelete.payload),
actionOrDelete.plugin
)
)
} else {
// delete case
actions.push(publicActions.deleteNode(getNode(id), actionOrDelete.plugin))
}
}

return actions
}
64 changes: 46 additions & 18 deletions packages/gatsby/src/redux/actions/public.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const apiRunnerNode = require(`../../utils/api-runner-node`)
const { getNonGatsbyCodeFrame } = require(`../../utils/stack-trace-utils`)
const { getPageMode } = require(`../../utils/page-mode`)
const normalizePath = require(`../../utils/normalize-path`).default
import { createJobV2FromInternalJob } from "./internal"
import { createJobV2FromInternalJob, setPublicActions } from "./internal"
import { maybeSendJobToMainProcess } from "../../utils/jobs/worker-messaging"
import { reportOnce } from "../../utils/report-once"
import { wrapNode } from "../../utils/detect-node-mutations"
Expand Down Expand Up @@ -78,6 +78,7 @@ const findChildren = initialChildren => {
}

import type { Plugin } from "./types"
import { shouldRunOnCreateNode } from "../plugin-runner"

type Job = {
id: string,
Expand Down Expand Up @@ -137,10 +138,15 @@ type PageDataRemove = {
* @example
* deletePage(page)
*/
actions.deletePage = (page: IPageInput) => {
actions.deletePage = (
page: IPageInput,
plugin?: Plugin,
actionOptions?: ActionOptions
) => {
return {
type: `DELETE_PAGE`,
payload: page,
transactionId: actionOptions?.transactionId,
}
}

Expand Down Expand Up @@ -475,10 +481,45 @@ ${reservedFields.map(f => ` * "${f}"`).join(`\n`)}
contentDigest: createContentDigest(node),
}
node.id = `SitePage ${internalPage.path}`
const oldNode = getNode(node.id)

let deleteActions
let updateNodeAction
// const shouldCommitImmediately =
// // !shouldRunOnCreateNode() ||
// !page.path.includes("hello-world")
const transactionId =
actionOptions?.transactionId ??
(shouldRunOnCreateNode() ? node.internal.contentDigest : undefined)

// Sanitize page object so we don't attempt to serialize user-provided objects that are not serializable later
const sanitizedPayload = sanitizeNode(internalPage)

const actions = [
{
...actionOptions,
type: `CREATE_PAGE`,
contextModified,
componentModified,
slicesModified,
plugin,
payload: sanitizedPayload,
transactionId,
},
]

if (transactionId) {
actions.push({
...actionOptions,
type: `CREATE_NODE_STAGING`,
plugin: { name: `internal-data-bridge` },
payload: node,
transactionId,
})
return actions
}

const oldNode = getNode(node.id)

// marking internal-data-bridge as owner of SitePage instead of plugin that calls createPage
if (oldNode && !hasNodeChanged(node.id, node.internal.contentDigest)) {
updateNodeAction = {
Expand Down Expand Up @@ -517,21 +558,6 @@ ${reservedFields.map(f => ` * "${f}"`).join(`\n`)}
}
}

// Sanitize page object so we don't attempt to serialize user-provided objects that are not serializable later
const sanitizedPayload = sanitizeNode(internalPage)

const actions = [
{
...actionOptions,
type: `CREATE_PAGE`,
contextModified,
componentModified,
slicesModified,
plugin,
payload: sanitizedPayload,
},
]

if (deleteActions && deleteActions.length) {
actions.push(...deleteActions)
}
Expand Down Expand Up @@ -1526,3 +1552,5 @@ actions.setRequestHeaders = ({ domain, headers }, plugin: Plugin) => {
}

module.exports = { actions }

setPublicActions(actions)
27 changes: 24 additions & 3 deletions packages/gatsby/src/redux/plugin-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { Span } from "opentracing"
import { emitter, store } from "./index"
import apiRunnerNode from "../utils/api-runner-node"
import { ActivityTracker } from "../../"
import { ICreateNodeAction } from "./types"
import { ICreateNodeStagingAction } from "./types"
import { commitStagingNodes } from "./actions/internal"

type Plugin = any // TODO

Expand Down Expand Up @@ -39,8 +40,12 @@ interface ICreatePageAction {
pluginCreatorId: string
componentPath: string
}
transactionId?: string
}

let hasOnCreatePage = false
let hasOnCreateNode = false

export const startPluginRunner = (): void => {
const plugins = store.getState().flattenedPlugins
const pluginsImplementingOnCreatePage = plugins.filter(plugin =>
Expand All @@ -50,11 +55,17 @@ export const startPluginRunner = (): void => {
plugin.nodeAPIs.includes(`onCreateNode`)
)
if (pluginsImplementingOnCreatePage.length > 0) {
hasOnCreatePage = true
emitter.on(`CREATE_PAGE`, (action: ICreatePageAction) => {
const page = action.payload
apiRunnerNode(
`onCreatePage`,
{ page, traceId: action.traceId, parentSpan: action.parentSpan },
{
page,
traceId: action.traceId,
parentSpan: action.parentSpan,
transactionId: action.transactionId,
},
{ pluginSource: action.plugin.name, activity: action.activity }
)
})
Expand All @@ -63,15 +74,25 @@ export const startPluginRunner = (): void => {
// We make page nodes outside of the normal action for speed so we manually
// call onCreateNode here for SitePage nodes.
if (pluginsImplementingOnCreateNode.length > 0) {
emitter.on(`CREATE_NODE`, (action: ICreateNodeAction) => {
hasOnCreateNode = true
emitter.on(`CREATE_NODE_STAGING`, (action: ICreateNodeStagingAction) => {
const node = action.payload
if (node.internal.type === `SitePage`) {
apiRunnerNode(`onCreateNode`, {
node,
parentSpan: action.parentSpan,
traceTags: { nodeId: node.id, nodeType: node.internal.type },
traceId: action.transactionId,
transactionId: action.transactionId,
waitForCascadingActions: true,
}).then(() => {
store.dispatch(commitStagingNodes(action.transactionId))
})
}
})
}
}

export const shouldRunOnCreateNode = (): boolean => hasOnCreateNode

export const shouldRunOnCreatePage = (): boolean => hasOnCreatePage
2 changes: 2 additions & 0 deletions packages/gatsby/src/redux/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { componentsUsingSlicesReducer } from "./components-using-slices"
import { slicesByTemplateReducer } from "./slices-by-template"
import { adapterReducer } from "./adapter"
import { remoteFileAllowedUrlsReducer } from "./remote-file-allowed-urls"
import { nodesStagingReducer } from "./nodes-staging"

/**
* @property exports.nodesTouched Set<string>
Expand Down Expand Up @@ -85,4 +86,5 @@ export {
telemetryReducer as telemetry,
adapterReducer as adapter,
remoteFileAllowedUrlsReducer as remoteFileAllowedUrls,
nodesStagingReducer as nodesStaging,
}
55 changes: 55 additions & 0 deletions packages/gatsby/src/redux/reducers/nodes-staging.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { ActionsUnion, IGatsbyState, TransactionActionsUnion } from "../types"

function getInitialState(): IGatsbyState["nodesStaging"] {
return { nodes: new Map(), transactions: new Map() }
}

function addActionToTransaction(
state: IGatsbyState["nodesStaging"],
action: TransactionActionsUnion
): void {
if (!action.transactionId) {
return
}

const transaction = state.transactions.get(action.transactionId)
if (!transaction) {
state.transactions.set(action.transactionId, [action])
} else {
transaction.push(action)
}
}

export const nodesStagingReducer = (
state: IGatsbyState["nodesStaging"] = getInitialState(),
action: ActionsUnion
): IGatsbyState["nodesStaging"] => {
switch (action.type) {
case `DELETE_CACHE`:
return getInitialState()

case `CREATE_NODE_STAGING`: {
if (action.transactionId) {
// state.nodes.set(action.payload.id, action.payload)
addActionToTransaction(state, action)
}

return state
}

case `DELETE_NODE_STAGING`: {
if (action.payload && action.transactionId) {
// state.nodes.delete(action.payload.id)
addActionToTransaction(state, action)
}
return state
}
case `COMMIT_STAGING_NODES`: {
state.transactions.delete(action.payload.transactionId)
return state
}

default:
return state
}
}
Loading

0 comments on commit 370b4b2

Please sign in to comment.