aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2021-12-26 13:08:28 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2021-12-26 13:13:00 +0100
commit731f3808ed1bf2d839b408a4ac43c66ad859885a (patch)
treee01b221e37cd0721d5535da264795b735b71d919
parentfeat: Config persistence (diff)
downloadsophie-731f3808ed1bf2d839b408a4ac43c66ad859885a.tar.gz
sophie-731f3808ed1bf2d839b408a4ac43c66ad859885a.tar.zst
sophie-731f3808ed1bf2d839b408a4ac43c66ad859885a.zip
refactor: Improved config reloading
If we watch the containing directory, we can use inotify instead of stat polling.
-rw-r--r--packages/main/src/index.ts45
1 files changed, 34 insertions, 11 deletions
diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts
index a79a6e2..605c17c 100644
--- a/packages/main/src/index.ts
+++ b/packages/main/src/index.ts
@@ -25,8 +25,13 @@ import {
25 ipcMain, 25 ipcMain,
26 nativeTheme, 26 nativeTheme,
27} from 'electron'; 27} from 'electron';
28import { readFileSync, watchFile } from 'fs'; 28import { readFileSync } from 'fs';
29import { readFile, stat, writeFile } from 'fs/promises'; 29import {
30 readFile,
31 stat,
32 watch,
33 writeFile,
34} from 'fs/promises';
30import { autorun } from 'mobx'; 35import { autorun } from 'mobx';
31import { 36import {
32 applySnapshot, 37 applySnapshot,
@@ -121,7 +126,9 @@ nativeTheme.on('updated', () => {
121 store.setShouldUseDarkColors(nativeTheme.shouldUseDarkColors); 126 store.setShouldUseDarkColors(nativeTheme.shouldUseDarkColors);
122}); 127});
123 128
124const configPath = join(app.getPath('userData'), 'config.json'); 129const userDataDir = app.getPath('userData');
130const configFileName = 'config.json';
131const configPath = join(userDataDir, configFileName);
125let loadingConfig = false; 132let loadingConfig = false;
126let savingConfig = false; 133let savingConfig = false;
127let configMtime: Date | null = null; 134let configMtime: Date | null = null;
@@ -175,21 +182,37 @@ onSnapshot(store.config, (snapshot) => {
175 } 182 }
176}); 183});
177 184
178async function initializeConfig(): Promise<void> { 185async function watchConfig(): Promise<void> {
179 await loadConfig(); 186 const configWatcher = watch(userDataDir, {
180 watchFile(configPath, ({ mtime }) => { 187 persistent: false,
188 });
189 for await (const { eventType, filename } of configWatcher) {
190 if (eventType !== 'change'
191 && (filename !== configFileName || filename !== null)) {
192 continue;
193 }
194 let mtime: Date;
195 try {
196 const stats = await stat(configPath);
197 mtime = stats.mtime;
198 } catch (err) {
199 if ((err as NodeJS.ErrnoException).code === 'ENOENT') {
200 continue;
201 }
202 throw err;
203 }
181 if (!savingConfig && (configMtime === null || mtime > configMtime)) { 204 if (!savingConfig && (configMtime === null || mtime > configMtime)) {
182 loadConfig().catch((err) => { 205 await loadConfig();
183 console.error('Failed to reload config', configPath, err);
184 });
185 configMtime = mtime; 206 configMtime = mtime;
186 console.log('Reloaded config', configPath); 207 console.log('Reloaded config', configPath);
187 } 208 }
188 }); 209 }
189} 210}
190 211
191initializeConfig().catch((err) => { 212loadConfig().catch((err) => {
192 console.error('Failed to load config', configPath, err); 213 console.error('Failed to load config', configPath, err);
214}).then(watchConfig).catch((err) => {
215 console.error('Error when watching for config changes', configPath, err);
193}); 216});
194 217
195const rendererBaseUrl = getResourceUrl('../renderer/'); 218const rendererBaseUrl = getResourceUrl('../renderer/');