#!/bin/sh set -eu umask 077 ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd) # shellcheck source=scripts/scale-common.sh . "$ROOT/scripts/scale-common.sh" scale_load_environment K6_IMAGE="grafana/k6@sha256:65c920dc067d5e2e00befbf982af6ad6ad0117034e8b1c65817c7975c52d4669" STATE_FILE=${WNH_SCALE_BROWSER_STATE:-"$ROOT/output/runtime/scale-browser-state.json"} VUS=${WNH_SCALE_READONLY_VUS:?WNH_SCALE_READONLY_VUS is required} DURATION=${WNH_SCALE_READONLY_DURATION:?WNH_SCALE_READONLY_DURATION is required} THINK_SECONDS=${WNH_SCALE_READONLY_THINK_SECONDS:?WNH_SCALE_READONLY_THINK_SECONDS is required} LABEL=${WNH_SCALE_READONLY_LABEL:-"scale-readonly-$(date -u +%Y%m%dT%H%M%SZ)"} OUTPUT_DIR="$ROOT/output/performance/$LABEL" case "$VUS" in ''|*[!0-9]*|0) echo "WNH_SCALE_READONLY_VUS must be a positive integer." >&2 exit 2 ;; esac if ! printf '%s\n' "$DURATION" | grep -Eq '^[1-9][0-9]*(ms|s|m|h)$'; then echo "WNH_SCALE_READONLY_DURATION must be a positive k6 duration." >&2 exit 2 fi if ! printf '%s\n' "$THINK_SECONDS" | grep -Eq '^([0-9]+([.][0-9]+)?|[.][0-9]+)$'; then echo "WNH_SCALE_READONLY_THINK_SECONDS must be a non-negative number." >&2 exit 2 fi case "$LABEL" in ''|*[!A-Za-z0-9._-]*) echo "WNH_SCALE_READONLY_LABEL contains unsupported characters." >&2 exit 2 ;; esac if [ ! -f "$STATE_FILE" ]; then echo "Missing authenticated scale browser state: $STATE_FILE" >&2 exit 2 fi session_cookie=$( jq -r ' .cookies[] | select(.domain == "scale.localhost" and .name == "_who_need_help_key") | "\(.name)=\(.value)" ' "$STATE_FILE" ) if [ -z "$session_cookie" ]; then echo "The browser state does not contain the scale session cookie." >&2 exit 2 fi web_id=$(scale_compose ps -q web) worker_id=$(scale_compose ps -q worker) db_id=$(scale_compose ps -q db) for pair in "web:$web_id" "worker:$worker_id" "db:$db_id"; do service=${pair%%:*} container=${pair#*:} if [ -z "$container" ] || [ "$(docker inspect --format '{{.State.Status}}' "$container")" != "running" ]; then echo "Scale service $service is not running." >&2 exit 2 fi done actual_database=$( scale_compose exec -T db \ psql -XAt -U "$POSTGRES_USER" -d "$POSTGRES_DB" \ -c 'SELECT current_database()' ) if [ "$actual_database" != "$WNH_SCALE_EXPECTED_DATABASE" ]; then echo "Refusing unexpected database: $actual_database" >&2 exit 2 fi if [ -e "$OUTPUT_DIR" ]; then echo "Output path already exists: $OUTPUT_DIR" >&2 exit 2 fi mkdir -p "$OUTPUT_DIR" chmod 700 "$ROOT/output" "$ROOT/output/performance" "$OUTPUT_DIR" snapshot_counts() { destination=$1 scale_compose exec -T db \ psql -XAt -U "$POSTGRES_USER" -d "$POSTGRES_DB" \ -c " SELECT json_build_object( 'captured_at', clock_timestamp(), 'database', current_database(), 'users', (SELECT count(*) FROM users), 'users_tokens', (SELECT count(*) FROM users_tokens), 'help_requests', (SELECT count(*) FROM help_requests), 'activities', (SELECT count(*) FROM activities), 'help_assignments', (SELECT count(*) FROM help_assignments), 'activity_participants', (SELECT count(*) FROM activity_participants), 'messages', (SELECT count(*) FROM messages), 'activity_messages', (SELECT count(*) FROM activity_messages), 'rate_limit_buckets', (SELECT count(*) FROM rate_limit_buckets) ) " >"$destination" } snapshot_counts "$OUTPUT_DIR/counts-before.json" cat >"$OUTPUT_DIR/scope.txt" </dev/null docker run --rm \ --volume "$OUTPUT_DIR:/output" \ alpine:3.23.3@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659 \ chown -R "$(id -u):$(id -g)" /output printf 'Read-only scale result: %s\n' "$OUTPUT_DIR"