Skip to content

docs(readme): add benchmark artifact references #10

docs(readme): add benchmark artifact references

docs(readme): add benchmark artifact references #10

Workflow file for this run

name: Benchmark & Load Test
on:
workflow_dispatch:
push:
branches: [main]
jobs:
benchmark:
name: Run Benchmarks
runs-on: ubuntu-latest
timeout-minutes: 30
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: journal
POSTGRES_USER: journal
POSTGRES_PASSWORD: journal
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 5s
--health-timeout 5s
--health-retries 10
redis:
image: redis:7-alpine
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 5s
--health-timeout 5s
--health-retries 10
env:
DATABASE_URL: postgresql://journal:journal@localhost:5432/journal?sslmode=disable
REDIS_URL: redis://localhost:6379/0
NATS_URL: nats://localhost:4222
PORT: "8080"
PROMETHEUS_PORT: "2112"
IDEMPOTENCY_TTL_HOURS: "24"
OUTBOX_POLL_INTERVAL_MS: "500"
OUTBOX_BATCH_SIZE: "100"
MAX_SERIALIZATION_RETRIES: "3"
SERIALIZATION_BACKOFF_BASE_MS: "10"
LOG_LEVEL: "warn"
steps:
- uses: actions/checkout@v4
- name: Start NATS JetStream
run: docker run -d -p 4222:4222 -p 8222:8222 --name nats nats:2.10-alpine -js
- uses: actions/setup-go@v5
with:
go-version: "1.22"
cache: true
# Install migrate CLI
- name: Install migrate
run: |
curl -L https://github.com/golang-migrate/migrate/releases/download/v4.17.1/migrate.linux-amd64.tar.gz | tar xvz
sudo mv migrate /usr/local/bin/
# Install k6
- name: Install k6
run: |
curl -L https://github.com/grafana/k6/releases/download/v0.52.0/k6-v0.52.0-linux-amd64.tar.gz | tar xz
sudo mv k6-v0.52.0-linux-amd64/k6 /usr/local/bin/
# Apply migrations
- name: Run migrations
run: migrate -path migrations -database "$DATABASE_URL" up
# Unit + integration tests
- name: Unit tests (with race detector)
run: go test -race -cover -coverprofile=coverage.out ./internal/domain/... ./internal/ledger/...
- name: Integration tests
run: go test -race -v ./test/integration/...
# Concurrency stress test
- name: Concurrency stress test
run: |
go test -race -count=5 -timeout=300s -v ./test/concurrency/... \
2>&1 | tee concurrency-results.txt
# Start API for load testing
- name: Build and start API
run: |
go build -o api ./cmd/api/...
./api &
# Wait for API to be ready
for i in $(seq 1 20); do
if curl -sf http://localhost:8080/v1/health > /dev/null; then
echo "API ready after ${i}s"
break
fi
sleep 1
done
# k6 Load tests
- name: Baseline throughput (50 VUs, 60s)
run: |
k6 run \
--summary-trend-stats="med,p(95),p(99),max" \
--out json=baseline-results.json \
load/scenarios/baseline.js \
2>&1 | tee baseline-summary.txt
- name: Hot account contention (50 VUs, 60s)
run: |
k6 run \
--summary-trend-stats="med,p(95),p(99),max" \
--out json=hot-account-results.json \
load/scenarios/hot_account.js \
2>&1 | tee hot-account-summary.txt
- name: Idempotency storm (20 VUs, 60s)
run: |
k6 run \
--summary-trend-stats="med,p(95),p(99),max" \
--out json=idempotency-results.json \
load/scenarios/idempotency_storm.js \
2>&1 | tee idempotency-summary.txt
# Upload all results as artifacts
- name: Upload benchmark results
uses: actions/upload-artifact@v4
if: always()
with:
name: benchmark-results-${{ github.sha }}
retention-days: 90
path: |
coverage.out
concurrency-results.txt
baseline-summary.txt
baseline-results.json
hot-account-summary.txt
hot-account-results.json
idempotency-summary.txt
idempotency-results.json
# Print summary to job log
- name: Print benchmark summary
if: always()
run: |
echo "=== BASELINE ===" && cat baseline-summary.txt || true
echo "=== HOT ACCOUNT ===" && cat hot-account-summary.txt || true
echo "=== IDEMPOTENCY ===" && cat idempotency-summary.txt || true
echo "=== CONCURRENCY ===" && cat concurrency-results.txt || true