refactor(nix-monitor): rewrite most of the service code to make it a little bit more readable

This commit is contained in:
avivbintangaringga
2026-07-15 01:34:11 +07:00
parent 64bf767497
commit ba68ee6677
3 changed files with 135 additions and 107 deletions
+2 -1
View File
@@ -33,8 +33,9 @@ function displayWidget(glyph: string, text: string, color: string?)
end end
end end
-- Hooks
function update() function update()
if getState("isRunning") then if getState("isRemoteCheckRunning") then
displayWidget(barCfg("checking_glyph"), tr("bar.checking"), barCfg("checking_color")) displayWidget(barCfg("checking_glyph"), tr("bar.checking"), barCfg("checking_color"))
else else
if getState("isUpdateAvailable") then if getState("isUpdateAvailable") then
+119 -101
View File
@@ -1,5 +1,6 @@
noctalia.setUpdateInterval(1000) noctalia.setUpdateInterval(5000)
-- Helper functions
function tr(key) function tr(key)
return noctalia.tr(key) return noctalia.tr(key)
end end
@@ -20,32 +21,34 @@ function watchState(key, cb)
noctalia.state.watch(key, cb) noctalia.state.watch(key, cb)
end end
-- Vars
local branch = cfg("branch") local branch = cfg("branch")
local updateCheckInterval = cfg("check_interval") local updateCheckInterval = cfg("check_interval")
local checkDurationThreshold = cfg("check_duration_threshold") local checkDurationThreshold = cfg("check_duration_threshold")
local systemStatsCheckInterval = cfg("system_stats_check_interval") local systemStatsCheckInterval = cfg("system_stats_check_interval")
local isInit = true
local stateDir = "/tmp/nix-monitor" local stateDir = "/tmp/nix-monitor"
local localHashFile = stateDir .. "/localHash"
local remoteHashFile = stateDir .. "/remoteHash" local remoteHashFile = stateDir .. "/remoteHash"
local storeSizeFile = stateDir .. "/storeSize" local storeSizeFile = stateDir .. "/storeSize"
local closureSizeFile = stateDir .. "/closureSize" local closureSizeFile = stateDir .. "/closureSize"
local showUpdateNotification = true
local localHashCmd = "nixos-version --hash 2> /dev/null | cut -c -7 > " .. localHashFile .. " &" local localHashCmd = "nixos-version --hash 2> /dev/null | cut -c -7"
local remoteHashCmd = "git ls-remote https://github.com/NixOS/nixpkgs " .. branch .. " 2>/dev/null | cut -c 1-7 > " .. remoteHashFile .. " &" local remoteHashCmd = "git ls-remote https://github.com/NixOS/nixpkgs " .. branch .. " 2>/dev/null | cut -c 1-7"
local nixosGenerationsCmd = "nixos-rebuild list-generations | tail -n +2 | wc -l" local nixosGenerationsCmd = "nixos-rebuild list-generations | tail -n +2 | wc -l"
local nixosCurrentGenCmd = "nixos-rebuild list-generations | grep True | awk '{print $1}'" local nixosCurrentGenCmd = "nixos-rebuild list-generations | grep True | awk '{print $1}'"
local hmGenerationsCmd = "home-manager generations | wc -l" local hmGenerationsCmd = "home-manager generations | wc -l"
local hmCurrentGenCmd = "home-manager generations | grep '(current)' | awk '{print $5}'" local hmCurrentGenCmd = "home-manager generations | grep '(current)' | awk '{print $5}'"
local storeSizeCmd = `du -s --block-size=1GiB /nix/store | awk '\{print $1 " GiB"\}' > {storeSizeFile} &` local storeSizeCmd = "du -s --block-size=1GiB /nix/store | awk '\{print $1 \" GiB\"\}'"
local closureSizeCmd = `nix path-info --closure-size --human-readable /run/current-system | awk '\{print $2, $3\}' > {closureSizeFile} &` local closureSizeCmd = "nix path-info --closure-size --human-readable /run/current-system | awk '\{print $2, $3\}'"
setState("lastRunTime", os.time()) -- State inits
setState("lastCheckTime", os.time()) setState("lastLocalCheckTime", os.time())
setState("lastCheckTimeStr", "n/a") setState("lastRemoteCheckRunTime", os.time())
setState("lastRemoteCheckTime", os.time())
setState("lastRemoteCheckTimeStr", "n/a")
setState("localHash", "n/a") setState("localHash", "n/a")
setState("remoteHash", "n/a") setState("remoteHash", "n/a")
setState("isRunning", false) setState("isRemoteCheckRunning", false)
setState("isUpdateAvailable", false) setState("isUpdateAvailable", false)
setState("lastGenerationsCheckTime", 0) setState("lastGenerationsCheckTime", 0)
setState("lastSystemStatsCheckTime", 0) setState("lastSystemStatsCheckTime", 0)
@@ -58,120 +61,61 @@ setState("storeSize", "•••")
setState("closureSize", "•••") setState("closureSize", "•••")
noctalia.mkdirAll(stateDir) noctalia.mkdirAll(stateDir)
noctalia.writeFile(localHashFile, "")
noctalia.writeFile(remoteHashFile, "") noctalia.writeFile(remoteHashFile, "")
function update() -- Local check
if isInit or (os.time() - getState("lastCheckTime")) >= 60 * updateCheckInterval then function checkLocalHash()
cancelCheck() noctalia.runAsync(localHashCmd, function(res)
checkUpdate() if res.exitCode == 0 then
end setState("localHash", res.stdout)
if getState("isRunning") then
if isCheckUpdateSuccessfully() then
onHashCheckCompleted()
end end
end end)
if getState("isSystemStatsCheckRunning") then
checkSystemStatsFile()
end
if getState("isRunning") and (os.time() - getState("lastRunTime")) >= 60 * checkDurationThreshold then
cancelCheck()
end
if (os.time() - getState("lastGenerationsCheckTime")) >= 20 then
checkGenerations()
end
if (os.time() - getState("lastSystemStatsCheckTime")) >= 60 * systemStatsCheckInterval then
checkSystemStats()
end
end end
function checkUpdate() -- Remote check
if getState("isRunning") then --
-- Currently it is writing to a file because when I use the runAsync with
-- the callback, it is timed out
function checkRemoteHash(delay: number?)
local delay = delay or 0
if getState("isRemoteCheckRunning") then
return return
end end
local remoteCmd = remoteHashCmd setState("isRemoteCheckRunning", true)
setState("lastRemoteCheckRunTime", os.time())
if isInit then
remoteCmd = "sleep 10 && " .. remoteCmd
isInit = false
end
setState("lastRunTime", os.time())
if cfg("show_checking_notification") then
noctalia.notify(tr("notification.checking_update"))
end
setState("isRunning", true)
noctalia.writeFile(localHashFile, "")
noctalia.writeFile(remoteHashFile, "") noctalia.writeFile(remoteHashFile, "")
noctalia.runAsync(`sleep {delay} && {remoteHashCmd} > {remoteHashFile} &`)
noctalia.runAsync(localHashCmd)
noctalia.runAsync(remoteCmd)
end end
function isCheckUpdateSuccessfully() -- Check if the remoteHash check command is finished by reading the file
local localHash = noctalia.string.trim(noctalia.readFile(localHashFile)) function checkRemoteStatus()
local remoteHash = noctalia.string.trim(noctalia.readFile(remoteHashFile)) local remoteHash = noctalia.string.trim(noctalia.readFile(remoteHashFile))
if typeof(localHash) == "string" and localHash ~= "" then if type(remoteHash) == "string" and remoteHash ~= "" then
setState("localHash", localHash) setState("isRemoteCheckRunning", false)
end
if typeof(remoteHash) == "string" and remoteHash ~= "" then
setState("remoteHash", remoteHash) setState("remoteHash", remoteHash)
onRemoteHashCheckCompleted()
end end
local success = typeof(localHash) == "string" and localHash ~= "" and
typeof(remoteHash) == "string" and remoteHash ~= ""
if success then
onHashCheckCompleted()
end
return success
end end
function onHashCheckCompleted() function onRemoteHashCheckCompleted()
if getState("localHash") ~= getState("remoteHash") then
setState("isUpdateAvailable", true)
if cfg("show_update_notification") then
noctalia.notify(tr("notification.update_is_available"))
end
end
if cfg("show_checking_notification") then if cfg("show_checking_notification") then
noctalia.notify(tr("notification.update_check_completed")) noctalia.notify(tr("notification.update_check_completed"))
end end
setState("lastCheckTime", os.time()) setState("lastRemoteCheckTime", os.time())
noctalia.runAsync("date '+%Y-%m-%d %H:%M'", function(date) setState("lastCheckTimeStr", date.stdout) end) noctalia.runAsync("date '+%Y-%m-%d %H:%M'", function(date) setState("lastRemoteCheckTimeStr", date.stdout) end)
setState("isRunning", false)
end end
function cancelCheck() function cancelRemoteCheck()
setState("isRunning", false) setState("isRemoteCheckRunning", false)
noctalia.runAsync(`kill $(ps -ef | grep "git ls-remote https://github.com/NixOS/nixpkgs" | grep -v grep | awk '\{print $2\}')`) noctalia.runAsync(`kill $(ps -ef | grep "git ls-remote https://github.com/NixOS/nixpkgs" | grep -v grep | awk '\{print $2\}')`)
end end
watchState("command", function(command) -- Generation check
if command == "check" then
checkUpdate()
end
if command == "cancel" then
cancelCheck()
end
end)
function checkGenerations() function checkGenerations()
setState("lastGenerationsCheckTime", os.time()) setState("lastGenerationsCheckTime", os.time())
@@ -194,6 +138,7 @@ function checkGenerations()
end end
end end
-- System stats check
function checkSystemStats() function checkSystemStats()
if getState("isSystemStatsCheckRunning") then if getState("isSystemStatsCheckRunning") then
return return
@@ -202,8 +147,8 @@ function checkSystemStats()
setState("isSystemStatsCheckRunning", true) setState("isSystemStatsCheckRunning", true)
setState("lastSystemStatsCheckTime", os.time()) setState("lastSystemStatsCheckTime", os.time())
noctalia.runAsync(storeSizeCmd) noctalia.runAsync(`{storeSizeCmd} > {storeSizeFile} &`)
noctalia.runAsync(closureSizeCmd) noctalia.runAsync(`{closureSizeCmd} > {closureSizeFile} &`)
end end
function checkSystemStatsFile() function checkSystemStatsFile()
@@ -226,6 +171,79 @@ function checkSystemStatsFile()
end end
end end
-- Init
checkLocalHash()
checkRemoteHash(10)
-- Command watcher
watchState("command", function(command)
if command == "check" then
checkLocalHash()
cancelRemoteCheck()
checkRemoteHash()
checkGenerations()
checkSystemStats()
end
if command == "cancel" then
cancelRemoteCheck()
end
end)
--
-- Hooks
--
function update()
-- Check local hash every 10 seconds
if (os.time() - getState("lastLocalCheckTime") >= 10) then
checkLocalHash()
end
-- Remote check
if (os.time() - getState("lastRemoteCheckTime")) >= 60 * updateCheckInterval then
checkRemoteHash()
end
if getState("isRemoteCheckRunning") then
checkRemoteStatus()
-- Remote check timeout
if (os.time() - getState("lastRemoteCheckRunTime")) >= 60 * checkDurationThreshold then
cancelRemoteCheck()
end
end
if getState("localHash") ~= getState("remoteHash") and
getState("localHash") ~= "n/a" and getState("remoteHash") ~= "n/a"
then
setState("isUpdateAvailable", true)
if cfg("show_update_notification") and showUpdateNotification then
noctalia.notify(tr("notification.update_is_available"))
showUpdateNotification = false
end
else
setState("isUpdateAvailable", false)
showUpdateNotification = true
end
-- Generations check
if (os.time() - getState("lastGenerationsCheckTime")) >= 20 then
checkGenerations()
end
-- System stats check
if (os.time() - getState("lastSystemStatsCheckTime")) >= 60 * systemStatsCheckInterval then
checkSystemStats()
end
if getState("isSystemStatsCheckRunning") then
checkSystemStatsFile()
end
end
function onExit(signal) function onExit(signal)
cancelCheck() cancelRemoteCheck()
end end
+14 -5
View File
@@ -1,3 +1,5 @@
-- Helper functions
function tr(key) function tr(key)
return noctalia.tr(key) return noctalia.tr(key)
end end
@@ -48,7 +50,7 @@ local function labelBox(subtext, text, glyph)
}) })
end end
function statLabel(text, glyph: string?) local function statLabel(text, glyph: string?)
local items = {} local items = {}
if glyph ~= nil then if glyph ~= nil then
table.insert(items, ui.glyph({ table.insert(items, ui.glyph({
@@ -72,7 +74,7 @@ end
local function render() local function render()
local firstBtn = btnCheck local firstBtn = btnCheck
if getState("isRunning") then if getState("isRemoteCheckRunning") then
firstBtn = ui.button({ firstBtn = ui.button({
text = tr("panel.cancel"), text = tr("panel.cancel"),
glyph = "cancel", glyph = "cancel",
@@ -100,7 +102,7 @@ local function render()
end end
end end
local lastCheckTimeStr = getState("lastCheckTimeStr") local lastCheckTimeStr = getState("lastRemoteCheckTimeStr")
local generationItems = { local generationItems = {
statLabel(`SYS: {getState("nixosGenerations")}`, "device-desktop"), statLabel(`SYS: {getState("nixosGenerations")}`, "device-desktop"),
statLabel(`{tr("panel.current")}: {getState("nixosCurrentGen")}`, "device-desktop-check") statLabel(`{tr("panel.current")}: {getState("nixosCurrentGen")}`, "device-desktop-check")
@@ -200,15 +202,22 @@ local function render()
) )
end end
watchState("isRunning", render) -- State watcher
watchState("lastCheckTimeStr", render) watchState("isRemoteCheckRunning", render)
watchState("lastRemoteCheckTimeStr", render)
watchState("localHash", render) watchState("localHash", render)
watchState("remoteHash", render) watchState("remoteHash", render)
-- Hooks
function onOpen(_ctx) function onOpen(_ctx)
render() render()
end end
function update()
render()
end
-- Click handler
function onCheckClicked() function onCheckClicked()
setState("command", "check") setState("command", "check")
end end