Skip to content

status: prepend a one-glance live summary (hashrate, pool, shares) from the worker API #143

Description

@VijitSingh97

Why

status today is a thin passthrough: svc_status (rigforge.sh:2603-2610) runs systemctl status on Linux and mac_status (rigforge.sh:2534-2545) prints one "running / not running" line on macOS. Neither answers the question an operator actually walks up with: is it hashing, at what rate, on which pool, and are shares landing? Today that takes logs plus squinting, or a manual curl against the worker API. The API already has everything in one endpoint (/2/summary), and RigForge already has a tested reader for it (_read_api_hashrate, rigforge.sh:2328-2343). One fetch, five lines, done.

Scope

  • When the miner is up, status prints a compact RigForge summary block FIRST, then the existing platform block (systemd on Linux, the mac_status line on macOS) unchanged below it. Summary first because it's the glance; systemd detail is the drill-down.
  • Summary fields, all from ONE /2/summary fetch: hashrate (.hashrate.total[0]), pool + connection (.connection.pool), miner uptime (.uptime, seconds — render as 1d 4h 23m), accepted/rejected shares (.connection.accepted / .connection.rejected), huge pages (.hugepages // empty — the field exists on our pinned XMRig 6.26.0; verify during implementation and drop the line silently if empty).
  • No sudo, ever — keep the existing comment at rigforge.sh:2608 ("don't prompt for a password to look") and extend its spirit to the new block. No log-file grep for huge pages: the service log can be root-owned, and doctor already owns the log-based check (rigforge.sh:3018-3023). The API field or nothing.
  • Degrade gracefully: API unreachable (miner stopped, still starting, or http disabled) → the platform block prints exactly as today, plus one line: RigForge: worker API not reachable at 127.0.0.1:8080 (miner stopped or still starting).
  • macOS gets the identical summary block appended to mac_status — the API runs there too (the miner is a nohup background process or a launchd login agent, rigforge.sh:2494-2545, using the same generated config with the same http block).
  • Output format decision: plain aligned printf ' %-10s %s\n' "Hashrate:" "..." key/value lines — NOT the _ck_ok/_ck_warn/ markers (rigforge.sh:2735-2737). Rationale: status reports facts; ✓/! imply a pass/fail judgment, which is doctor's job. Plain lines also stay grep-friendly.

Out of scope: watchdog logic, thresholds, exit codes based on hashrate, --json output. No new config keys — the summary is derived entirely from the existing API and ACCESS_TOKEN handling.

Acceptance criteria

  • status with an active miner shows hashrate, pool URL, uptime, accepted/rejected shares in one block, then the unchanged systemd output; total of ONE curl to the API.
  • status with the miner stopped shows the systemd block exactly as today plus the single "worker API not reachable" line; exit code unchanged (still 0).
  • With ACCESS_TOKEN set in config.json, the fetch sends the Bearer header; without it, no Authorization header (same contract as _read_api_hashrate — the existing Bearer test at tests/run.sh:1463-1486 stays green untouched).
  • status never invokes sudo and never prompts.
  • Works on macOS: status with a running miner shows the same summary block after the existing mac_status line.
  • A missing or invalid config.json cannot crash status — the platform block still prints.
  • Tests cover: summary rendering from a stubbed API body, the unreachable branch, and the Bearer/no-Bearer paths. make lint clean; suite passes on macOS bash 3.2 and Linux.

Implementation notes

Numbered, mechanical. All design decisions are made — do not reopen them.

  1. Extract _read_api_summary() directly above _read_api_hashrate (rigforge.sh:2328). Move the curl + Bearer-branch body there verbatim (the branch comment at rigforge.sh:2335-2337 moves with it — it documents a real 401/set-e trap), minus the trailing jq. It prints the raw /2/summary JSON, or nothing if curl is missing/unreachable.
  2. Rewire _read_api_hashrate to keep its exact external contract: the API_CMD eval branch stays FIRST and unchanged (tests at tests/run.sh:1309, 1338, 1362, 1403 stub it with a bare number — API_CMD output bypasses jq, do not route it through _read_api_summary); otherwise _read_api_summary | jq -r '.hashrate.total[0] // empty' 2>/dev/null.
  3. New _status_api_summary() near svc_status (rigforge.sh:2603): fetch once into a local (body=$(_read_api_summary)), bail with the one-line unreachable message if empty, else ONE jq -r extracting all fields (a single jq invocation emitting tab-separated values, read into locals — one fork, bash-3.2-safe), then the aligned printf block. Render uptime seconds as Nd Nh Nm with a tiny arithmetic helper (integer math only; no bc).
  4. parse_config inside a subshell. ACCESS_TOKEN only exists after parse_config, and parse_config calls error (which exit 1s) on a bad config — || true does NOT catch exit in the current shell. So svc_status runs the whole summary as ( parse_config >/dev/null 2>&1 && _status_api_summary ) || true — a bad/missing config degrades to just the platform block.
  5. svc_status becomes: subshell summary (note 4), then the existing systemctl status ... || true line unchanged (keep the rigforge.sh:2608 no-sudo comment). mac_status (rigforge.sh:2534): keep its current lines, append the same subshell summary call at the end. OS_TYPE gating is already handled by the svc_status dispatch at rigforge.sh:2604-2607.
  6. Docs: update the status line in usage() (rigforge.sh:3049, "show whether the miner is running" → mention the live summary) and the corresponding line in docs/operations.md.
  7. Tests (tests/run.sh): extend the curl stub at tests/run.sh:173-179 — its printf body currently emits only {"hashrate":...}; add connection (pool/accepted/rejected/uptime), top-level uptime, and hugepages fields (existing assertions only parse hashrate, so this is additive). Copy the subshell-runner shape of the doctor block (tests/run.sh:1921-1966: run_doctor() sources $SCRIPT, overrides paths, captures output; assert_contains at tests/run.sh:43). New block: (a) source + PATH="$STUBS:$PATH" + call svc_status with a stubbed systemctl, assert pool/hashrate/accepted values appear; (b) point curl at a failing stub (exit 7) and assert the "not reachable" line plus the systemctl passthrough; (c) re-run the existing Bearer assertions pattern against _read_api_summary if the refactor moved the header logic (the feat: worker HTTP API open (read-only) by default #125 block at tests/run.sh:1463-1486 must stay green as-is).
  8. Verification: make lint (shellcheck 0.11 warning + shfmt -i 4), make test, then on miner-0: rigforge status while mining (summary + systemd), sudo systemctl stop xmrig && rigforge status (unreachable line + inactive systemd block), and once with ACCESS_TOKEN set.

Pitfalls: bash 3.2 (no associative arrays, no ${var,,}); set -Eeuo pipefail — every jq/curl in the summary path needs || true/// empty guards so a half-up API can't abort status; exit inside error/parse_config is only containable in a subshell (note 4); don't print ACCESS_TOKEN anywhere; no new config keys, so config.reference.json is untouched.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions