dev: E2E and bench runners via justfile

This commit is contained in:
2026-03-19 13:49:12 +01:00
parent 833c85f4ac
commit e7a7460191
4 changed files with 188 additions and 29 deletions

View File

@@ -48,10 +48,23 @@ Current `supported_nips` list:
- Elixir `~> 1.18` - Elixir `~> 1.18`
- Erlang/OTP 28 - Erlang/OTP 28
- PostgreSQL (18 used in the dev environment; 16+ recommended) - PostgreSQL (18 used in the dev environment; 16+ recommended)
- [`just`](https://github.com/casey/just) for the command runner used in this repo
- Docker or Podman plus Docker Compose support if you want to run the published container image - Docker or Podman plus Docker Compose support if you want to run the published container image
--- ---
## Command runner (`just`)
This repo includes a `justfile` that provides a grouped command/subcommand CLI over common mix tasks and scripts.
```bash
just
just help bench
just help e2e
```
---
## Run locally ## Run locally
### 1) Prepare the database ### 1) Prepare the database
@@ -97,9 +110,9 @@ ws://localhost:4413/relay
Primary test entrypoints: Primary test entrypoints:
- `mix test` for the ExUnit suite - `mix test` for the ExUnit suite
- `mix test.marmot_e2e` for the Marmot client end-to-end suite - `just e2e marmot` for the Marmot client end-to-end suite
- `mix test.node_sync_e2e` for the two-node relay sync end-to-end suite - `just e2e node-sync` for the two-node relay sync end-to-end suite
- `mix test.node_sync_docker_e2e` for the release-image Docker two-node relay sync suite - `just e2e node-sync-docker` for the release-image Docker two-node relay sync suite
The node-sync harnesses are driven by: The node-sync harnesses are driven by:
@@ -108,7 +121,7 @@ The node-sync harnesses are driven by:
- [`scripts/node_sync_e2e.exs`](./scripts/node_sync_e2e.exs) - [`scripts/node_sync_e2e.exs`](./scripts/node_sync_e2e.exs)
- [`compose.node-sync-e2e.yaml`](./compose.node-sync-e2e.yaml) - [`compose.node-sync-e2e.yaml`](./compose.node-sync-e2e.yaml)
`mix test.node_sync_e2e` runs two real Parrhesia nodes against separate PostgreSQL databases, verifies catch-up and live sync, restarts one node, and verifies persisted resume behavior. `mix test.node_sync_docker_e2e` runs the same scenario against the release Docker image. `just e2e node-sync` runs two real Parrhesia nodes against separate PostgreSQL databases, verifies catch-up and live sync, restarts one node, and verifies persisted resume behavior. `just e2e node-sync-docker` runs the same scenario against the release Docker image.
GitHub CI currently runs the non-Docker node-sync e2e on the main Linux matrix job. The Docker node-sync e2e remains an explicit/manual check because it depends on release-image build/runtime fidelity and a working Docker host. GitHub CI currently runs the non-Docker node-sync e2e on the main Linux matrix job. The Docker node-sync e2e remains an explicit/manual check because it depends on release-image build/runtime fidelity and a working Docker host.
@@ -540,12 +553,12 @@ Notes:
The benchmark compares two Parrhesia profiles, one backed by PostgreSQL and one backed by the in-memory adapter, against [`strfry`](https://github.com/hoytech/strfry) and [`nostr-rs-relay`](https://sr.ht/~gheartsfield/nostr-rs-relay/) using [`nostr-bench`](https://github.com/rnostr/nostr-bench). Benchmark runs also lift Parrhesia's relay-side limits by default so the benchmark client, not server guardrails, is the main bottleneck. The benchmark compares two Parrhesia profiles, one backed by PostgreSQL and one backed by the in-memory adapter, against [`strfry`](https://github.com/hoytech/strfry) and [`nostr-rs-relay`](https://sr.ht/~gheartsfield/nostr-rs-relay/) using [`nostr-bench`](https://github.com/rnostr/nostr-bench). Benchmark runs also lift Parrhesia's relay-side limits by default so the benchmark client, not server guardrails, is the main bottleneck.
`mix bench` is a sequential mixed-workload benchmark, not an isolated per-endpoint microbenchmark. Each relay instance runs `connect`, then `echo`, then `event`, then `req` against the same live process, so later phases measure against state and load created by earlier phases. `just bench compare` is a sequential mixed-workload benchmark, not an isolated per-endpoint microbenchmark. Each relay instance runs `connect`, then `echo`, then `event`, then `req` against the same live process, so later phases measure against state and load created by earlier phases.
Run it with: Run it with:
```bash ```bash
mix bench just bench compare
``` ```
### Cloud benchmark (Hetzner Cloud) ### Cloud benchmark (Hetzner Cloud)
@@ -553,7 +566,8 @@ mix bench
For distributed runs (one server node + multiple client nodes), use: For distributed runs (one server node + multiple client nodes), use:
```bash ```bash
./scripts/run_bench_cloud.sh just bench cloud
# or: ./scripts/run_bench_cloud.sh
``` ```
or invoke the orchestrator directly: or invoke the orchestrator directly:
@@ -572,7 +586,8 @@ Example:
```bash ```bash
export HCLOUD_TOKEN=... export HCLOUD_TOKEN=...
./scripts/run_bench_cloud.sh --quick just bench cloud-quick
# or: ./scripts/run_bench_cloud.sh --quick
``` ```
Outputs: Outputs:
@@ -584,13 +599,13 @@ Useful history/render commands:
```bash ```bash
# List available machines and runs in history # List available machines and runs in history
./scripts/run_bench_update.sh --list just bench list
# Regenerate chart + README table for a machine # Regenerate chart + README table for a machine
./scripts/run_bench_update.sh <machine_id> just bench update <machine_id>
# Regenerate from all machines # Regenerate from all machines
./scripts/run_bench_update.sh all just bench update all
``` ```
Current comparison results: Current comparison results:
@@ -625,11 +640,11 @@ mix precommit
Additional external CLI end-to-end checks with `nak`: Additional external CLI end-to-end checks with `nak`:
```bash ```bash
mix test.nak_e2e just e2e nak
``` ```
For Marmot client end-to-end checks (TypeScript/Node suite using `marmot-ts`, included in `precommit`): For Marmot client end-to-end checks (TypeScript/Node suite using `marmot-ts`, included in `precommit`):
```bash ```bash
mix test.marmot_e2e just e2e marmot
``` ```

78
justfile Normal file
View File

@@ -0,0 +1,78 @@
set shell := ["bash", "-euo", "pipefail", "-c"]
set script-interpreter := ["bash", "-euo", "pipefail"]
repo_root := justfile_directory()
# Show curated command help (same as `just help`).
default:
@just help
# Show top-level or topic-specific help.
help topic="":
@cd "{{repo_root}}" && ./scripts/just_help.sh "{{topic}}"
# Raw e2e harness commands.
[script]
e2e subcommand="help" *args:
cd "{{repo_root}}"
subcommand="{{subcommand}}"
if [[ -z "$subcommand" || "$subcommand" == "help" ]]; then
just help e2e
elif [[ "$subcommand" == "nak" ]]; then
./scripts/run_nak_e2e.sh {{args}}
elif [[ "$subcommand" == "marmot" ]]; then
./scripts/run_marmot_e2e.sh {{args}}
elif [[ "$subcommand" == "node-sync" ]]; then
./scripts/run_node_sync_e2e.sh {{args}}
elif [[ "$subcommand" == "node-sync-docker" ]]; then
./scripts/run_node_sync_docker_e2e.sh {{args}}
elif [[ "$subcommand" == "suite" ]]; then
if [[ -z "{{args}}" ]]; then
echo "usage: just e2e suite <suite-name> <command> [args...]" >&2
exit 1
fi
./scripts/run_e2e_suite.sh {{args}}
else
echo "Unknown e2e subcommand: $subcommand" >&2
just help e2e
exit 1
fi
# Benchmark flows (local/cloud/history + direct relay targets).
[script]
bench subcommand="help" *args:
cd "{{repo_root}}"
subcommand="{{subcommand}}"
if [[ -z "$subcommand" || "$subcommand" == "help" ]]; then
just help bench
elif [[ "$subcommand" == "compare" ]]; then
./scripts/run_bench_compare.sh {{args}}
elif [[ "$subcommand" == "collect" ]]; then
./scripts/run_bench_collect.sh {{args}}
elif [[ "$subcommand" == "update" ]]; then
./scripts/run_bench_update.sh {{args}}
elif [[ "$subcommand" == "list" ]]; then
./scripts/run_bench_update.sh --list {{args}}
elif [[ "$subcommand" == "at" ]]; then
if [[ -z "{{args}}" ]]; then
echo "usage: just bench at <git-ref>" >&2
exit 1
fi
./scripts/run_bench_at_ref.sh {{args}}
elif [[ "$subcommand" == "cloud" ]]; then
./scripts/run_bench_cloud.sh {{args}}
elif [[ "$subcommand" == "cloud-quick" ]]; then
./scripts/run_bench_cloud.sh --quick {{args}}
elif [[ "$subcommand" == "relay" ]]; then
./scripts/run_nostr_bench.sh {{args}}
elif [[ "$subcommand" == "relay-strfry" ]]; then
./scripts/run_nostr_bench_strfry.sh {{args}}
elif [[ "$subcommand" == "relay-nostr-rs" ]]; then
./scripts/run_nostr_bench_nostr_rs_relay.sh {{args}}
else
echo "Unknown bench subcommand: $subcommand" >&2
just help bench
exit 1
fi

18
mix.exs
View File

@@ -28,11 +28,7 @@ defmodule Parrhesia.MixProject do
def cli do def cli do
[ [
preferred_envs: [ preferred_envs: [
precommit: :test, precommit: :test
bench: :test,
"bench.collect": :test,
"bench.update": :test,
"bench.at": :test
] ]
] ]
end end
@@ -74,15 +70,6 @@ defmodule Parrhesia.MixProject do
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
"ecto.reset": ["ecto.drop", "ecto.setup"], "ecto.reset": ["ecto.drop", "ecto.setup"],
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"], test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
"test.nak_e2e": ["cmd ./scripts/run_nak_e2e.sh"],
"test.marmot_e2e": ["cmd ./scripts/run_marmot_e2e.sh"],
"test.node_sync_e2e": ["cmd ./scripts/run_node_sync_e2e.sh"],
"test.node_sync_docker_e2e": ["cmd ./scripts/run_node_sync_docker_e2e.sh"],
bench: ["cmd ./scripts/run_bench_compare.sh"],
"bench.collect": ["cmd ./scripts/run_bench_collect.sh"],
"bench.update": ["cmd ./scripts/run_bench_update.sh"],
"bench.at": ["cmd ./scripts/run_bench_at_ref.sh"],
# cov: ["cmd mix coveralls.lcov"],
lint: ["format --check-formatted", "credo"], lint: ["format --check-formatted", "credo"],
precommit: [ precommit: [
"format", "format",
@@ -90,8 +77,7 @@ defmodule Parrhesia.MixProject do
"credo --strict --all", "credo --strict --all",
"deps.unlock --unused", "deps.unlock --unused",
"test", "test",
# "test.nak_e2e", "cmd just e2e marmot"
"test.marmot_e2e"
] ]
] ]
end end

80
scripts/just_help.sh Executable file
View File

@@ -0,0 +1,80 @@
#!/usr/bin/env bash
set -euo pipefail
topic="${1:-}"
if [[ -z "$topic" || "$topic" == "root" || "$topic" == "all" ]]; then
cat <<'EOF'
Parrhesia command runner
Usage:
just <group> <subcommand> [args...]
just help [group]
Command groups:
e2e <subcommand> End-to-end harness entrypoints
bench <subcommand> Benchmark tasks (local/cloud/history/chart)
Notes:
- Keep using mix aliases for core project workflows:
mix setup
mix test
mix lint
mix precommit
Examples:
just help bench
just e2e marmot
just e2e node-sync
just bench compare
just bench cloud --clients 3 --runs 3
EOF
exit 0
fi
if [[ "$topic" == "e2e" ]]; then
cat <<'EOF'
E2E commands
just e2e nak CLI e2e tests via nak
just e2e marmot Marmot client e2e tests
just e2e node-sync Local two-node sync harness
just e2e node-sync-docker Docker two-node sync harness
Advanced:
just e2e suite <name> <cmd...>
-> runs scripts/run_e2e_suite.sh directly
EOF
exit 0
fi
if [[ "$topic" == "bench" ]]; then
cat <<'EOF'
Benchmark commands
just bench compare Local benchmark comparison table only
just bench collect Append run results to bench/history.jsonl
just bench update Regenerate chart + README table
just bench list List machines/runs from history
just bench at <git-ref> Run collect benchmark at git ref
just bench cloud [args...] Cloud benchmark wrapper
just bench cloud-quick Cloud smoke profile
Relay-target helpers:
just bench relay [all|connect|echo|event|req] [nostr-bench-args...]
just bench relay-strfry [...]
just bench relay-nostr-rs [...]
Examples:
just bench compare
just bench collect
just bench update --machine all
just bench at v0.5.0
just bench cloud --clients 3 --runs 3
EOF
exit 0
fi
echo "Unknown help topic: $topic" >&2
echo "Run: just help" >&2
exit 1