fix: swapping config.file stopped watching it

Massimo Melina committed Mar 24, 2023 at 22:56 UTC 691a95211336d53db735748f65042a7853c93163
2 files changed +24 -20
src/block.ts
+3 -3
@@ -7,15 +7,15 @@ import cidr from 'cidr-tools'
7 import _ from 'lodash'
8 import { Socket } from 'net'
9
10 +type BlockFun = (x: string) => boolean
11 +let blockFunctions: BlockFun[] = [] // "compiled" versions of the rules in config.block
12 +
13 defineConfig<string[]>('block', []).sub(rules => {
14 compileBlock(rules)
15 for (const { socket, ip } of getConnections())
16 applyBlock(socket, ip)
17 })
18
16 -type BlockFun = (x: string) => boolean
17 -let blockFunctions: BlockFun[] = [] // "compiled" versions of the rules in config.block
18 -
19 function compileBlock(rules: any) {
20 blockFunctions = !Array.isArray(rules) ? []
21 : onlyTruthy(rules.map(rule => !rule ? null
src/watchLoad.ts
+21 -17
@@ -18,13 +18,9 @@ export function watchLoad(path:string, parser:(data:any)=>void|Promise<void>, {
18 let retry: NodeJS.Timeout
19 let saving: Promise<unknown> | undefined
20 let last: string | undefined
21 - init().then(ok => ok || failedOnFirstAttempt?.())
21 + install(true)
22 return {
23 - unwatch(){
24 - watcher?.close()
25 - clearTimeout(retry)
26 - watcher = undefined
27 - },
23 + unwatch: uninstall,
24 save(...args:Parameters<WriteFile>) {
25 return Promise.resolve(saving).then(() => // wait in case another is ongoing
26 saving = fs.writeFile(...args).finally(() => // save but also keep track of the current operation
@@ -32,35 +28,43 @@ export function watchLoad(path:string, parser:(data:any)=>void|Promise<void>, {
28 }
29 }
30
35 - async function init() {
31 + function install(first=false) {
32 try {
37 - debounced().then()
33 watcher = watch(path, ()=> {
34 if (!saving)
35 debounced().then()
36 })
42 - return true // used actually just by the first invocation
37 + debounced().catch(x=>x)
38 }
39 catch(e) {
45 - retry = setTimeout(init, 3_000) // manual watching until watch is successful
40 + retry = setTimeout(install, 3_000) // manual watching until watch is successful
41 + if (first)
42 + failedOnFirstAttempt?.()
43 }
44 }
45
46 + function uninstall() {
47 + watcher?.close()
48 + clearTimeout(retry)
49 + watcher = undefined
50 + }
51 +
52 async function load(){
53 if (doing) return
54 doing = true
55 try {
53 - const text = await readFileBusy(path)
56 + const text = await readFileBusy(path).catch(e => { // ignore read errors
57 + if (e.code === 'EPERM')
58 + console.error("missing permissions on file", path) // warn user, who could be clueless about this problem
59 + return ''
60 + })
61 if (text === last)
62 return
63 last = text
64 console.debug('loaded', path)
58 - const parsed = path.endsWith('.yaml') ? yaml.parse(text) : text
59 - await parser(parsed)
60 - }
61 - catch (e: any) { // ignore read errors
62 - if (e.code === 'EPERM')
63 - console.error("missing permissions on file", path) // warn user, who could be clueless about this problem
65 + uninstall(); install() // reinstall, as the original file could have been renamed. We watch by the name.
66 + const decoded = path.endsWith('.yaml') ? yaml.parse(text) : text
67 + await parser(decoded)
68 }
69 finally {
70 doing = false