diff --git a/backend/langs.js b/backend/langs.js index 7225d96..db9f11c 100644 --- a/backend/langs.js +++ b/backend/langs.js @@ -1,36 +1,47 @@ -import { promises as fs } from "fs"; +import fsOrig, { promises as fs } from "fs"; import path from "path"; +import debounce from "debounce"; + import { log } from "./util.js"; // Map from language IDs to language configuration objects. This is // populated at runtime and updated asynchronously. export let langs = {}; +// Read languages from JSON files in /opt/riju/langs, and update the +// global langs variable in this module. Never throw an error. If +// there is a problem then just leave the languages as they previously +// were. async function readLangsFromDisk() { - const newLangs = {}; - for (const filename of await fs.readdir("/opt/riju/langs")) { - if (path.parse(filename).ext !== ".json") { - continue; - } - const id = path.parse(filename).name; - const langConfig = JSON.parse( - await fs.readFile(`/opt/riju/langs/${filename}`, "utf-8") - ); - if (langConfig.id !== id) { - log.error( - "Language config ${filename} has mismatched language ID ${id}, ignoring" + try { + const newLangs = {}; + for (const filename of await fs.readdir("/opt/riju/langs")) { + if (path.parse(filename).ext !== ".json") { + continue; + } + const id = path.parse(filename).name; + const langConfig = JSON.parse( + await fs.readFile(`/opt/riju/langs/${filename}`, "utf-8") ); - continue; + if (langConfig.id !== id) { + log.error( + "Language config ${filename} has mismatched language ID ${id}, ignoring" + ); + continue; + } + newLangs[id] = langConfig; } - newLangs[id] = langConfig; + log.info( + `Loaded ${ + Object.keys(newLangs).length + } language configuration(s) from disk` + ); + langs = newLangs; + } catch (err) { + log.error("Failed to read languages from disk:", err); } - log.info( - `Loaded ${Object.keys(newLangs).length} language configuration(s) from disk` - ); - langs = newLangs; } -readLangsFromDisk().catch((err) => { - log.error("Failed to read languages from disk:", err); -}); +readLangsFromDisk(); +fsOrig.watch("/opt/riju/langs", debounce(readLangsFromDisk, 200)); diff --git a/docker/runtime/install.bash b/docker/runtime/install.bash index af904fc..382ffb5 100755 --- a/docker/runtime/install.bash +++ b/docker/runtime/install.bash @@ -47,6 +47,9 @@ tee /etc/sudoers.d/90-riju >/dev/null <<"EOF" %sudo ALL=(ALL:ALL) NOPASSWD: ALL EOF +mkdir -p /opt/riju/langs +touch /opt/riju/langs/.keep + popd rm "$0" diff --git a/package.json b/package.json index 4215bad..f5c0e12 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "buffer": "^6.0.3", "commander": "^6.2.1", "css-loader": "^5.0.1", + "debounce": "^1.2.0", "ejs": "^3.1.5", "express": "^4.17.1", "express-ws": "^4.0.0", diff --git a/tools/ci-run.bash b/tools/ci-run.bash index f4757bb..f9b0801 100755 --- a/tools/ci-run.bash +++ b/tools/ci-run.bash @@ -2,6 +2,6 @@ set -euo pipefail -echo "${DOCKER_PASSWORD}" | docker login --username "${DOCKER_USERNAME}" --password-stdin +echo "${DOCKER_PASSWORD}" | sudo -E docker login --username "${DOCKER_USERNAME}" --password-stdin make publish diff --git a/yarn.lock b/yarn.lock index b047f70..3d30858 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1302,6 +1302,11 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +debounce@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" + integrity sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg== + debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"