Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(gatsby-plugin-gatsby-cloud): add backpressure for IPC #32963

Merged
merged 2 commits into from Sep 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -319,15 +319,18 @@ describe(`build-headers-program`, () => {
process.send = jest.fn()
await buildHeadersProgram(pluginData, pluginOptions)

expect(process.send).toHaveBeenCalledWith({
type: `LOG_ACTION`,
action: {
type: `CREATE_HEADER_ENTRY`,
payload: {
url: `/hello`,
headers: [`X-Frame-Options: SAMEORIGIN`],
expect(process.send).toHaveBeenCalledWith(
{
type: `LOG_ACTION`,
action: {
type: `CREATE_HEADER_ENTRY`,
payload: {
url: `/hello`,
headers: [`X-Frame-Options: SAMEORIGIN`],
},
},
},
})
expect.any(Function)
)
})
})
Expand Up @@ -269,27 +269,33 @@ describe(`create-redirects`, () => {
]
)

expect(process.send).toHaveBeenCalledWith({
type: `LOG_ACTION`,
action: {
type: `CREATE_REDIRECT_ENTRY`,
payload: {
fromPath: `/old-url`,
toPath: `/new-url`,
isPermanent: true,
expect(process.send).toHaveBeenCalledWith(
{
type: `LOG_ACTION`,
action: {
type: `CREATE_REDIRECT_ENTRY`,
payload: {
fromPath: `/old-url`,
toPath: `/new-url`,
isPermanent: true,
},
},
},
})
expect.any(Function)
)

expect(process.send).toHaveBeenCalledWith({
type: `LOG_ACTION`,
action: {
type: `CREATE_REWRITE_ENTRY`,
payload: {
fromPath: `/url_that_is/ugly`,
toPath: `/not_ugly/url`,
expect(process.send).toHaveBeenCalledWith(
{
type: `LOG_ACTION`,
action: {
type: `CREATE_REWRITE_ENTRY`,
payload: {
fromPath: `/url_that_is/ugly`,
toPath: `/not_ugly/url`,
},
},
},
})
expect.any(Function)
)
})
})
144 changes: 56 additions & 88 deletions packages/gatsby-plugin-gatsby-cloud/src/__tests__/routes.js
Expand Up @@ -64,111 +64,79 @@ describe(`Routes IPC`, () => {
)

if (os.platform() !== `win32`) {
expect(process.send).toHaveBeenCalledWith({
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"index.html": `DSR`,
"page-data/index/page-data.json": `DSR`,
},
},
},
})

expect(process.send).toHaveBeenCalledWith({
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"path/1/index.html": `DSR`,
"page-data/path/1/page-data.json": `DSR`,
},
},
},
})

expect(process.send).toHaveBeenCalledWith({
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"path/2/index.html": `SSR`,
"page-data/path/2/page-data.json": `SSR`,
expect(process.send).toHaveBeenCalledWith(
{
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"index.html": `DSR`,
"page-data/index/page-data.json": `DSR`,
"path/1/index.html": `DSR`,
"page-data/path/1/page-data.json": `DSR`,
"path/2/index.html": `SSR`,
"page-data/path/2/page-data.json": `SSR`,
},
},
},
},
})
expect.any(Function)
)

expect(process.send).not.toHaveBeenCalledWith({
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"path/3/index.html": `SSG`,
"page-data/path/3/page-data.json": `SSG`,
expect(process.send).not.toHaveBeenCalledWith(
{
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"path/3/index.html": `SSG`,
"page-data/path/3/page-data.json": `SSG`,
},
},
},
},
})
expect.any(Function)
)
}

if (os.platform() === `win32`) {
expect(process.send).toHaveBeenCalledWith({
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"index.html": `DSR`,
"page-data\\index\\page-data.json": `DSR`,
},
},
},
})

expect(process.send).toHaveBeenCalledWith({
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"path\\1\\index.html": `DSR`,
"page-data\\path\\1\\page-data.json": `DSR`,
},
},
},
})

expect(process.send).toHaveBeenCalledWith({
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"path\\2\\index.html": `SSR`,
"page-data\\path\\2\\page-data.json": `SSR`,
expect(process.send).toHaveBeenCalledWith(
{
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"index.html": `DSR`,
"page-data\\index\\page-data.json": `DSR`,
"path\\1\\index.html": `DSR`,
"page-data\\path\\1\\page-data.json": `DSR`,
"path\\2\\index.html": `SSR`,
"page-data\\path\\2\\page-data.json": `SSR`,
},
},
},
},
})
expect.any(Function)
)

expect(process.send).not.toHaveBeenCalledWith({
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"path\\3\\index.html": `SSG`,
"page-data\\path\\3\\page-data.json": `SSG`,
expect(process.send).not.toHaveBeenCalledWith(
{
type: `LOG_ACTION`,
action: {
type: `CREATE_ROUTE`,
payload: {
routes: {
"path\\3\\index.html": `SSG`,
"page-data\\path\\3\\page-data.json": `SSG`,
},
},
},
},
})
expect.any(Function)
)
}
})
})
72 changes: 41 additions & 31 deletions packages/gatsby-plugin-gatsby-cloud/src/build-headers-program.js
Expand Up @@ -310,40 +310,50 @@ const applyTransfromHeaders =
headers =>
_.mapValues(headers, transformHeaders)

const writeHeadersFile =
({ publicFolder }) =>
contents =>
new Promise((resolve, reject) => {
/**
* Emit Headers via IPC
*/
Object.entries(contents).map(([k, val]) => {
emitHeaders({
url: k,
headers: val,
})
})
const sendHeadersViaIPC = async headers => {
/**
* Emit Headers via IPC
*/
let lastMessage
Object.entries(headers).forEach(([k, val]) => {
lastMessage = emitHeaders({
url: k,
headers: val,
})
})
await lastMessage
}

const contentsStr = JSON.stringify(contents)
const writeStream = createWriteStream(publicFolder(HEADERS_FILENAME))
const chunkSize = 10000
const numChunks = Math.ceil(contentsStr.length / chunkSize)

for (let i = 0; i < numChunks; i++) {
writeStream.write(
contentsStr.slice(
i * chunkSize,
Math.min((i + 1) * chunkSize, contentsStr.length)
)
const writeHeadersFile = async (publicFolder, contents) =>
new Promise((resolve, reject) => {
const contentsStr = JSON.stringify(contents)
const writeStream = createWriteStream(publicFolder(HEADERS_FILENAME))
const chunkSize = 10000
const numChunks = Math.ceil(contentsStr.length / chunkSize)

for (let i = 0; i < numChunks; i++) {
writeStream.write(
contentsStr.slice(
i * chunkSize,
Math.min((i + 1) * chunkSize, contentsStr.length)
)
}
)
}

writeStream.end()
writeStream.on(`finish`, () => {
resolve()
})
writeStream.on(`error`, reject)
writeStream.end()
writeStream.on(`finish`, () => {
resolve()
})
writeStream.on(`error`, reject)
})

const saveHeaders =
({ publicFolder }) =>
contents =>
Promise.all([
sendHeadersViaIPC(contents),
writeHeadersFile(publicFolder, contents),
])

export default function buildHeadersProgram(pluginData, pluginOptions) {
return _.flow(
Expand All @@ -353,6 +363,6 @@ export default function buildHeadersProgram(pluginData, pluginOptions) {
mapUserLinkAllPageHeaders(pluginData, pluginOptions),
applyLinkHeaders(pluginData, pluginOptions),
applyTransfromHeaders(pluginOptions),
writeHeadersFile(pluginData)
saveHeaders(pluginData)
)(pluginOptions.headers)
}
8 changes: 6 additions & 2 deletions packages/gatsby-plugin-gatsby-cloud/src/create-redirects.js
Expand Up @@ -29,17 +29,21 @@ export default async function writeRedirectsFile(
/**
* IPC Emit for redirects
*/
let lastMessageSent
redirects.forEach(redirect => {
emitRedirects(redirect)
lastMessageSent = emitRedirects(redirect)
})

/**
* IPC Emit for rewrites
*/
rewrites.forEach(rewrite => {
emitRewrites(rewrite)
lastMessageSent = emitRewrites(rewrite)
})

// This prevents process from exiting before handling the last IPC message
await lastMessageSent

// Is it ok to pass through the data or should we format it so that we don't have dependencies
// between the redirects and rewrites formats? What are the chances those will change?
const FILE_PATH = publicFolder(REDIRECTS_FILENAME)
Expand Down