askrene-migration: contrib script robustness + de-flake coalesce test
Some checks are pending
Code Base Sanity Check / tests (push) Waiting to run
Code Base Sanity Check / coverage (push) Waiting to run
Code Base Sanity Check / build-clang (push) Waiting to run

Three fixes from the 2026-06-29 CodeRabbit pass on PR #320.

clboss-askrene-layer-summary: load_layers() now catches OSError and
JSONDecodeError on the --input replay path and exits with a message
instead of crashing with a traceback on a missing file or malformed
JSON. This is the offline mode the help text advertises.

clboss-askrene-layer-summary: reject --json together with --top. The
combination previously printed a JSON object and then appended a
human-readable top section, producing invalid mixed-format output.
The top list is human-readable only.

test_askrene_layer: pin the coalescing bucket window astronomically
large in test_coalesce_drops_dominated so both writes always land in
the same Ev::now()/window bucket. Previously a run straddling a bucket
boundary re-emitted the dominated write as a keep-alive and failed the
sentinel assertion. It is the final test before Shutdown, so the global
window needs no restore.
This commit is contained in:
Ken Sedgwick 2026-06-29 11:04:34 -07:00
parent 16ee4d0f62
commit 4f1b56aad0
No known key found for this signature in database
GPG key ID: DBD2AF0849D711A9
2 changed files with 23 additions and 2 deletions

View file

@ -128,8 +128,15 @@ def percentile(sorted_vals, q):
def load_layers(args, network_option):
if args.input is not None:
raw = sys.stdin.read() if args.input == "-" else open(args.input).read()
return json.loads(raw).get("layers", [])
try:
if args.input == "-":
raw = sys.stdin.read()
else:
with open(args.input) as f:
raw = f.read()
return json.loads(raw).get("layers", [])
except (OSError, json.JSONDecodeError) as e:
sys.exit(f"failed to load --input data: {e}")
res = run_lightning_cli_command(
args.lightning_dir, network_option, "askrene-listlayers", args.layer
)
@ -239,6 +246,10 @@ def main():
s = summarize(target)
depth = s.pop("_depth")
if args.json and args.top > 0:
sys.exit("--json cannot be combined with --top "
"(the top list is human-readable only)")
if args.json:
print(json.dumps(s, indent=2))
else:

View file

@ -320,6 +320,16 @@ test_coalesce_drops_dominated( MockRpcServer& server
) {
auto const layer = std::string("coalesce-layer");
/* Pin the coalescing bucket astronomically large so both writes
* below always land in the same Ev::now()/window bucket regardless
* of when the test runs; otherwise a run straddling a bucket
* boundary re-emits the dominated write as a keep-alive and
* assert_sentinel fires spuriously. This is the final test before
* Shutdown, so the global window needs no restore. */
Boss::Mod::AskreneLayer::set_aging_window_secs(
std::uint64_t(1000) * 365 * 24 * 60 * 60
);
auto assert_first = [](Jsmn::Object const& req) {
auto id = assert_method(req, "askrene-inform-channel");
auto params = req["params"];