feat: config file for refresh interval, cycle timing warning, persistent cbreak
- Optional JSON config ($PI_STAT_CONFIG, ~/.config/pi-stat/config.json, <script dir>/pi-stat.json) with refresh_interval; -i SEC overrides it - Refresh deadline anchored to cycle start; warn when a cycle takes >= 80% of the refresh interval or exceeds it - Switch the tty to cbreak once per session so keypresses made during a long cycle are not dropped - Ship pi-stat.json with the repo Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,11 +14,29 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
./pi-stat -g / --geo # With geolocation (implies -p)
|
||||
./pi-stat -s / --show-ip # Show IP column (hidden by default)
|
||||
./pi-stat -x / --extended # Show full RX/TX/RX-rate/TX-rate columns (default: ratio only)
|
||||
./pi-stat -i [SEC] / --interactive [SEC] # Interactive auto-refresh (default: 10s)
|
||||
./pi-stat -i [SEC] / --interactive [SEC] # Interactive auto-refresh (default: 5s, configurable)
|
||||
```
|
||||
|
||||
No build step. Requires `pip install docker` and a running Docker daemon. Runs on Linux, WSL2, and Windows.
|
||||
|
||||
## Configuration
|
||||
|
||||
Optional JSON config file, first match wins: `$PI_STAT_CONFIG` → `~/.config/pi-stat/config.json` → `<script dir>/pi-stat.json` (see `pi-stat.json`, shipped with the repo). Loaded by `load_config()`; missing, unreadable or non-object files fall back to defaults with a warning on stderr.
|
||||
|
||||
| Key | Default | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `refresh_interval` | `5` | Interactive auto-refresh interval in seconds (clamped to >= 1) |
|
||||
|
||||
Precedence for the refresh interval: `-i SEC` on the command line > config file > `DEFAULT_REFRESH` (5).
|
||||
|
||||
Standard JSON has no comment syntax; document settings with a `_comment` key instead (any key not read by `config_refresh()` is ignored), e.g.:
|
||||
```json
|
||||
{
|
||||
"_comment": "refresh_interval in seconds, min. 1 (default: 5)",
|
||||
"refresh_interval": 5
|
||||
}
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
Single self-contained script (`pi-stat`). Logic is split into helper functions and a `run_cycle()` function that collects data and renders one full screen, called either once (normal mode) or in a loop (interactive mode).
|
||||
@@ -49,6 +67,8 @@ Single self-contained script (`pi-stat`). Logic is split into helper functions a
|
||||
|
||||
Outbound peers are numbered in the table. Full node IDs are fetched via `peers?fullkeys=true` for the `droppeer` API call.
|
||||
|
||||
The refresh deadline is anchored to the start of the cycle (`cycle_start`), not its end, so the update's own execution time doesn't stack on top of `refresh_interval`. Execution time is measured and a warning is printed (into the same buffered screen) when a cycle takes >= `REFRESH_WARN_RATIO` (80%) of the interval, or exceeds it outright.
|
||||
|
||||
### Key patterns
|
||||
|
||||
- **Graceful degradation** — every external call is wrapped in try-except; missing data renders as `—`
|
||||
@@ -57,3 +77,6 @@ Outbound peers are numbered in the table. Full node IDs are fetched via `peers?f
|
||||
- **Validator matching** — `load_validators()` parses `stellar-core.cfg` and indexes by IP, name, and public key; matched peers show a truncated key + `(Vn)` label
|
||||
- **Geo caching** — `_geo_cache` is a module-level dict; `geo_batch()` only fetches IPs not already cached
|
||||
- **Flag parsing** — manual `sys.argv` parsing; `-g` implies `-p`; `-i` accepts an optional next argument as the refresh interval
|
||||
- **Config precedence** — `config_refresh()` reads the config value; an explicit `-i SEC` argument overrides it
|
||||
- **Cycle timing** — `interactive_loop()` measures cycle duration and warns via `warn()` when it nears or exceeds `refresh_interval`, so a slow update doesn't silently push out the actual refresh cadence
|
||||
- **Persistent cbreak** — the tty is switched to cbreak once for the whole session (not reset to canonical between cycles); doing it per-cycle would flush unread input on the mode switch and leave the terminal line-buffered during `run_cycle()`, silently dropping keypresses (e.g. `q`) made while a cycle overruns `refresh_interval`
|
||||
|
||||
Reference in New Issue
Block a user