Keep million-row fixtures in development
This commit is contained in:
parent
ebaaeaf517
commit
4490280e0e
|
|
@ -183,6 +183,10 @@ FCM_SERVICE_ACCOUNT_JSON_BASE64=
|
||||||
POSTGRES_DB=who_need_help
|
POSTGRES_DB=who_need_help
|
||||||
POSTGRES_USER=postgres
|
POSTGRES_USER=postgres
|
||||||
POSTGRES_PASSWORD=replace-with-a-local-or-deployment-secret
|
POSTGRES_PASSWORD=replace-with-a-local-or-deployment-secret
|
||||||
|
|
||||||
|
# Required only by scripts/dev-scale-seed.sh for the local synthetic viewer.
|
||||||
|
# Generate a distinct value; never reuse a real user or deployment password.
|
||||||
|
DEV_SCALE_VIEWER_PASSWORD=replace-with-a-random-local-fixture-password
|
||||||
DATABASE_URL=ecto://postgres:replace-with-url-encoded-password@db/who_need_help
|
DATABASE_URL=ecto://postgres:replace-with-url-encoded-password@db/who_need_help
|
||||||
# Optional absolute host directory containing PostgreSQL Unix sockets. When it
|
# Optional absolute host directory containing PostgreSQL Unix sockets. When it
|
||||||
# is set in external mode, Compose mounts it read-only and Ecto uses it instead
|
# is set in external mode, Compose mounts it read-only and Ecto uses it instead
|
||||||
|
|
|
||||||
|
|
@ -767,7 +767,9 @@ ignored `output/runtime/scale.env`. Fixture mutation additionally requires the
|
||||||
exact database name and `WNH_SCALE_FIXTURE_CONFIRM=persistent-local-scale`.
|
exact database name and `WNH_SCALE_FIXTURE_CONFIRM=persistent-local-scale`.
|
||||||
The seed task refuses a partially populated database instead of mixing data
|
The seed task refuses a partially populated database instead of mixing data
|
||||||
sets. `scale-stack-stop.sh` stops only this Compose project and deliberately
|
sets. `scale-stack-stop.sh` stops only this Compose project and deliberately
|
||||||
preserves the named volume.
|
preserves the named volume. `scale-stack-down.sh` removes only the profile's
|
||||||
|
containers and networks while also preserving that volume for an explicit
|
||||||
|
operator decision.
|
||||||
|
|
||||||
The canonical local fixture contains 1,000,000 requests, 1,000,000 activities,
|
The canonical local fixture contains 1,000,000 requests, 1,000,000 activities,
|
||||||
1,000 synthetic request owners, and one scale viewer. Records are distributed
|
1,000 synthetic request owners, and one scale viewer. Records are distributed
|
||||||
|
|
@ -848,6 +850,26 @@ messages, and rate-limit buckets before and after.
|
||||||
|
|
||||||
The final 2026-07-28 one-VU, 30-second, one-CPU static-shell observation
|
The final 2026-07-28 one-VU, 30-second, one-CPU static-shell observation
|
||||||
completed 60 authenticated GETs with 0 HTTP failures and 120/120 checks.
|
completed 60 authenticated GETs with 0 HTTP failures and 120/120 checks.
|
||||||
|
|
||||||
|
### Keeping the fixtures in the ordinary development site
|
||||||
|
|
||||||
|
The isolated profile is useful for destructive load rehearsals. For routine
|
||||||
|
development of the actual `whoneedhelp.imalto.site` UI, the same deterministic
|
||||||
|
fixtures can instead be appended to the already running `who_need_help`
|
||||||
|
development database:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./scripts/dev-scale-seed.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
This guarded path requires the running Compose project and services to be named
|
||||||
|
`who_need_help`, `who_need_help-web-1`, and `who_need_help-db-1`; verifies that
|
||||||
|
the target database is exactly `who_need_help`; and uses the separate
|
||||||
|
confirmation value `persistent-dev-scale`. It preserves ordinary development
|
||||||
|
users and records. Synthetic rows carry `structured_data.scale_fixture=true`,
|
||||||
|
use deterministic UUIDs, and are inserted with conflict handling, so rerunning
|
||||||
|
the command fills missing fixtures without duplicating them. The resulting
|
||||||
|
summary is ignored at `output/dev-scale/summary.json`.
|
||||||
Overall HTTP duration was 2.566 ms median, 3.196 ms average, and 8.709 ms
|
Overall HTTP duration was 2.566 ms median, 3.196 ms average, and 8.709 ms
|
||||||
maximum. Every tracked table count was identical before and after. The
|
maximum. Every tracked table count was identical before and after. The
|
||||||
discovery-query medians are the independently measured values in the table
|
discovery-query medians are the independently measured values in the table
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,9 @@ defmodule Mix.Tasks.Wnh.ScaleFixtures do
|
||||||
alias WhoNeedHelp.{Activities, Catalog, Help, Repo}
|
alias WhoNeedHelp.{Activities, Catalog, Help, Repo}
|
||||||
alias WhoNeedHelp.Help.DiscoveryViewport
|
alias WhoNeedHelp.Help.DiscoveryViewport
|
||||||
|
|
||||||
@shortdoc "Prepares or verifies a persistent, isolated local discovery-scale data set"
|
@shortdoc "Prepares, appends, or verifies a persistent local discovery-scale data set"
|
||||||
@confirmation "persistent-local-scale"
|
@isolated_confirmation "persistent-local-scale"
|
||||||
|
@additive_confirmation "persistent-dev-scale"
|
||||||
@default_rows 1_000_000
|
@default_rows 1_000_000
|
||||||
@synthetic_users 1_000
|
@synthetic_users 1_000
|
||||||
@viewer_email "scale-viewer@example.invalid"
|
@viewer_email "scale-viewer@example.invalid"
|
||||||
|
|
@ -24,7 +25,7 @@ defmodule Mix.Tasks.Wnh.ScaleFixtures do
|
||||||
|
|
||||||
action =
|
action =
|
||||||
case rest do
|
case rest do
|
||||||
[value] when value in ["prepare", "verify"] -> value
|
[value] when value in ["prepare", "append", "verify"] -> value
|
||||||
_other -> Mix.raise(usage())
|
_other -> Mix.raise(usage())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -32,16 +33,17 @@ defmodule Mix.Tasks.Wnh.ScaleFixtures do
|
||||||
activity_count = positive_count!(options, :activities)
|
activity_count = positive_count!(options, :activities)
|
||||||
samples = positive_count!(options, :samples, 3)
|
samples = positive_count!(options, :samples, 3)
|
||||||
output = Keyword.get(options, :output) || Mix.raise("--output PATH is required")
|
output = Keyword.get(options, :output) || Mix.raise("--output PATH is required")
|
||||||
context = verified_context!(output)
|
context = verified_context!(output, action)
|
||||||
|
|
||||||
case action do
|
case action do
|
||||||
"prepare" -> prepare!(context, request_count, activity_count)
|
"prepare" -> prepare!(context, request_count, activity_count)
|
||||||
|
"append" -> append!(context, request_count, activity_count)
|
||||||
"verify" -> verify!(context, request_count, activity_count, samples)
|
"verify" -> verify!(context, request_count, activity_count, samples)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp usage do
|
defp usage do
|
||||||
"usage: mix wnh.scale_fixtures prepare|verify " <>
|
"usage: mix wnh.scale_fixtures prepare|append|verify " <>
|
||||||
"[--requests COUNT] [--activities COUNT] [--samples COUNT] --output /output/FILE.json"
|
"[--requests COUNT] [--activities COUNT] [--samples COUNT] --output /output/FILE.json"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -50,12 +52,15 @@ defmodule Mix.Tasks.Wnh.ScaleFixtures do
|
||||||
if is_integer(value) and value > 0, do: value, else: Mix.raise("--#{key} must be positive")
|
if is_integer(value) and value > 0, do: value, else: Mix.raise("--#{key} must be positive")
|
||||||
end
|
end
|
||||||
|
|
||||||
defp verified_context!(output) do
|
defp verified_context!(output, action) do
|
||||||
expected_database = required_env!("WNH_SCALE_EXPECTED_DATABASE")
|
expected_database = required_env!("WNH_SCALE_EXPECTED_DATABASE")
|
||||||
output = Path.expand(output)
|
output = Path.expand(output)
|
||||||
|
|
||||||
unless System.get_env("WNH_SCALE_FIXTURE_CONFIRM") == @confirmation do
|
expected_confirmation =
|
||||||
Mix.raise("WNH_SCALE_FIXTURE_CONFIRM must equal #{@confirmation}")
|
if action == "append", do: @additive_confirmation, else: @isolated_confirmation
|
||||||
|
|
||||||
|
unless System.get_env("WNH_SCALE_FIXTURE_CONFIRM") == expected_confirmation do
|
||||||
|
Mix.raise("WNH_SCALE_FIXTURE_CONFIRM must equal #{expected_confirmation}")
|
||||||
end
|
end
|
||||||
|
|
||||||
unless String.starts_with?(output, "/output/") do
|
unless String.starts_with?(output, "/output/") do
|
||||||
|
|
@ -75,6 +80,54 @@ defmodule Mix.Tasks.Wnh.ScaleFixtures do
|
||||||
%{database: actual_database, output: output}
|
%{database: actual_database, output: output}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp append!(context, request_count, activity_count) do
|
||||||
|
before_totals = discovery_counts()
|
||||||
|
before_synthetic = synthetic_discovery_counts()
|
||||||
|
|
||||||
|
if before_synthetic.help_requests > request_count or
|
||||||
|
before_synthetic.activities > activity_count do
|
||||||
|
Mix.raise(
|
||||||
|
"the development database already contains more synthetic scale rows than requested: " <>
|
||||||
|
"#{before_synthetic.help_requests} requests and #{before_synthetic.activities} activities"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
categories = seed_categories!()
|
||||||
|
ensure_viewer!()
|
||||||
|
|
||||||
|
Repo.transaction(
|
||||||
|
fn ->
|
||||||
|
seed_users!()
|
||||||
|
seed_requests!(request_count, categories.help)
|
||||||
|
seed_activities!(activity_count, categories.activity)
|
||||||
|
end,
|
||||||
|
timeout: :infinity
|
||||||
|
)
|
||||||
|
|
||||||
|
Repo.query!(
|
||||||
|
"ANALYZE users, categories, help_requests, activities",
|
||||||
|
[],
|
||||||
|
timeout: :infinity,
|
||||||
|
log: false
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_synthetic_counts!(request_count, activity_count)
|
||||||
|
|
||||||
|
write_summary!(context, "appended", request_count, activity_count, %{
|
||||||
|
expected_kind: "synthetic",
|
||||||
|
totals_before: before_totals,
|
||||||
|
synthetic_before: before_synthetic,
|
||||||
|
synthetic_after: synthetic_discovery_counts()
|
||||||
|
})
|
||||||
|
|
||||||
|
totals = discovery_counts()
|
||||||
|
|
||||||
|
Mix.shell().info(
|
||||||
|
"persistent synthetic scale data is ready alongside existing data in #{context.database}: " <>
|
||||||
|
"#{totals.help_requests} total requests and #{totals.activities} total activities"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
defp prepare!(context, request_count, activity_count) do
|
defp prepare!(context, request_count, activity_count) do
|
||||||
counts = discovery_counts()
|
counts = discovery_counts()
|
||||||
|
|
||||||
|
|
@ -312,6 +365,7 @@ defmodule Mix.Tasks.Wnh.ScaleFixtures do
|
||||||
) AS cities(index, name, longitude, latitude)
|
) AS cities(index, name, longitude, latitude)
|
||||||
WHERE cities.index = value % 20
|
WHERE cities.index = value % 20
|
||||||
) AS city
|
) AS city
|
||||||
|
ON CONFLICT (id) DO NOTHING
|
||||||
""",
|
""",
|
||||||
[rows, @synthetic_users, category_ids],
|
[rows, @synthetic_users, category_ids],
|
||||||
timeout: :infinity,
|
timeout: :infinity,
|
||||||
|
|
@ -379,6 +433,7 @@ defmodule Mix.Tasks.Wnh.ScaleFixtures do
|
||||||
) AS cities(index, name, longitude, latitude)
|
) AS cities(index, name, longitude, latitude)
|
||||||
WHERE cities.index = value % 20
|
WHERE cities.index = value % 20
|
||||||
) AS city
|
) AS city
|
||||||
|
ON CONFLICT (id) DO NOTHING
|
||||||
""",
|
""",
|
||||||
[rows, @synthetic_users, category_ids],
|
[rows, @synthetic_users, category_ids],
|
||||||
timeout: :infinity,
|
timeout: :infinity,
|
||||||
|
|
@ -465,6 +520,17 @@ defmodule Mix.Tasks.Wnh.ScaleFixtures do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp assert_synthetic_counts!(request_count, activity_count) do
|
||||||
|
actual = synthetic_discovery_counts()
|
||||||
|
|
||||||
|
unless actual.help_requests == request_count and actual.activities == activity_count do
|
||||||
|
Mix.raise(
|
||||||
|
"expected #{request_count} synthetic requests and #{activity_count} synthetic activities, " <>
|
||||||
|
"found #{actual.help_requests} and #{actual.activities}"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp discovery_counts do
|
defp discovery_counts do
|
||||||
%{
|
%{
|
||||||
help_requests: scalar!("SELECT count(*) FROM help_requests"),
|
help_requests: scalar!("SELECT count(*) FROM help_requests"),
|
||||||
|
|
@ -472,6 +538,21 @@ defmodule Mix.Tasks.Wnh.ScaleFixtures do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp synthetic_discovery_counts do
|
||||||
|
%{
|
||||||
|
help_requests:
|
||||||
|
scalar!(
|
||||||
|
"SELECT count(*) FROM help_requests " <>
|
||||||
|
"WHERE structured_data @> '{\"scale_fixture\": true}'::jsonb"
|
||||||
|
),
|
||||||
|
activities:
|
||||||
|
scalar!(
|
||||||
|
"SELECT count(*) FROM activities " <>
|
||||||
|
"WHERE structured_data @> '{\"scale_fixture\": true}'::jsonb"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
defp write_summary!(context, status, request_count, activity_count, extra) do
|
defp write_summary!(context, status, request_count, activity_count, extra) do
|
||||||
File.mkdir_p!(Path.dirname(context.output))
|
File.mkdir_p!(Path.dirname(context.output))
|
||||||
|
|
||||||
|
|
|
||||||
173
scripts/dev-scale-seed.sh
Executable file
173
scripts/dev-scale-seed.sh
Executable file
|
|
@ -0,0 +1,173 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
|
||||||
|
|
||||||
|
if [ ! -f "$ROOT/.env" ]; then
|
||||||
|
echo "Missing $ROOT/.env." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -a
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. "$ROOT/.env"
|
||||||
|
set +a
|
||||||
|
|
||||||
|
PROJECT=${WNH_DEV_COMPOSE_PROJECT:-who_need_help}
|
||||||
|
EXPECTED_DATABASE=${WNH_DEV_SCALE_EXPECTED_DATABASE:-who_need_help}
|
||||||
|
REQUESTS=${WNH_DEV_SCALE_REQUESTS:-1000000}
|
||||||
|
ACTIVITIES=${WNH_DEV_SCALE_ACTIVITIES:-1000000}
|
||||||
|
WEB_CONTAINER=${PROJECT}-web-1
|
||||||
|
DB_CONTAINER=${PROJECT}-db-1
|
||||||
|
NETWORK=${PROJECT}_internal
|
||||||
|
TOOLS_IMAGE=who-need-help:dev-scale-tools
|
||||||
|
OUTPUT_DIR="$ROOT/output/dev-scale"
|
||||||
|
SUMMARY="$OUTPUT_DIR/summary.json"
|
||||||
|
|
||||||
|
container_label() {
|
||||||
|
docker inspect "$1" --format "{{index .Config.Labels \"$2\"}}"
|
||||||
|
}
|
||||||
|
|
||||||
|
container_env() {
|
||||||
|
docker inspect "$WEB_CONTAINER" --format '{{range .Config.Env}}{{println .}}{{end}}' |
|
||||||
|
sed -n "s/^$1=//p"
|
||||||
|
}
|
||||||
|
|
||||||
|
require_positive_integer() {
|
||||||
|
case "$2" in
|
||||||
|
''|*[!0-9]*|0)
|
||||||
|
echo "$1 must be a positive integer." >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
require_positive_integer WNH_DEV_SCALE_REQUESTS "$REQUESTS"
|
||||||
|
require_positive_integer WNH_DEV_SCALE_ACTIVITIES "$ACTIVITIES"
|
||||||
|
|
||||||
|
for container in "$WEB_CONTAINER" "$DB_CONTAINER"; do
|
||||||
|
if ! docker inspect "$container" >/dev/null 2>&1; then
|
||||||
|
echo "Required development container $container does not exist." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(docker inspect "$container" --format '{{.State.Running}}')" != true ]; then
|
||||||
|
echo "Required development container $container is not running." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(container_label "$container" com.docker.compose.project)" != "$PROJECT" ]; then
|
||||||
|
echo "Container $container does not belong to Compose project $PROJECT." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$(container_label "$WEB_CONTAINER" com.docker.compose.service)" != web ]; then
|
||||||
|
echo "$WEB_CONTAINER is not the development web service." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(container_label "$DB_CONTAINER" com.docker.compose.service)" != db ]; then
|
||||||
|
echo "$DB_CONTAINER is not the development database service." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! docker network inspect "$NETWORK" >/dev/null 2>&1; then
|
||||||
|
echo "Development network $NETWORK does not exist." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DATABASE_URL=$(container_env DATABASE_URL)
|
||||||
|
SECRET_KEY_BASE=$(container_env SECRET_KEY_BASE)
|
||||||
|
HANDOVER_SECRET=$(container_env HANDOVER_SECRET)
|
||||||
|
RELEASE_COOKIE=$(container_env RELEASE_COOKIE)
|
||||||
|
METRICS_TOKEN=$(container_env METRICS_TOKEN)
|
||||||
|
PHX_HOST=$(container_env PHX_HOST)
|
||||||
|
PHX_SCHEME=$(container_env PHX_SCHEME)
|
||||||
|
PHX_URL_PORT=$(container_env PHX_URL_PORT)
|
||||||
|
DB_USER=$(
|
||||||
|
docker inspect "$DB_CONTAINER" --format '{{range .Config.Env}}{{println .}}{{end}}' |
|
||||||
|
sed -n 's/^POSTGRES_USER=//p'
|
||||||
|
)
|
||||||
|
DB_NAME=$(
|
||||||
|
docker inspect "$DB_CONTAINER" --format '{{range .Config.Env}}{{println .}}{{end}}' |
|
||||||
|
sed -n 's/^POSTGRES_DB=//p'
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ -z "${DEV_SCALE_VIEWER_PASSWORD:-}" ]; then
|
||||||
|
echo "DEV_SCALE_VIEWER_PASSWORD must be set in the project .env." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for pair in \
|
||||||
|
"DATABASE_URL:$DATABASE_URL" \
|
||||||
|
"SECRET_KEY_BASE:$SECRET_KEY_BASE" \
|
||||||
|
"HANDOVER_SECRET:$HANDOVER_SECRET" \
|
||||||
|
"RELEASE_COOKIE:$RELEASE_COOKIE" \
|
||||||
|
"METRICS_TOKEN:$METRICS_TOKEN" \
|
||||||
|
"PHX_HOST:$PHX_HOST" \
|
||||||
|
"PHX_SCHEME:$PHX_SCHEME" \
|
||||||
|
"PHX_URL_PORT:$PHX_URL_PORT"; do
|
||||||
|
name=${pair%%:*}
|
||||||
|
value=${pair#*:}
|
||||||
|
|
||||||
|
if [ -z "$value" ]; then
|
||||||
|
echo "The running development web container is missing $name." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
export DATABASE_URL SECRET_KEY_BASE HANDOVER_SECRET RELEASE_COOKIE METRICS_TOKEN
|
||||||
|
export PHX_HOST PHX_SCHEME PHX_URL_PORT
|
||||||
|
SCALE_VIEWER_PASSWORD=$DEV_SCALE_VIEWER_PASSWORD
|
||||||
|
export SCALE_VIEWER_PASSWORD
|
||||||
|
|
||||||
|
if [ -z "$DB_USER" ] || [ -z "$DB_NAME" ]; then
|
||||||
|
echo "The running development database container is missing POSTGRES_USER or POSTGRES_DB." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
actual_database=$(
|
||||||
|
docker exec "$DB_CONTAINER" \
|
||||||
|
psql -U "$DB_USER" -d "$DB_NAME" -Atc "SELECT current_database()"
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ "$actual_database" != "$EXPECTED_DATABASE" ]; then
|
||||||
|
echo "Refusing dev-scale mutation: expected database $EXPECTED_DATABASE, observed $actual_database." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$OUTPUT_DIR"
|
||||||
|
docker build --target load_tools --tag "$TOOLS_IMAGE" "$ROOT"
|
||||||
|
|
||||||
|
docker run --rm \
|
||||||
|
--network "$NETWORK" \
|
||||||
|
--env APP_ROLE=migrate \
|
||||||
|
--env DATABASE_URL \
|
||||||
|
--env POOL_SIZE=2 \
|
||||||
|
--env ERL_ZFLAGS='+Q 65536 +S 1:1' \
|
||||||
|
--env SECRET_KEY_BASE \
|
||||||
|
--env HANDOVER_SECRET \
|
||||||
|
--env RELEASE_COOKIE \
|
||||||
|
--env METRICS_TOKEN \
|
||||||
|
--env PHX_HOST \
|
||||||
|
--env PHX_SCHEME \
|
||||||
|
--env PHX_URL_PORT \
|
||||||
|
--env SCALE_VIEWER_PASSWORD \
|
||||||
|
--env EMAIL_FROM_NAME='Who Need Help development scale fixtures' \
|
||||||
|
--env EMAIL_FROM_ADDRESS=dev-scale@example.invalid \
|
||||||
|
--env WNH_SCALE_EXPECTED_DATABASE="$EXPECTED_DATABASE" \
|
||||||
|
--env WNH_SCALE_FIXTURE_CONFIRM=persistent-dev-scale \
|
||||||
|
--volume "$OUTPUT_DIR:/output" \
|
||||||
|
"$TOOLS_IMAGE" \
|
||||||
|
mix wnh.scale_fixtures append \
|
||||||
|
--requests "$REQUESTS" \
|
||||||
|
--activities "$ACTIVITIES" \
|
||||||
|
--output /output/summary.json
|
||||||
|
|
||||||
|
docker run --rm \
|
||||||
|
--volume "$OUTPUT_DIR:/output" \
|
||||||
|
alpine:3.23.3@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659 \
|
||||||
|
chown -R "$(id -u):$(id -g)" /output
|
||||||
|
|
||||||
|
printf 'Development scale summary: %s\n' "$SUMMARY"
|
||||||
10
scripts/scale-stack-down.sh
Executable file
10
scripts/scale-stack-down.sh
Executable file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
|
||||||
|
# shellcheck source=scripts/scale-common.sh
|
||||||
|
. "$ROOT/scripts/scale-common.sh"
|
||||||
|
scale_load_environment
|
||||||
|
|
||||||
|
scale_compose down
|
||||||
|
printf 'Removed %s containers and networks; its PostgreSQL volume was preserved.\n' "$LOAD_PROJECT"
|
||||||
Loading…
Reference in New Issue
Block a user