1
0
mirror of https://github.com/citizenfx/cfx-server-data.git synced 2025-01-08 22:22:57 +08:00

update webpack and yarn builders

Updating the WebPack and Yarn builders so that they do not launch simultaneously. Compiling some modules simultaneously causes conflicts/crashes
This commit is contained in:
GiroudMathias 2019-11-20 16:00:19 +01:00
parent 85419a6145
commit 3bac230553
2 changed files with 191 additions and 156 deletions

View File

@ -2,138 +2,155 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const workerFarm = require('worker-farm'); const workerFarm = require('worker-farm');
const async = require('async'); const async = require('async');
let buildingInProgress = false;
let currentBuildingModule = '';
let currentBuildingScript = '';
const webpackBuildTask = { const webpackBuildTask = {
shouldBuild(resourceName) { shouldBuild(resourceName) {
const numMetaData = GetNumResourceMetadata(resourceName, 'webpack_config'); const numMetaData = GetNumResourceMetadata(resourceName, 'webpack_config');
if (numMetaData > 0) { if (numMetaData > 0) {
for (let i = 0; i < numMetaData; i++) { for (let i = 0; i < numMetaData; i++) {
const configName = GetResourceMetadata(resourceName, 'webpack_config'); const configName = GetResourceMetadata(resourceName, 'webpack_config');
if (shouldBuild(configName)) { if (shouldBuild(configName)) {
return true; return true;
} }
} }
} }
return false; return false;
function loadCache(config) { function loadCache(config) {
const cachePath = `cache/${resourceName}/${config.replace(/\//g, '_')}.json`; const cachePath = `cache/${resourceName}/${config.replace(/\//g, '_')}.json`;
try { try {
return JSON.parse(fs.readFileSync(cachePath, { encoding: 'utf8' })); return JSON.parse(fs.readFileSync(cachePath, {encoding: 'utf8'}));
} catch { } catch {
return null; return null;
} }
} }
function shouldBuild(config) { function shouldBuild(config) {
const cache = loadCache(config); const cache = loadCache(config);
if (!cache) { if (!cache) {
return true; return true;
} }
for (const file of cache) { for (const file of cache) {
const stats = getStat(file.name); const stats = getStat(file.name);
if (!stats || if (!stats ||
stats.mtime !== file.stats.mtime || stats.mtime !== file.stats.mtime ||
stats.size !== file.stats.size || stats.size !== file.stats.size ||
stats.inode !== file.stats.inode) { stats.inode !== file.stats.inode) {
return true; return true;
} }
} }
return false; return false;
} }
function getStat(path) { function getStat(path) {
try { try {
const stat = fs.statSync(path); const stat = fs.statSync(path);
return stat ? { return stat ? {
mtime: stat.mtimeMs, mtime: stat.mtimeMs,
size: stat.size, size: stat.size,
inode: stat.ino, inode: stat.ino,
} : null; } : null;
} catch { } catch {
return null; return null;
} }
} }
}, },
build(resourceName, cb) { build(resourceName, cb) {
const configs = []; let buildWebpack = async () => {
const numMetaData = GetNumResourceMetadata(resourceName, 'webpack_config'); let error = null;
const configs = [];
const numMetaData = GetNumResourceMetadata(resourceName, 'webpack_config');
for (let i = 0; i < numMetaData; i++) { for (let i = 0; i < numMetaData; i++) {
configs.push(GetResourceMetadata(resourceName, 'webpack_config', i)); configs.push(GetResourceMetadata(resourceName, 'webpack_config', i));
} }
for (const configName of configs) {
const configPath = GetResourcePath(resourceName) + '/' + configName;
async.forEachOf(configs, (configName, i, acb) => { const cachePath = `cache/${resourceName}/${configName.replace(/\//g, '_')}.json`;
const configPath = GetResourcePath(resourceName) + '/' + configName;
const cachePath = `cache/${resourceName}/${configName.replace(/\//g, '_')}.json`; try {
fs.mkdirSync(path.dirname(cachePath));
} catch {
}
try { const config = require(configPath);
fs.mkdirSync(path.dirname(cachePath));
} catch {}
const config = require(configPath); const workers = workerFarm(require.resolve('./webpack_runner'));
const workers = workerFarm(require.resolve('./webpack_runner')); if (config) {
const resourcePath = path.resolve(GetResourcePath(resourceName));
if (config) { while (buildingInProgress) {
const resourcePath = path.resolve(GetResourcePath(resourceName)); console.log(`webpack is busy by another process: we are waiting to compile ${resourceName} (${configName})`);
await sleep(3000);
}
buildingInProgress = true;
currentBuildingModule = resourceName;
currentBuildingScript = configName;
workers({
configPath,
resourcePath,
cachePath
}, (err, outp) => {
workerFarm.end(workers);
workers({ if (err) {
configPath, console.error(err.stack || err);
resourcePath, if (err.details) {
cachePath console.error(err.details);
}, (err, outp) => { }
workerFarm.end(workers);
if (err) { buildingInProgress = false;
console.error(err.stack || err); currentBuildingModule = '';
if (err.details) { currentBuildingScript = '';
console.error(err.details); error = "worker farm webpack errored out";
} console.error("worker farm webpack errored out");
return;
}
acb("worker farm webpack errored out"); if (outp.errors) {
return; for (const error of outp.errors) {
} console.log(error);
}
buildingInProgress = false;
currentBuildingModule = '';
currentBuildingScript = '';
error = "webpack got an error";
console.error("webpack got an error");
return;
}
if (outp.errors) { console.log(`${resourceName}: built ${configName}`);
for (const error of outp.errors) {
console.log(error);
}
acb("webpack got an error");
return;
}
console.log(`${resourceName}: built ${configName}`); buildingInProgress = false;
currentBuildingModule = '';
currentBuildingScript = '';
});
}
}
if (error) {
cb(false, error);
} else cb(true);
};
buildWebpack().then();
}
};
acb(); function sleep(ms) {
}); return new Promise(resolve => setTimeout(resolve, ms));
return;
}
acb("no configuration");
}, (err) => {
setImmediate(() => {
if (err) {
cb(false, err);
return;
}
cb(true);
});
});
}
} }
RegisterResourceBuildTaskFactory('z_webpack', () => webpackBuildTask); RegisterResourceBuildTaskFactory('z_webpack', () => webpackBuildTask);

View File

@ -1,6 +1,8 @@
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const child_process = require('child_process'); const child_process = require('child_process');
let buildingInProgress = false;
let currentBuildingModule = '';
const yarnBuildTask = { const yarnBuildTask = {
shouldBuild(resourceName) { shouldBuild(resourceName) {
@ -30,33 +32,49 @@ const yarnBuildTask = {
}, },
build(resourceName, cb) { build(resourceName, cb) {
const process = child_process.fork( let buildYarn = async () => {
require.resolve('./yarn_cli.js'), while (buildingInProgress) {
['install'], console.log(`yarn is busy by another process: we are waiting to compile ${resourceName}`);
{ await sleep(3000);
cwd: path.resolve(GetResourcePath(resourceName)) }
buildingInProgress = true;
currentBuildingModule = resourceName;
const process = child_process.fork(
require.resolve('./yarn_cli.js'),
['install'],
{
cwd: path.resolve(GetResourcePath(resourceName))
});
process.on('exit', (code, signal) => {
setImmediate(() => {
if (code != 0 || signal) {
buildingInProgress = false;
currentBuildingModule = '';
cb(false, 'yarn failed!');
return;
}
const resourcePath = GetResourcePath(resourceName);
const yarnLock = path.resolve(resourcePath, 'yarn.lock');
try {
fs.utimesSync(yarnLock, new Date(), new Date());
} catch (e) {
}
buildingInProgress = false;
currentBuildingModule = '';
cb(true);
});
}); });
};
process.on('exit', (code, signal) => { buildYarn().then();
setImmediate(() => {
if (code != 0 || signal) {
cb(false, 'yarn failed!');
return;
}
const resourcePath = GetResourcePath(resourceName);
const yarnLock = path.resolve(resourcePath, 'yarn.lock');
try {
fs.utimesSync(yarnLock, new Date(), new Date());
} catch (e) {
}
cb(true);
});
});
} }
} };
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
RegisterResourceBuildTaskFactory('yarn', () => yarnBuildTask); RegisterResourceBuildTaskFactory('yarn', () => yarnBuildTask);