Run hooks

This commit is contained in:
Lynn Smeria 2020-03-18 19:57:56 +02:00
parent 0e380a26ba
commit 5e71de7f55
2 changed files with 48 additions and 7 deletions

View file

@ -2,6 +2,7 @@ const fs = require('fs').promises;
const ms = require('ms'); const ms = require('ms');
const os = require('os'); const os = require('os');
const path = require('path'); const path = require('path');
const { spawn } = require('child_process');
const getHooksRoot = () => path.join(os.homedir(), '/.syncthing-hooks'); const getHooksRoot = () => path.join(os.homedir(), '/.syncthing-hooks');
@ -9,7 +10,8 @@ const readHooksRoot = async root => {
try { try {
const files = await fs.readdir(root); const files = await fs.readdir(root);
return files; return files;
} catch { } catch (error) {
console.error(error);
return []; return [];
} }
}; };
@ -33,6 +35,26 @@ const collectHooks = async () => {
return parseHooks(root, hooks); return parseHooks(root, hooks);
}; };
const waitForProcess = childProcess =>
new Promise((resolve, reject) => {
childProcess.once('exit', code =>
code === 0
? resolve(null)
: reject(new Error(`hook failed with code: ${code}`))
);
childProcess.once('error', error => reject(error));
});
const runHook = hook =>
waitForProcess(
spawn(hook.path, [], {
cwd: path.dirname(hook.path),
shell: true,
stdio: [process.stdin, process.stdout, process.stderr],
})
);
module.exports = { module.exports = {
collectHooks, collectHooks,
runHook,
}; };

31
index.js Normal file → Executable file
View file

@ -1,11 +1,12 @@
const { fetchNewEvents } = require('./api'); const { fetchNewEvents } = require('./api');
const { collectHooks } = require('./hooks'); const { collectHooks, runHook } = require('./hooks');
require('dotenv').config(); require('dotenv').config();
const state = { const state = {
seenIds: null, seenIds: null,
mostRecentEventForFolder: null, mostRecentEventForFolder: null,
promisesForHooks: new Map(),
}; };
const getMostRecentEvents = (events, monitoredFolders) => { const getMostRecentEvents = (events, monitoredFolders) => {
@ -50,13 +51,31 @@ setInterval(async () => {
.filter(x => deltaForFolders[x.folder]) .filter(x => deltaForFolders[x.folder])
.forEach(hook => { .forEach(hook => {
const timeToWait = hook.time - deltaForFolders[hook.folder]; const timeToWait = hook.time - deltaForFolders[hook.folder];
console.log(timeToWait); console.log(`scheduled hook "${hook.path}" to run in ${timeToWait}ms`);
if (timeToWait < 0) { if (timeToWait < 0) {
delete state.mostRecentEventForFolder[hook.folder]; const existingPromise = state.promisesForHooks[hook.path];
console.log('running hook', hook); if (existingPromise) {
console.log(
`hook "${hook.path}" was skipped because it is already running`
);
} else {
delete state.mostRecentEventForFolder[hook.folder];
console.log(`running hook "${hook.path}"`);
const promise = runHook(hook);
state.promisesForHooks[hook.path] = promise;
promise
.then(() => {
console.log(`successfully ran hook "${hook.path}"`);
})
.catch(error => {
console.error(`failed to run hook "${hook.path}": ${error}`);
})
.finally(() => {
delete state.promisesForHooks[hook.path];
});
}
} }
}); });
console.warn(deltaForFolders);
state.seenIds = seenIds; state.seenIds = seenIds;
}, 2000); }, 30000);