7 Commits
Author SHA1 Message Date
clawbot 0947975427 Refuse a script/loadtest clients count that starts with 0
check / check (push) Failing after 3s
vegeta reads a leading 0 in its worker count as octal, so 00 gave no
workers and 010 gave eight. The clients check before the build now
refuses any value starting with 0, zero included. The duration needs no
change: vegeta reads it as decimal, so 05s is five seconds.

TODO.md: the load test entry is once, at the top of Completed Steps,
and the entries for #206 and #204 are no longer repeated.

Model: opus-5-5
2026-10-05 00:00:10 +00:00
clawbot d33ff21cce Check script/loadtest's duration before the build
A duration must be a whole number above zero followed by ms, s, m or
h; anything else prints the usage line and exits 2 before the image
build, as a bad number of clients already did. vegeta takes 0 to mean
no end. The load test's entry moves to the top of Completed Steps in
TODO.md.

Model: opus-5-5
2026-10-04 23:59:24 +00:00
clawbot 053e438ce7 Move the load-test origin's logic into internal/loadtestorigin
REPO_POLICIES.md requires cmd/ to be thin: one main.go whose body is a
single call into internal/ or pkg/. The image, the handler, the server
and their test move unchanged into internal/loadtestorigin, whose Run
does what main did; cmd/loadtest-origin/main.go only calls it.

Model: opus-5-5
2026-10-04 23:59:24 +00:00
clawbot 0e490e4866 Add script/loadtest to measure throughput, latency and memory (closes #81)
script/loadtest [duration [clients]], or make loadtest, is a benchmark
that script/check does not run. It builds the image and vegeta from a
pinned commit, then for each scenario starts a new pixad container and
a new cmd/loadtest-origin container, an upstream host that answers every
path with one generated JPEG: a cached image (hit), a new source image
per request (miss), and each new source image asked for by all clients
at once (herd). It prints vegeta's report, pixad's peak resident memory
and the requests the origin got. The containers share a network in
203.0.113.0/24, as pixad refuses private and local upstream addresses.
README.md says how to run and read it; TODO.md records a small baseline.

Model: opus-5-5
2026-10-04 23:59:24 +00:00
clawbot 56972cb6eb Test that the load-test origin serves one JPEG at every path
script/loadtest, added in the next commit, needs an upstream host that
answers any path with the same image, so each new path is a new source
image for pixad to fetch. This test checks that the origin's handler
answers several paths with 200, Content-Type image/jpeg and the same
bytes, and that the image decodes as a JPEG of the expected size. It
does not build until the origin exists.

Model: opus-5-5
2026-10-04 23:59:24 +00:00
clawbot f77faf13de Keep config.yml out of git and the Docker build context (closes #212)
check / check (push) Failing after 2s
Getting Started has you create config.yml at the repository root with a
real signing key, but neither .gitignore nor .dockerignore left it out,
so it could be committed and, through COPY . ., reach a build-stage
layer. .gitignore now ignores it next to config.yaml, and .dockerignore
leaves it out in every directory and in any letter case, as it already
does config.yaml and config.dev.yml.

Model: opus-5-5
2026-10-05 01:58:32 +02:00
clawbot ae7c3f226d Keep local config files out of the Docker build context (closes #211)
check / check (push) Failing after 2s
config.yaml and config.dev.yml are kept out of git because they can hold
the signing key, but .dockerignore did not leave them out, so a local
copy in the working tree reached the build context and, through
COPY . ., a build-stage layer. .dockerignore now leaves them out in
every directory and in any letter case. configs/config.example.yml is
still sent.

Model: opus-5-5
2026-10-05 01:24:41 +02:00
4 changed files with 21 additions and 1 deletions
+5
View File
@@ -66,3 +66,8 @@
.gitignore
/bin
/data
# Local config files, kept out of git because they can hold the signing key.
**/[cC][oO][nN][fF][iI][gG].[yY][mM][lL]
**/[cC][oO][nN][fF][iI][gG].[yY][aA][mM][lL]
**/[cC][oO][nN][fF][iI][gG].[dD][eE][vV].[yY][mM][lL]
+1
View File
@@ -37,5 +37,6 @@ node_modules/
*.sqlite3
# Local dev configs
config.yml
config.yaml
config.dev.yml
+12
View File
@@ -46,6 +46,18 @@ P2: security: per-IP rate limiting on the image routes
not pixad's limit); `miss` 70 r/s, p50 52 ms, p95 91 ms, p99 122 ms, peak 100
MiB, one fetch per request; `herd` 74 r/s, p50 52 ms, p95 69 ms, p99 111 ms,
peak 60 MiB, 188 fetches for 749 requests.
- 2026-10-04 `config.yml` stays out of git and the Docker build context (closes
#212): `.gitignore` now ignores `config.yml`, the config file Getting Started
creates with the signing key, and `.dockerignore` leaves it out in every
directory and in any letter case, as it already did `config.yaml` and
`config.dev.yml`.
- 2026-10-04 local config files stay out of the Docker build context (closes
#211): `.dockerignore` now leaves out `config.yaml` and `config.dev.yml` in
every directory and in any letter case, the local config files `.gitignore`
keeps out of git because they can hold the signing key.
`configs/config.example.yml` is still sent. `config.yml`, which Getting
Started creates, is in neither file:
https://git.eeqj.de/sneak/pixa/issues/212.
- 2026-10-04 `cmd/pixad/main.go` is one call into `internal/` (closes #206):
what it did (the command line and its `--config` flag, setting
`PIXA_CONFIG_PATH`, ignoring `SIGPIPE`, starting the fx app) is now `Run` in
+3 -1
View File
@@ -51,8 +51,10 @@ main() {
"" | *[!0-9]*) usage ;;
esac
[ "$number" -gt 0 ] || usage
# The number of clients is a whole number that does not start with 0,
# which also refuses zero: vegeta reads a leading 0 as octal.
case "$clients" in
*[!0-9]* | 0) usage ;;
*[!0-9]* | 0*) usage ;;
esac
cd "$ROOT"