Skip to content

Commit 7f9d5bb

Browse files
wardpeetsidharthachatterjee
authored andcommitted
fix(gatsby-plugin-sharp): fix progressbar & caching layer (#19717)
1 parent 9eb2e8e commit 7f9d5bb

File tree

4 files changed

+48
-13
lines changed

4 files changed

+48
-13
lines changed

packages/gatsby-plugin-sharp/src/__tests__/index.js

+27-4
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ jest.mock(`async/queue`, () => () => {
99
}
1010
})
1111

12+
const { scheduleJob } = require(`../scheduler`)
13+
scheduleJob.mockReturnValue(Promise.resolve())
1214
fs.ensureDirSync = jest.fn()
1315
fs.existsSync = jest.fn().mockReturnValue(false)
16+
let isolatedQueueImageResizing
17+
jest.isolateModules(() => {
18+
isolatedQueueImageResizing = require(`../index`).queueImageResizing
19+
})
1420

1521
const {
1622
base64,
@@ -20,8 +26,6 @@ const {
2026
getImageSize,
2127
stats,
2228
} = require(`../`)
23-
const { scheduleJob } = require(`../scheduler`)
24-
scheduleJob.mockResolvedValue(Promise.resolve())
2529

2630
jest.mock(`gatsby-cli/lib/reporter`, () => {
2731
return {
@@ -56,6 +60,12 @@ describe(`gatsby-plugin-sharp`, () => {
5660
}
5761

5862
describe(`queueImageResizing`, () => {
63+
beforeEach(() => {
64+
scheduleJob.mockClear()
65+
fs.existsSync.mockReset()
66+
fs.existsSync.mockReturnValue(false)
67+
})
68+
5969
it(`should round height when auto-calculated`, () => {
6070
// Resize 144-density.png (281x136) with a 3px width
6171
const result = queueImageResizing({
@@ -93,7 +103,6 @@ describe(`gatsby-plugin-sharp`, () => {
93103

94104
// re-enable when image processing on demand is implemented
95105
it.skip(`should process immediately when asked`, async () => {
96-
scheduleJob.mockClear()
97106
const result = queueImageResizing({
98107
file: getFileObject(path.join(__dirname, `images/144-density.png`)),
99108
args: { width: 3 },
@@ -105,7 +114,6 @@ describe(`gatsby-plugin-sharp`, () => {
105114
})
106115

107116
it(`Shouldn't schedule a job when outputFile already exists`, async () => {
108-
scheduleJob.mockClear()
109117
fs.existsSync.mockReturnValue(true)
110118

111119
const result = queueImageResizing({
@@ -118,6 +126,21 @@ describe(`gatsby-plugin-sharp`, () => {
118126
expect(fs.existsSync).toHaveBeenCalledWith(result.absolutePath)
119127
expect(scheduleJob).not.toHaveBeenCalled()
120128
})
129+
130+
it(`Shouldn't schedule a job when with same outputFile is already being queued`, async () => {
131+
const result = isolatedQueueImageResizing({
132+
file: getFileObject(path.join(__dirname, `images/144-density.png`)),
133+
args: { width: 5 },
134+
})
135+
isolatedQueueImageResizing({
136+
file: getFileObject(path.join(__dirname, `images/144-density.png`)),
137+
args: { width: 5 },
138+
})
139+
140+
await result.finishedPromise
141+
142+
expect(scheduleJob).toHaveBeenCalledTimes(1)
143+
})
121144
})
122145

123146
describe(`fluid`, () => {

packages/gatsby-plugin-sharp/src/__tests__/scheduler.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ describe(`scheduler`, () => {
4040
},
4141
contentDigest: `digest`,
4242
}
43-
await scheduleJob(job, boundActionCreators, {}, false, `value`)
43+
await scheduleJob(job, boundActionCreators, `value`, {}, false)
4444

4545
expect(createProgress).not.toHaveBeenCalled()
4646
expect(workerMock).toHaveBeenCalledWith([job.inputPath], job.outputDir, {
@@ -110,6 +110,7 @@ describe(`scheduler`, () => {
110110
},
111111
boundActionCreators,
112112
{},
113+
{},
113114
false
114115
)
115116
} catch (err) {
@@ -147,7 +148,7 @@ describe(`scheduler`, () => {
147148
},
148149
contentDigest: `digest`,
149150
}
150-
const job1Promise = scheduleJob(job1, boundActionCreators, {}, false)
151+
const job1Promise = scheduleJob(job1, boundActionCreators, {}, {}, false)
151152

152153
const job2 = {
153154
inputPath: `/test-image.jpg`,
@@ -158,7 +159,7 @@ describe(`scheduler`, () => {
158159
},
159160
contentDigest: `digest`,
160161
}
161-
const job2Promise = scheduleJob(job2, boundActionCreators, {}, false)
162+
const job2Promise = scheduleJob(job2, boundActionCreators, {}, {}, false)
162163

163164
await Promise.all([job1Promise, job2Promise])
164165

packages/gatsby-plugin-sharp/src/index.js

+15-4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ exports.setBoundActionCreators = actions => {
4040
boundActionCreators = actions
4141
}
4242

43+
const cachedOutputFiles = new Map()
4344
function queueImageResizing({ file, args = {}, reporter }) {
4445
const pluginOptions = getPluginOptions()
4546
const options = healOptions(pluginOptions, args, file.extension)
@@ -103,19 +104,29 @@ function queueImageResizing({ file, args = {}, reporter }) {
103104
outputPath: outputFilePath,
104105
}
105106

107+
const outputFile = path.join(job.outputDir, job.outputPath)
106108
let finishedPromise = Promise.resolve()
107109

108-
// Check if the output file already exists so we don't redo work.
110+
if (cachedOutputFiles.has(outputFile)) {
111+
finishedPromise = cachedOutputFiles.get(outputFile)
112+
}
113+
114+
// Check if the output file already exists or already is being created.
109115
// TODO: Remove this when jobs api is stable, it will have a better check
110-
const outputFile = path.join(job.outputDir, job.outputPath)
111-
if (!fs.existsSync(outputFile)) {
116+
if (!fs.existsSync(outputFile) && !cachedOutputFiles.has(outputFile)) {
112117
// schedule job immediately - this will be changed when image processing on demand is implemented
113118
finishedPromise = scheduleJob(
114119
job,
115120
boundActionCreators,
116121
pluginOptions,
117122
reporter
118-
)
123+
).then(res => {
124+
cachedOutputFiles.delete(outputFile)
125+
126+
return res
127+
})
128+
129+
cachedOutputFiles.set(outputFile, finishedPromise)
119130
}
120131

121132
return {

packages/gatsby-plugin-sharp/src/scheduler.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ const executeJobs = _.throttle(
6060
const scheduleJob = async (
6161
job,
6262
boundActionCreators,
63+
pluginOptions,
6364
reporter,
64-
reportStatus = true,
65-
pluginOptions
65+
reportStatus = true
6666
) => {
6767
const isQueued = toProcess.has(job.inputPath)
6868
let scheduledPromise

0 commit comments

Comments
 (0)