Skip to content

Commit 44257b6

Browse files
authored
feat(gatsby): PQR worker can run page queries (#32017)
* run queries in child/schema * split schema into schema & queries, add new test * wip * test static queries * revert changes related to page queries * initial * smaller ts improvements removing unused types, consolidate them, export IQueryJob * convert query/index.js to TS + change pageQueryIds type to Array<IGatsbyPage> * wip * use .cache/worker folder for slices location * optional chaining, test context variables * make cloud tests pass? * add runQueriesInWorkers function * remove runQueriesInWorkersQueue from build command for now * add test for runQueriesInWorkersQueue * adapt activity * first part of review comments * wip test * finalize test * proper test with jest-extended Co-authored-by: [email protected] * typescript magic * revert createProgress changes
1 parent 069cb53 commit 44257b6

File tree

17 files changed

+401
-105
lines changed

17 files changed

+401
-105
lines changed

jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,5 @@ module.exports = {
5454
testEnvironment: `jest-environment-jsdom-fourteen`,
5555
moduleFileExtensions: [`js`, `jsx`, `ts`, `tsx`, `json`],
5656
setupFiles: [`<rootDir>/.jestSetup.js`],
57+
setupFilesAfterEnv: [`jest-extended`],
5758
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"ignore": "^5.1.8",
5252
"jest": "^24.9.0",
5353
"jest-cli": "^24.9.0",
54+
"jest-extended": "^0.11.5",
5455
"jest-environment-jsdom-fourteen": "^0.1.0",
5556
"jest-junit": "^10.0.0",
5657
"jest-serializer-path": "^0.1.15",

packages/gatsby/src/query/index.js renamed to packages/gatsby/src/query/index.ts

Lines changed: 93 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
const _ = require(`lodash`)
2-
const fastq = require(`fastq`)
3-
const { store } = require(`../redux`)
4-
const { hasFlag, FLAG_ERROR_EXTRACTION } = require(`../redux/reducers/queries`)
5-
const { queryRunner } = require(`./query-runner`)
6-
const { websocketManager } = require(`../utils/websocket-manager`)
7-
const { GraphQLRunner } = require(`./graphql-runner`)
1+
import _ from "lodash"
2+
import fastq from "fastq"
3+
import { IProgressReporter } from "gatsby-cli/lib/reporter/reporter-progress"
4+
import { store } from "../redux"
5+
import { IGatsbyPage, IGatsbyState } from "../redux/types"
6+
import { hasFlag, FLAG_ERROR_EXTRACTION } from "../redux/reducers/queries"
7+
import { IQueryJob, queryRunner } from "./query-runner"
8+
import {
9+
IStaticQueryResult,
10+
websocketManager,
11+
} from "../utils/websocket-manager"
12+
import { GraphQLRunner } from "./graphql-runner"
13+
import { IGroupedQueryIds } from "../services"
814

915
if (process.env.GATSBY_EXPERIMENTAL_QUERY_CONCURRENCY) {
1016
console.info(
@@ -21,7 +27,7 @@ const concurrency =
2127
* Dirty state is tracked in `queries` reducer, here we simply filter
2228
* them from all tracked queries.
2329
*/
24-
function calcDirtyQueryIds(state) {
30+
export function calcDirtyQueryIds(state: IGatsbyState): Array<string> {
2531
const { trackedQueries, trackedComponents, deletedQueries } = state.queries
2632

2733
const queriesWithBabelErrors = new Set()
@@ -33,7 +39,7 @@ function calcDirtyQueryIds(state) {
3339
}
3440
}
3541
// Note: trackedQueries contains both - page and static query ids
36-
const dirtyQueryIds = []
42+
const dirtyQueryIds: Array<string> = []
3743
for (const [queryId, query] of trackedQueries) {
3844
if (deletedQueries.has(queryId)) {
3945
continue
@@ -45,32 +51,49 @@ function calcDirtyQueryIds(state) {
4551
return dirtyQueryIds
4652
}
4753

54+
export { calcDirtyQueryIds as calcInitialDirtyQueryIds }
55+
4856
/**
49-
* groups queryIds by whether they are static or page queries.
57+
* Groups queryIds by whether they are static or page queries.
5058
*/
51-
function groupQueryIds(queryIds) {
59+
export function groupQueryIds(queryIds: Array<string>): IGroupedQueryIds {
5260
const grouped = _.groupBy(queryIds, p =>
5361
p.slice(0, 4) === `sq--` ? `static` : `page`
5462
)
63+
64+
const { pages } = store.getState()
65+
5566
return {
56-
staticQueryIds: grouped.static || [],
57-
pageQueryIds: grouped.page || [],
67+
staticQueryIds: grouped?.static || [],
68+
pageQueryIds:
69+
grouped?.page
70+
?.map(path => pages.get(path) as IGatsbyPage)
71+
?.filter(Boolean) || [],
5872
}
5973
}
6074

61-
function createQueue({
75+
function createQueue<QueryIDType>({
6276
createJobFn,
6377
state,
6478
activity,
6579
graphqlRunner,
6680
graphqlTracing,
67-
}) {
81+
}: {
82+
createJobFn: (
83+
state: IGatsbyState,
84+
queryId: QueryIDType
85+
) => IQueryJob | undefined
86+
state: IGatsbyState
87+
activity: IProgressReporter
88+
graphqlRunner: GraphQLRunner
89+
graphqlTracing: boolean
90+
}): fastq.queue<QueryIDType, any> {
6891
if (!graphqlRunner) {
6992
graphqlRunner = new GraphQLRunner(store, { graphqlTracing })
7093
}
7194
state = state || store.getState()
7295

73-
function worker(queryId, cb) {
96+
function worker(queryId: QueryIDType, cb): void {
7497
const job = createJobFn(state, queryId)
7598
if (!job) {
7699
cb(null, undefined)
@@ -91,15 +114,28 @@ function createQueue({
91114
return fastq(worker, concurrency)
92115
}
93116

94-
async function processQueries({
117+
async function processQueries<QueryIDType>({
95118
queryIds,
96119
createJobFn,
97120
onQueryDone,
98121
state,
99122
activity,
100123
graphqlRunner,
101124
graphqlTracing,
102-
}) {
125+
}: {
126+
queryIds: Array<QueryIDType>
127+
createJobFn: (
128+
state: IGatsbyState,
129+
queryId: QueryIDType
130+
) => IQueryJob | undefined
131+
onQueryDone:
132+
| (({ job, result }: { job: IQueryJob; result: unknown }) => void)
133+
| undefined
134+
state: IGatsbyState
135+
activity: IProgressReporter
136+
graphqlRunner: GraphQLRunner
137+
graphqlTracing: boolean
138+
}): Promise<void> {
103139
return new Promise((resolve, reject) => {
104140
const fastQueue = createQueue({
105141
createJobFn,
@@ -109,7 +145,7 @@ async function processQueries({
109145
graphqlTracing,
110146
})
111147

112-
queryIds.forEach(queryId => {
148+
queryIds.forEach((queryId: QueryIDType) => {
113149
fastQueue.push(queryId, (err, res) => {
114150
if (err) {
115151
fastQueue.kill()
@@ -123,40 +159,57 @@ async function processQueries({
123159
})
124160

125161
if (!fastQueue.idle()) {
126-
fastQueue.drain = () => resolve()
162+
fastQueue.drain = (): any => resolve()
127163
} else {
128164
resolve()
129165
}
130166
})
131167
}
132168

133-
function createStaticQueryJob(state, queryId) {
169+
function createStaticQueryJob(
170+
state: IGatsbyState,
171+
queryId: string
172+
): IQueryJob | undefined {
134173
const component = state.staticQueryComponents.get(queryId)
174+
135175
if (!component) {
136176
return undefined
137177
}
178+
138179
const { hash, id, query, componentPath } = component
180+
139181
return {
140182
id: queryId,
141-
hash,
142183
query,
184+
isPage: false,
185+
hash,
143186
componentPath,
144187
context: { path: id },
145188
}
146189
}
147190

148-
function onDevelopStaticQueryDone({ job, result }) {
191+
function onDevelopStaticQueryDone({
192+
job,
193+
result,
194+
}: {
195+
job: IQueryJob
196+
result: IStaticQueryResult["result"]
197+
}): void {
198+
if (!job.hash) {
199+
return
200+
}
201+
149202
websocketManager.emitStaticQueryData({
150203
result,
151204
id: job.hash,
152205
})
153206
}
154207

155-
async function processStaticQueries(
156-
queryIds,
208+
export async function processStaticQueries(
209+
queryIds: IGroupedQueryIds["staticQueryIds"],
157210
{ state, activity, graphqlRunner, graphqlTracing }
158-
) {
159-
return processQueries({
211+
): Promise<void> {
212+
return processQueries<string>({
160213
queryIds,
161214
createJobFn: createStaticQueryJob,
162215
onQueryDone:
@@ -170,33 +223,34 @@ async function processStaticQueries(
170223
})
171224
}
172225

173-
async function processPageQueries(
174-
queryIds,
226+
export async function processPageQueries(
227+
queryIds: IGroupedQueryIds["pageQueryIds"],
175228
{ state, activity, graphqlRunner, graphqlTracing }
176-
) {
177-
return processQueries({
229+
): Promise<void> {
230+
return processQueries<IGatsbyPage>({
178231
queryIds,
179232
createJobFn: createPageQueryJob,
233+
onQueryDone: undefined,
180234
state,
181235
activity,
182236
graphqlRunner,
183237
graphqlTracing,
184238
})
185239
}
186240

187-
function createPageQueryJob(state, queryId) {
188-
const page = state.pages.get(queryId)
241+
function createPageQueryJob(
242+
state: IGatsbyState,
243+
page: IGatsbyPage
244+
): IQueryJob | undefined {
245+
const component = state.components.get(page.componentPath)
189246

190-
// Make sure we filter out pages that don't exist. An example is
191-
// /dev-404-page/, whose SitePage node is created via
192-
// `internal-data-bridge`, but the actual page object is only
193-
// created during `gatsby develop`.
194-
if (!page) {
247+
if (!component) {
195248
return undefined
196249
}
197-
const component = state.components.get(page.componentPath)
250+
198251
const { path, componentPath, context } = page
199252
const { query } = component
253+
200254
return {
201255
id: path,
202256
query,
@@ -208,11 +262,3 @@ function createPageQueryJob(state, queryId) {
208262
},
209263
}
210264
}
211-
212-
module.exports = {
213-
calcInitialDirtyQueryIds: calcDirtyQueryIds,
214-
calcDirtyQueryIds,
215-
processPageQueries,
216-
processStaticQueries,
217-
groupQueryIds,
218-
}

packages/gatsby/src/query/query-runner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ import { pageDataExists } from "../utils/page-data"
1717

1818
const resultHashes = new Map()
1919

20-
interface IQueryJob {
20+
export interface IQueryJob {
2121
id: string
2222
hash?: string
2323
query: string
2424
componentPath: string
2525
context: PageContext
2626
isPage: boolean
27-
pluginCreatorId: string
27+
pluginCreatorId?: string
2828
}
2929

3030
function reportLongRunningQueryJob(queryJob): void {

packages/gatsby/src/query/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export interface IGraphQLRunnerStatResults {
2828
uniqueSorts: number
2929
}
3030

31-
export type PageContext = any
31+
export type PageContext = Record<string, any>
3232

3333
export interface IExecutionResult extends ExecutionResult {
3434
pageContext?: PageContext

0 commit comments

Comments
 (0)