2018-09-25 01:12:42 +02:00
|
|
|
const path = require('path');
|
|
|
|
const chokidar = require('chokidar');
|
|
|
|
const AsyncLock = require('async-lock');
|
|
|
|
|
|
|
|
|
2018-09-25 01:57:18 +02:00
|
|
|
// This script sits and waits for a build of an underlying SDK (js or react)
|
|
|
|
// to complete before exiting. This is done by cooperating with build-watch-sdk.js
|
|
|
|
// by waiting for it's signal to start watching for file changes, then watching
|
|
|
|
// the SDK's build output for a storm of file changes to stop. Both the js-sdk
|
|
|
|
// and react-sdk compile each file one by one, so by waiting for file changes to
|
|
|
|
// stop we know it is safe to continue and therefore exit this script. We give
|
|
|
|
// some leeway to the SDK's build process to handle larger/more complex files
|
|
|
|
// through use of a reset-on-touch countdown timer. When a file change occurs,
|
|
|
|
// we reset the countdown to WAIT_TIME and let it count down. If the count down
|
|
|
|
// completes, we consider ourselves having left the file system update storm and
|
|
|
|
// therefore can consider a build of the SDK to be fully completed.
|
|
|
|
|
|
|
|
// Why do we block in the first place? Because if riot-web starts it's initial
|
|
|
|
// build (via webpack-dev-server) and the react-sdk or js-sdk are halfway through
|
|
|
|
// their initial builds, then riot-web's initial build fails out of the box. This
|
|
|
|
// can sometimes be corrected by waiting for the SDK build to complete and triggering
|
|
|
|
// a file change, thereby causing a cascading build, however it isn't great if the
|
|
|
|
// initial build of riot-web fails out of the box. We block at the js-sdk first so
|
|
|
|
// that the react-sdk build doesn't fall victim to the same problem, which also
|
|
|
|
// slows down the riot-web build. After the js-sdk completes, we start the react-sdk
|
|
|
|
// build which riot-web is waiting for. When complete, riot-web starts building as
|
|
|
|
// per normal.
|
|
|
|
|
|
|
|
// Why the canary to begin watching? Because we can't reliably determine that the
|
|
|
|
// build triggered by `npm install` in each SDK is actually the process we need to
|
|
|
|
// be watching for. To work around this, build-watch-sdk.js does the `npm install`
|
|
|
|
// and follows through with a canary to signal to this script that it should start
|
|
|
|
// watching for changes produced by that SDK's `npm start` (run immediately after
|
|
|
|
// the canary is sent).
|
|
|
|
|
|
|
|
|
2018-09-25 01:12:42 +02:00
|
|
|
const WAIT_TIME = 5000; // ms
|
|
|
|
|
|
|
|
function waitForCanary(canaryName) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const filename = path.resolve(path.join(".tmp", canaryName));
|
|
|
|
|
|
|
|
// See triggerCanarySignal in build-watch-sdk.js for why we watch for `unlink`
|
|
|
|
const watcher = chokidar.watch(filename).on('unlink', (path) => {
|
|
|
|
console.log("[block-on-build] Received signal to start watching for builds");
|
|
|
|
watcher.close();
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function waitOnSdkBuild(sdkName) {
|
|
|
|
// First we wait for a local canary file to be changed
|
|
|
|
return waitForCanary(sdkName).then(() => new Promise((resolve, reject) => {
|
|
|
|
const buildDirectory = path.dirname(require.resolve(`matrix-${sdkName}-sdk`));
|
|
|
|
const lock = new AsyncLock();
|
|
|
|
let timerId = null;
|
|
|
|
|
|
|
|
const watcher = chokidar.watch(buildDirectory).on('all', (event, path) => {
|
|
|
|
lock.acquire("timer", (done) => {
|
|
|
|
if (timerId !== null) {
|
|
|
|
//console.log("Resetting countdown");
|
|
|
|
clearTimeout(timerId);
|
|
|
|
}
|
|
|
|
//console.log(`Waiting ${WAIT_TIME}ms for another file update...`);
|
|
|
|
timerId = setTimeout(() => {
|
|
|
|
console.log("[block-on-build] No updates - unblocking");
|
|
|
|
watcher.close();
|
|
|
|
resolve();
|
|
|
|
}, WAIT_TIME);
|
|
|
|
done();
|
|
|
|
}, null, null);
|
|
|
|
});
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
const sdkName = process.argv[2];
|
|
|
|
if (!sdkName) {
|
|
|
|
console.error("[block-on-build] No SDK name provided");
|
|
|
|
process.exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log("[block-on-build] Waiting for SDK: " + sdkName);
|
|
|
|
waitOnSdkBuild(sdkName).then(() => {
|
|
|
|
console.log("[block-on-build] Unblocked");
|
|
|
|
process.exit(0);
|
|
|
|
});
|