Files
30-seconds-of-code/node_modules/gatsby-plugin-sharp/scheduler.js
2019-08-20 15:52:05 +02:00

151 lines
3.5 KiB
JavaScript

"use strict";
const _ = require(`lodash`);
const {
existsSync
} = require(`fs`);
const queue = require(`async/queue`);
const {
processFile
} = require(`./process-file`);
const {
createProgress
} = require(`./utils`);
const toProcess = {};
let totalJobs = 0;
const q = queue((task, callback) => {
task(callback);
}, 1);
let bar; // when the queue is empty we stop the progressbar
q.drain = () => {
if (bar) {
bar.done();
}
totalJobs = 0;
};
exports.scheduleJob = async (job, boundActionCreators, pluginOptions, reporter, reportStatus = true) => {
const inputFileKey = job.inputPath.replace(/\./g, `%2E`);
const outputFileKey = job.outputPath.replace(/\./g, `%2E`);
const jobPath = `${inputFileKey}.${outputFileKey}`; // Check if the job has already been queued. If it has, there's nothing
// to do, return.
if (_.has(toProcess, jobPath)) {
return _.get(toProcess, `${jobPath}.deferred.promise`);
} // Check if the output file already exists so we don't redo work.
if (existsSync(job.outputPath)) {
return Promise.resolve(job);
}
let isQueued = false;
if (toProcess[inputFileKey]) {
isQueued = true;
} // deferred naming comes from https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred
let deferred = {};
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
});
if (totalJobs === 0) {
bar = createProgress(`Generating image thumbnails`, reporter);
bar.start();
}
totalJobs += 1;
_.set(toProcess, jobPath, {
job: job,
deferred
});
if (!isQueued) {
// Create image job
boundActionCreators.createJob({
id: `processing image ${job.inputPath}`,
imagesCount: 1
}, {
name: `gatsby-plugin-sharp`
});
q.push(cb => {
runJobs(inputFileKey, boundActionCreators, pluginOptions, reportStatus, cb);
});
}
return deferred.promise;
};
function runJobs(inputFileKey, boundActionCreators, pluginOptions, reportStatus, cb) {
const jobs = _.values(toProcess[inputFileKey]);
const findDeferred = job => jobs.find(j => j.job === job).deferred;
const {
job
} = jobs[0]; // Delete the input key from the toProcess list so more jobs can be queued.
delete toProcess[inputFileKey]; // Update job info
boundActionCreators.setJob({
id: `processing image ${job.inputPath}`,
imagesCount: jobs.length
}, {
name: `gatsby-plugin-sharp`
}); // We're now processing the file's jobs.
let imagesFinished = 0;
bar.total = totalJobs;
try {
const promises = processFile(job.inputPath, job.contentDigest, jobs.map(job => job.job), pluginOptions).map(promise => promise.then(job => {
findDeferred(job).resolve();
}).catch(err => {
findDeferred(job).reject({
err,
message: `Failed to process image ${job.inputPath}`
});
}).then(() => {
imagesFinished += 1; // only show progress on build
if (reportStatus) {
bar.tick();
}
boundActionCreators.setJob({
id: `processing image ${job.inputPath}`,
imagesFinished
}, {
name: `gatsby-plugin-sharp`
});
}));
Promise.all(promises).then(() => {
boundActionCreators.endJob({
id: `processing image ${job.inputPath}`
}, {
name: `gatsby-plugin-sharp`
});
cb();
});
} catch (err) {
jobs.forEach(({
deferred
}) => {
deferred.reject({
err,
message: err.message
});
});
}
}