From ba68ee667716cd395621a43733db34beac6b10e5 Mon Sep 17 00:00:00 2001 From: avivbintangaringga Date: Wed, 15 Jul 2026 01:34:11 +0700 Subject: [PATCH] refactor(nix-monitor): rewrite most of the service code to make it a little bit more readable --- nix-monitor/nix_monitor.luau | 3 +- nix-monitor/nix_monitor_service.luau | 220 +++++++++++++++------------ nix-monitor/panel.luau | 19 ++- 3 files changed, 135 insertions(+), 107 deletions(-) diff --git a/nix-monitor/nix_monitor.luau b/nix-monitor/nix_monitor.luau index b65d110..20d972a 100644 --- a/nix-monitor/nix_monitor.luau +++ b/nix-monitor/nix_monitor.luau @@ -33,8 +33,9 @@ function displayWidget(glyph: string, text: string, color: string?) end end +-- Hooks function update() - if getState("isRunning") then + if getState("isRemoteCheckRunning") then displayWidget(barCfg("checking_glyph"), tr("bar.checking"), barCfg("checking_color")) else if getState("isUpdateAvailable") then diff --git a/nix-monitor/nix_monitor_service.luau b/nix-monitor/nix_monitor_service.luau index 11be4b4..9f25111 100644 --- a/nix-monitor/nix_monitor_service.luau +++ b/nix-monitor/nix_monitor_service.luau @@ -1,5 +1,6 @@ -noctalia.setUpdateInterval(1000) +noctalia.setUpdateInterval(5000) +-- Helper functions function tr(key) return noctalia.tr(key) end @@ -20,32 +21,34 @@ function watchState(key, cb) noctalia.state.watch(key, cb) end +-- Vars local branch = cfg("branch") local updateCheckInterval = cfg("check_interval") local checkDurationThreshold = cfg("check_duration_threshold") local systemStatsCheckInterval = cfg("system_stats_check_interval") -local isInit = true local stateDir = "/tmp/nix-monitor" -local localHashFile = stateDir .. "/localHash" local remoteHashFile = stateDir .. "/remoteHash" local storeSizeFile = stateDir .. "/storeSize" local closureSizeFile = stateDir .. "/closureSize" +local showUpdateNotification = true -local localHashCmd = "nixos-version --hash 2> /dev/null | cut -c -7 > " .. localHashFile .. " &" -local remoteHashCmd = "git ls-remote https://github.com/NixOS/nixpkgs " .. branch .. " 2>/dev/null | cut -c 1-7 > " .. remoteHashFile .. " &" +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" local nixosGenerationsCmd = "nixos-rebuild list-generations | tail -n +2 | wc -l" local nixosCurrentGenCmd = "nixos-rebuild list-generations | grep True | awk '{print $1}'" local hmGenerationsCmd = "home-manager generations | wc -l" 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 closureSizeCmd = `nix path-info --closure-size --human-readable /run/current-system | awk '\{print $2, $3\}' > {closureSizeFile} &` +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\}'" -setState("lastRunTime", os.time()) -setState("lastCheckTime", os.time()) -setState("lastCheckTimeStr", "n/a") +-- State inits +setState("lastLocalCheckTime", os.time()) +setState("lastRemoteCheckRunTime", os.time()) +setState("lastRemoteCheckTime", os.time()) +setState("lastRemoteCheckTimeStr", "n/a") setState("localHash", "n/a") setState("remoteHash", "n/a") -setState("isRunning", false) +setState("isRemoteCheckRunning", false) setState("isUpdateAvailable", false) setState("lastGenerationsCheckTime", 0) setState("lastSystemStatsCheckTime", 0) @@ -58,120 +61,61 @@ setState("storeSize", "•••") setState("closureSize", "•••") noctalia.mkdirAll(stateDir) -noctalia.writeFile(localHashFile, "") noctalia.writeFile(remoteHashFile, "") -function update() - if isInit or (os.time() - getState("lastCheckTime")) >= 60 * updateCheckInterval then - cancelCheck() - checkUpdate() - end - - if getState("isRunning") then - if isCheckUpdateSuccessfully() then - onHashCheckCompleted() +-- Local check +function checkLocalHash() + noctalia.runAsync(localHashCmd, function(res) + if res.exitCode == 0 then + setState("localHash", res.stdout) 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() - if getState("isRunning") then +-- Remote check +-- +-- 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 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.runAsync(localHashCmd) - noctalia.runAsync(remoteCmd) + noctalia.runAsync(`sleep {delay} && {remoteHashCmd} > {remoteHashFile} &`) end -function isCheckUpdateSuccessfully() - local localHash = noctalia.string.trim(noctalia.readFile(localHashFile)) +-- Check if the remoteHash check command is finished by reading the file +function checkRemoteStatus() local remoteHash = noctalia.string.trim(noctalia.readFile(remoteHashFile)) - if typeof(localHash) == "string" and localHash ~= "" then - setState("localHash", localHash) - end - - if typeof(remoteHash) == "string" and remoteHash ~= "" then + if type(remoteHash) == "string" and remoteHash ~= "" then + setState("isRemoteCheckRunning", false) setState("remoteHash", remoteHash) + onRemoteHashCheckCompleted() end - - local success = typeof(localHash) == "string" and localHash ~= "" and - typeof(remoteHash) == "string" and remoteHash ~= "" - - if success then - onHashCheckCompleted() - end - - return success end -function onHashCheckCompleted() - if getState("localHash") ~= getState("remoteHash") then - setState("isUpdateAvailable", true) - if cfg("show_update_notification") then - noctalia.notify(tr("notification.update_is_available")) - end - end - +function onRemoteHashCheckCompleted() if cfg("show_checking_notification") then noctalia.notify(tr("notification.update_check_completed")) end - setState("lastCheckTime", os.time()) - noctalia.runAsync("date '+%Y-%m-%d %H:%M'", function(date) setState("lastCheckTimeStr", date.stdout) end) - - setState("isRunning", false) + setState("lastRemoteCheckTime", os.time()) + noctalia.runAsync("date '+%Y-%m-%d %H:%M'", function(date) setState("lastRemoteCheckTimeStr", date.stdout) end) end -function cancelCheck() - setState("isRunning", false) +function cancelRemoteCheck() + setState("isRemoteCheckRunning", false) noctalia.runAsync(`kill $(ps -ef | grep "git ls-remote https://github.com/NixOS/nixpkgs" | grep -v grep | awk '\{print $2\}')`) end -watchState("command", function(command) - if command == "check" then - checkUpdate() - end - - if command == "cancel" then - cancelCheck() - end -end) - +-- Generation check function checkGenerations() setState("lastGenerationsCheckTime", os.time()) @@ -194,6 +138,7 @@ function checkGenerations() end end +-- System stats check function checkSystemStats() if getState("isSystemStatsCheckRunning") then return @@ -202,8 +147,8 @@ function checkSystemStats() setState("isSystemStatsCheckRunning", true) setState("lastSystemStatsCheckTime", os.time()) - noctalia.runAsync(storeSizeCmd) - noctalia.runAsync(closureSizeCmd) + noctalia.runAsync(`{storeSizeCmd} > {storeSizeFile} &`) + noctalia.runAsync(`{closureSizeCmd} > {closureSizeFile} &`) end function checkSystemStatsFile() @@ -226,6 +171,79 @@ function checkSystemStatsFile() 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) - cancelCheck() + cancelRemoteCheck() end diff --git a/nix-monitor/panel.luau b/nix-monitor/panel.luau index 521382e..37def09 100644 --- a/nix-monitor/panel.luau +++ b/nix-monitor/panel.luau @@ -1,3 +1,5 @@ +-- Helper functions + function tr(key) return noctalia.tr(key) end @@ -48,7 +50,7 @@ local function labelBox(subtext, text, glyph) }) end -function statLabel(text, glyph: string?) +local function statLabel(text, glyph: string?) local items = {} if glyph ~= nil then table.insert(items, ui.glyph({ @@ -72,7 +74,7 @@ end local function render() local firstBtn = btnCheck - if getState("isRunning") then + if getState("isRemoteCheckRunning") then firstBtn = ui.button({ text = tr("panel.cancel"), glyph = "cancel", @@ -100,7 +102,7 @@ local function render() end end - local lastCheckTimeStr = getState("lastCheckTimeStr") + local lastCheckTimeStr = getState("lastRemoteCheckTimeStr") local generationItems = { statLabel(`SYS: {getState("nixosGenerations")}`, "device-desktop"), statLabel(`{tr("panel.current")}: {getState("nixosCurrentGen")}`, "device-desktop-check") @@ -200,15 +202,22 @@ local function render() ) end -watchState("isRunning", render) -watchState("lastCheckTimeStr", render) +-- State watcher +watchState("isRemoteCheckRunning", render) +watchState("lastRemoteCheckTimeStr", render) watchState("localHash", render) watchState("remoteHash", render) +-- Hooks function onOpen(_ctx) render() end +function update() + render() +end + +-- Click handler function onCheckClicked() setState("command", "check") end