@samitouri / QOSami-HFS / commits / da52e606

better code

Massimo Melina committed May 3, 2026 at 12:27 UTC da52e60665ec582869936705958d79fe4f1899f6
2 files changed +17 -16
src/misc.ts
+15 -2
@@ -1,6 +1,6 @@
1 // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3 -import { basename } from 'path'
3 +import { basename, dirname, join } from 'path'
4 import Koa from 'koa'
5 import { Connection } from './connections'
6 export * from './util-http'
@@ -13,7 +13,7 @@ import { Readable, Transform } from 'stream'
13 import { SocketAddress, BlockList } from 'node:net'
14 import { ApiError } from './apiMiddleware'
15 import { HTTP_BAD_REQUEST } from './const'
16 -import { isIpLocalHost, makeMatcher, try_ } from './cross'
16 +import { Callback, isIpLocalHost, makeMatcher, try_ } from './cross'
17 import { isIPv6 } from 'net'
18 import _ from 'lodash'
19
@@ -129,3 +129,16 @@ export function createStreamLimiter(limit: number) {
129 }
130 })
131 }
132 +
133 +export function retrySync(cb: Callback, attempts=20, sleep=500) {
134 + const sleepSyncBuffer = new Int32Array(new SharedArrayBuffer(4))
135 + for (let retry = 0; ; retry++) {
136 + try { return cb() }
137 + catch (e: any) {
138 + if (e?.code !== 'EBUSY' || retry >= attempts)
139 + throw e
140 + Atomics.wait(sleepSyncBuffer, 0, 0, sleep)
141 + }
142 + }
143 +}
144 +
src/update.ts
+2 -14
@@ -5,7 +5,7 @@ import { ARGS_FILE, HFS_REPO, IS_BINARY, IS_WINDOWS, IS_MAC, PREVIOUS_TAG, RUNNI
5 import { dirname, join } from 'path'
6 import { spawn, spawnSync } from 'child_process'
7 import {
8 - DAY, exists, unzip, prefix, xlate, HOUR, httpStream, statWithTimeout, repeat, debounceAsync, formatPerc
8 + DAY, exists, unzip, prefix, xlate, HOUR, httpStream, statWithTimeout, repeat, debounceAsync, formatPerc, retrySync
9 } from './misc'
10 import { createReadStream, createWriteStream, existsSync, renameSync, unlinkSync, writeFileSync } from 'fs'
11 import { pluginsWatcher } from './plugins'
@@ -192,7 +192,7 @@ export async function update(tagOrUrl: string='') {
192 catch {}
193 renameSync(bin, oldBin)
194 if (!preserveTerminal) {
195 - try { renameSyncWithBusyRetry(newBin, join(binPath, binFile)) }
195 + try { retrySync(() => renameSync(newBin, join(binPath, binFile))) }
196 catch (e) {
197 try { renameSync(oldBin, bin) } // restore the service target because hfs.exe was already moved aside
198 catch (rollbackError) { console.error("Couldn't restore original binary after failed update", rollbackError) }
@@ -215,18 +215,6 @@ export async function update(tagOrUrl: string='') {
215 }
216 }
217
218 -function renameSyncWithBusyRetry(src: string, dest: string) {
219 - const sleepSyncBuffer = new Int32Array(new SharedArrayBuffer(4))
220 - for (let retry = 0; ; retry++) {
221 - try { return renameSync(src, dest) }
222 - catch (e: any) {
223 - if (e?.code !== 'EBUSY' || retry >= 20)
224 - throw e
225 - Atomics.wait(sleepSyncBuffer, 0, 0, 500)
226 - }
227 - }
228 -}
229 -
218 if (argv.updating) { // we were launched with a temporary name, restore original name to avoid breaking references
219 const bin = process.execPath
220 const dest = join(dirname(bin), argv.updating)