Skip to content

Commit dc0ce0c

Browse files
authored
fix(gatsby-source-contentful): fixed contentful asset download stalling with high number of assets (#27563)
* fix(gatsby-source-contentful): fixed contentful asset download stalling with high number of assets * Add new option to README * Fix test * Switch to pop and fix a typo made when cleaning up code
1 parent 7688f59 commit dc0ce0c

File tree

4 files changed

+36
-6
lines changed

4 files changed

+36
-6
lines changed

packages/gatsby-source-contentful/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ If you are confident your Content Types will have natural-language IDs (e.g. `bl
177177

178178
Number of entries to retrieve from Contentful at a time. Due to some technical limitations, the response payload should not be greater than 7MB when pulling content from Contentful. If you encounter this issue you can set this param to a lower number than 100, e.g `50`.
179179

180+
**`assetDownloadWorkers`** [number][optional] [default: `50`]
181+
182+
Number of workers to use when downloading contentful assets. Due to technical limitations, opening too many concurrent requests can cause stalled downloads. If you encounter this issue you can set this param to a lower number than 50, e.g 25.
183+
180184
**`richText.resolveFieldLocales`** [boolean][optional] [default: `false`]
181185

182186
If you want to resolve the locales in fields of assets and entries that are referenced by rich text (e.g., via embedded entries or entry hyperlinks), set this to `true`. Otherwise, fields of referenced assets or entries will be objects keyed by locale.

packages/gatsby-source-contentful/src/__tests__/download-contentful-assets.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ describe.only(`downloadContentfulAssets`, () => {
6565
actions: { touchNode: jest.fn() },
6666
getNodesByType: () => fixtures,
6767
cache,
68+
assetDownloadWorkers: 50,
6869
})
6970

7071
fixtures.forEach(n => {

packages/gatsby-source-contentful/src/download-contentful-assets.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,23 @@ const bar = new ProgressBar(
99
}
1010
)
1111

12-
let totalJobs = 0
12+
/**
13+
* @name distributeWorkload
14+
* @param workers A list of async functions to complete
15+
* @param {number} count The number of task runners to use
16+
*/
17+
18+
async function distributeWorkload(workers, count) {
19+
const methods = workers.slice()
20+
21+
async function task() {
22+
while (methods.length > 0) {
23+
await methods.pop()()
24+
}
25+
}
26+
27+
await Promise.all(new Array(count).fill(undefined).map(() => task()))
28+
}
1329

1430
/**
1531
* @name downloadContentfulAssets
@@ -27,16 +43,17 @@ const downloadContentfulAssets = async gatsbyFunctions => {
2743
getCache,
2844
getNodesByType,
2945
reporter,
46+
assetDownloadWorkers,
3047
} = gatsbyFunctions
3148

3249
// Any ContentfulAsset nodes will be downloaded, cached and copied to public/static
3350
// regardless of if you use `localFile` to link an asset or not.
3451

35-
await Promise.all(
36-
getNodesByType(`ContentfulAsset`).map(async node => {
37-
totalJobs += 1
38-
bar.total = totalJobs
52+
const assetNodes = getNodesByType(`ContentfulAsset`)
53+
bar.total = assetNodes.length
3954

55+
await distributeWorkload(
56+
assetNodes.map(node => async () => {
4057
let fileNodeID
4158
const { contentful_id: id, node_locale: locale } = node
4259
const remoteDataCacheKey = `contentful-asset-${id}-${locale}`
@@ -90,7 +107,8 @@ const downloadContentfulAssets = async gatsbyFunctions => {
90107
}
91108

92109
return node
93-
})
110+
}),
111+
assetDownloadWorkers
94112
)
95113
}
96114
exports.downloadContentfulAssets = downloadContentfulAssets

packages/gatsby-source-contentful/src/gatsby-node.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ List of locales and their codes can be found in Contentful app -> Settings -> Lo
122122
`Number of entries to retrieve from Contentful at a time. Due to some technical limitations, the response payload should not be greater than 7MB when pulling content from Contentful. If you encounter this issue you can set this param to a lower number than 100, e.g 50.`
123123
)
124124
.default(100),
125+
assetDownloadWorkers: Joi.number()
126+
.integer()
127+
.description(
128+
`Number of workers to use when downloading contentful assets. Due to technical limitations, opening too many concurrent requests can cause stalled downloads. If you encounter this issue you can set this param to a lower number than 50, e.g 25.`
129+
)
130+
.default(50),
125131
proxy: Joi.object()
126132
.keys({
127133
host: Joi.string().required(),
@@ -562,6 +568,7 @@ exports.sourceNodes = async (
562568
getCache,
563569
getNodesByType,
564570
reporter,
571+
assetDownloadWorkers: pluginConfig.get(`assetDownloadWorkers`),
565572
})
566573
}
567574

0 commit comments

Comments
 (0)