Files
tiku-backend.net/tools/performance/run-local.sh

151 lines
4.3 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
api_port="${TIKU_API_PORT:-5091}"
mode="${TIKU_MODE:-mixed}"
rate="${TIKU_RATE:-100}"
duration="${TIKU_DURATION:-30s}"
tenant_code="${TIKU_TENANT_CODE:-demo-crm-school}"
redis_container="${TIKU_REDIS_CONTAINER:-tiku-redis}"
database_name="${TIKU_DATABASE_NAME:-tiku}"
run_stamp="$(date +%Y%m%d-%H%M%S)"
result_dir="${repo_root}/artifacts/performance/${run_stamp}-${mode}-${rate}rps"
api_pid=""
cleanup() {
if [[ -n "${api_pid}" ]] && kill -0 "${api_pid}" 2>/dev/null; then
kill "${api_pid}" 2>/dev/null || true
wait "${api_pid}" 2>/dev/null || true
fi
api_pid=""
}
trap cleanup EXIT INT TERM
mkdir -p "${result_dir}"
if ! command -v docker >/dev/null 2>&1; then
echo "docker is required for the Redis readiness check" >&2
exit 1
fi
if ! docker inspect "${redis_container}" >/dev/null 2>&1; then
echo "Redis container '${redis_container}' does not exist" >&2
exit 1
fi
if [[ "$(docker inspect -f '{{.State.Running}}' "${redis_container}")" != "true" ]]; then
echo "Redis container '${redis_container}' is not running" >&2
exit 1
fi
docker exec "${redis_container}" redis-cli ping | grep -qx PONG
if ! command -v psql >/dev/null 2>&1; then
echo "psql is required to capture PostgreSQL metrics" >&2
exit 1
fi
psql -d "${database_name}" -Atqc 'select 1' | grep -qx 1
(
cd "${repo_root}"
dotnet build TIKU-BACKEND.slnx -c Release --no-restore
)
host_url="http://127.0.0.1:${api_port}"
load_url="${host_url}"
(
cd "${repo_root}"
exec env \
ASPNETCORE_ENVIRONMENT=Development \
ASPNETCORE_URLS="http://0.0.0.0:${api_port}" \
ConnectionStrings__Redis=localhost:6379 \
RateLimiting__Enabled=false \
BackgroundProcessing__Enabled=false \
Serilog__MinimumLevel__Default=Warning \
dotnet run --project Tiku.Api -c Release --no-build --no-launch-profile
) >"${result_dir}/api.log" 2>&1 &
api_pid=$!
ready_body=""
for _ in $(seq 1 60); do
if ready_body="$(curl -fsS "${host_url}/api/health/ready" 2>/dev/null)"; then
break
fi
if ! kill -0 "${api_pid}" 2>/dev/null; then
echo "Tiku.Api stopped during startup; see ${result_dir}/api.log" >&2
exit 1
fi
sleep 1
done
if [[ -z "${ready_body}" ]]; then
echo "Tiku.Api did not become ready; see ${result_dir}/api.log" >&2
exit 1
fi
printf '%s\n' "${ready_body}" >"${result_dir}/readiness.json"
if ! printf '%s' "${ready_body}" | grep -q '"status":"ready"'; then
echo "PostgreSQL or Redis is not ready: ${ready_body}" >&2
exit 1
fi
capture_dependencies() {
local suffix="$1"
psql -d "${database_name}" -P pager=off -c \
"select datname, numbackends, xact_commit, xact_rollback, blks_read, blks_hit, tup_returned, tup_fetched from pg_stat_database where datname = current_database();" \
>"${result_dir}/postgres-${suffix}.txt"
docker exec "${redis_container}" redis-cli INFO stats \
>"${result_dir}/redis-${suffix}.txt"
}
capture_dependencies before
{
sw_vers
printf 'logical_cpu: '
sysctl -n hw.logicalcpu
printf 'memory_bytes: '
sysctl -n hw.memsize
dotnet --info
} >"${result_dir}/host.txt"
set +e
if command -v k6 >/dev/null 2>&1; then
load_url="${host_url}"
k6 run \
--summary-export "${result_dir}/summary.json" \
-e "TIKU_BASE_URL=${load_url}" \
-e "TIKU_HOST_HEADER=localhost:${api_port}" \
-e "TIKU_TENANT_CODE=${tenant_code}" \
-e "TIKU_MODE=${mode}" \
-e "TIKU_RATE=${rate}" \
-e "TIKU_DURATION=${duration}" \
"${repo_root}/tools/performance/tiku-api.js" \
| tee "${result_dir}/k6.txt"
k6_exit=${PIPESTATUS[0]}
else
load_url="http://host.docker.internal:${api_port}"
docker run --rm \
-v "${repo_root}:/work:ro" \
-v "${result_dir}:/results" \
grafana/k6:latest \
run \
--summary-export /results/summary.json \
-e "TIKU_BASE_URL=${load_url}" \
-e "TIKU_HOST_HEADER=localhost:${api_port}" \
-e "TIKU_TENANT_CODE=${tenant_code}" \
-e "TIKU_MODE=${mode}" \
-e "TIKU_RATE=${rate}" \
-e "TIKU_DURATION=${duration}" \
/work/tools/performance/tiku-api.js \
| tee "${result_dir}/k6.txt"
k6_exit=${PIPESTATUS[0]}
fi
set -e
cleanup
capture_dependencies after
printf 'mode=%s\nrate=%s\nduration=%s\ntenant=%s\nk6_exit=%s\n' \
"${mode}" "${rate}" "${duration}" "${tenant_code}" "${k6_exit}" \
>"${result_dir}/run.env"
echo "Results: ${result_dir}"
exit "${k6_exit}"