Skip to content

Commit

Permalink
chore(gatsby): convert inference-metadata to typescript (#24381)
Browse files Browse the repository at this point in the history
* Convert file & add missing actions

* Address feedback
  • Loading branch information
Kornil authored and axe312ger committed Jun 23, 2020
1 parent 7a5c89d commit cef188c
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 66 deletions.
2 changes: 1 addition & 1 deletion packages/gatsby/src/redux/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { resolvedNodesCacheReducer } from "./resolved-nodes"
import { nodesTouchedReducer } from "./nodes-touched"
import { flattenedPluginsReducer } from "./flattened-plugins"
import schemaCustomizationReducer from "./schema-customization"
import inferenceMetadataReducer from "./inference-metadata"
import { inferenceMetadataReducer } from "./inference-metadata"

/**
* @property exports.nodesTouched Set<string>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,72 +1,31 @@
// Tracking structure of nodes to utilize this metadata for schema inference
// Type descriptors stay relevant at any point in time making incremental inference trivial
const { omit } = require(`lodash`)
const {
import { omit } from "lodash"
import {
addNode,
addNodes,
deleteNode,
ignore,
disable,
} = require(`../../schema/infer/inference-metadata`)
const { NodeInterfaceFields } = require(`../../schema/types/node-interface`)
const { typesWithoutInference } = require(`../../schema/types/type-defs`)
} from "../../schema/infer/inference-metadata"
import { NodeInterfaceFields } from "../../schema/types/node-interface"
import { typesWithoutInference } from "../../schema/types/type-defs"

const StepsEnum = {
initialBuild: `initialBuild`,
incrementalBuild: `incrementalBuild`,
}

const initialState = () => {
return {
step: StepsEnum.initialBuild, // `initialBuild` | `incrementalBuild`
typeMap: {},
}
}

module.exports = (state = initialState(), action) => {
switch (action.type) {
case `CREATE_NODE`:
case `DELETE_NODE`:
case `DELETE_NODES`:
case `ADD_CHILD_NODE_TO_PARENT_NODE`:
case `ADD_FIELD_TO_NODE`: {
// Perf: disable incremental inference until the first schema build.
// There are plugins which create and delete lots of nodes during bootstrap,
// which makes this reducer to do a lot of unnecessary work.
// Instead we defer the initial metadata creation until the first schema build
// and then enable incremental updates explicitly
if (state.step === StepsEnum.initialBuild) {
return state
}
state.typeMap = incrementalReducer(state.typeMap, action)
return state
}

case `START_INCREMENTAL_INFERENCE`: {
return {
...state,
step: StepsEnum.incrementalBuild,
}
}

case `DELETE_CACHE`: {
return initialState()
}
import { IGatsbyState, ActionsUnion } from "../types"

default: {
state.typeMap = incrementalReducer(state.typeMap, action)
return state
}
}
}
const ignoredFields: Set<string> = new Set([
...NodeInterfaceFields,
`__gatsby_resolved`,
])

const ignoredFields = new Set([...NodeInterfaceFields, `__gatsby_resolved`])

const initialTypeMetadata = () => {
const initialTypeMetadata = (): { ignoredFields: Set<string> } => {
return { ignoredFields }
}

const incrementalReducer = (state = {}, action) => {
const incrementalReducer = (
state: IGatsbyState["inferenceMetadata"]["typeMap"] = {},
action: ActionsUnion
): IGatsbyState["inferenceMetadata"]["typeMap"] => {
switch (action.type) {
case `CREATE_TYPES`: {
const typeDefs = Array.isArray(action.payload)
Expand Down Expand Up @@ -123,8 +82,8 @@ const incrementalReducer = (state = {}, action) => {
// Can't simply add { fields: { [addedField]: node.fields[addedField] } }
// because it will count `fields` key twice for the same node
const previousFields = omit(node.fields, [addedField])
state[type] = deleteNode(state[type], { fields: previousFields })
state[type] = addNode(state[type], { fields: node.fields })
state[type] = deleteNode(state[type], { ...node, fields: previousFields })
state[type] = addNode(state[type], { ...node, fields: node.fields })

// TODO: there might be an edge case when the same field is "added" twice.
// Then we'll count it twice in metadata. The only way to avoid it as I see it
Expand Down Expand Up @@ -161,3 +120,55 @@ const incrementalReducer = (state = {}, action) => {
return state
}
}

enum StepsEnum {
initialBuild = `initialBuild`,
incrementalBuild = `incrementalBuild`,
}

const initialState = (): IGatsbyState["inferenceMetadata"] => {
return {
step: StepsEnum.initialBuild, // `initialBuild` | `incrementalBuild`
typeMap: {},
}
}

export const inferenceMetadataReducer = (
state: IGatsbyState["inferenceMetadata"] = initialState(),
action: ActionsUnion
): IGatsbyState["inferenceMetadata"] => {
switch (action.type) {
case `CREATE_NODE`:
case `DELETE_NODE`:
case `DELETE_NODES`:
case `ADD_CHILD_NODE_TO_PARENT_NODE`:
case `ADD_FIELD_TO_NODE`: {
// Perf: disable incremental inference until the first schema build.
// There are plugins which create and delete lots of nodes during bootstrap,
// which makes this reducer to do a lot of unnecessary work.
// Instead we defer the initial metadata creation until the first schema build
// and then enable incremental updates explicitly
if (state.step === StepsEnum.initialBuild) {
return state
}
state.typeMap = incrementalReducer(state.typeMap, action)
return state
}

case `START_INCREMENTAL_INFERENCE`: {
return {
...state,
step: StepsEnum.incrementalBuild,
}
}

case `DELETE_CACHE`: {
return initialState()
}

default: {
state.typeMap = incrementalReducer(state.typeMap, action)
return state
}
}
}
32 changes: 26 additions & 6 deletions packages/gatsby/src/redux/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { DocumentNode, GraphQLSchema } from "graphql"
import { SchemaComposer } from "graphql-compose"
import { IGatsbyCLIState } from "gatsby-cli/src/reporter/redux/types"
import { InternalJobInterface, JobResultInterface } from "../utils/jobs-manager"
import { ITypeMetadata } from "../schema/infer/inference-metadata"

type SystemPath = string
type Identifier = string
Expand Down Expand Up @@ -75,6 +76,7 @@ export interface IGatsbyNode {
}
__gatsby_resolved: any // TODO
[key: string]: unknown
fields: string[]
}

export interface IGatsbyPlugin {
Expand Down Expand Up @@ -223,12 +225,7 @@ export interface IGatsbyState {
inferenceMetadata: {
step: string // TODO make enum or union
typeMap: {
[key: string]: {
ignoredFields: Set<string>
total: number
dirty: boolean
fieldMap: any // TODO
}
[key: string]: ITypeMetadata
}
}
pageDataStats: Map<SystemPath, number>
Expand Down Expand Up @@ -293,6 +290,9 @@ export type ActionsUnion =
| ICreateJobAction
| ISetJobAction
| IEndJobAction
| IStartIncrementalInferenceAction
| IBuildTypeMetadataAction
| IDisableTypeInferenceAction

interface ISetBabelPluginAction {
type: `SET_BABEL_PLUGIN`
Expand Down Expand Up @@ -605,11 +605,13 @@ export interface ISetSiteConfig {
export interface ICreateNodeAction {
type: `CREATE_NODE`
payload: IGatsbyNode
oldNode?: IGatsbyNode
}

export interface IAddFieldToNodeAction {
type: `ADD_FIELD_TO_NODE`
payload: IGatsbyNode
addedField: string
}

export interface IAddChildNodeToParentNodeAction {
Expand All @@ -625,6 +627,7 @@ export interface IDeleteNodeAction {
export interface IDeleteNodesAction {
type: `DELETE_NODES`
payload: Identifier[]
fullNodes: IGatsbyNode[]
}

export interface ISetSiteFlattenedPluginsAction {
Expand Down Expand Up @@ -652,3 +655,20 @@ export interface ITouchNodeAction {
type: `TOUCH_NODE`
payload: Identifier
}

interface IStartIncrementalInferenceAction {
type: `START_INCREMENTAL_INFERENCE`
}

interface IBuildTypeMetadataAction {
type: `BUILD_TYPE_METADATA`
payload: {
nodes: IGatsbyNode[]
typeName: string
}
}

interface IDisableTypeInferenceAction {
type: `DISABLE_TYPE_INFERENCE`
payload: string[]
}
2 changes: 1 addition & 1 deletion packages/gatsby/src/schema/infer/inference-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export interface ITypeMetadata {
dirty?: boolean
total?: number
ignoredFields?: Set<string>
fieldMap: Record<string, IValueDescriptor>
fieldMap?: Record<string, IValueDescriptor>
typeConflictReporter?: TypeConflictReporter
[key: string]: unknown
}
Expand Down

0 comments on commit cef188c

Please sign in to comment.