345 lines
9.4 KiB
Bash
345 lines
9.4 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
COMPOSE_FILE="$ROOT_DIR/local-services.compose.yml"
|
|
ENV_FILE="${LIKEI_ENV_FILE:-$ROOT_DIR/.env.local}"
|
|
DOCKER_APP_BIN_DIR="/Applications/Docker.app/Contents/Resources/bin"
|
|
|
|
resolve_default_workspace_dir() {
|
|
local candidate
|
|
for candidate in "$ROOT_DIR/.." "$ROOT_DIR/../chatapp3" "$ROOT_DIR/../../chatapp3" "$ROOT_DIR/../.."; do
|
|
if [ -d "$candidate/chatapp3-java" ] && [ -d "$candidate/chatapp3-golang" ]; then
|
|
cd "$candidate" && pwd
|
|
return 0
|
|
fi
|
|
done
|
|
cd "$ROOT_DIR/.." && pwd
|
|
}
|
|
|
|
DEFAULT_WORKSPACE_DIR="$(resolve_default_workspace_dir)"
|
|
WORKSPACE_DIR="$DEFAULT_WORKSPACE_DIR"
|
|
JAVA_REPO_DIR="$WORKSPACE_DIR/chatapp3-java"
|
|
GOLANG_REPO_DIR="$WORKSPACE_DIR/chatapp3-golang"
|
|
|
|
configure_local_repo_paths() {
|
|
if [ -n "${LIKEI_WORKSPACE_DIR:-}" ]; then
|
|
WORKSPACE_DIR="$(cd "$LIKEI_WORKSPACE_DIR" && pwd)"
|
|
else
|
|
WORKSPACE_DIR="$DEFAULT_WORKSPACE_DIR"
|
|
fi
|
|
|
|
JAVA_REPO_DIR="${LIKEI_LOCAL_JAVA_REPO_DIR:-$WORKSPACE_DIR/chatapp3-java}"
|
|
GOLANG_REPO_DIR="${LIKEI_LOCAL_GOLANG_REPO_DIR:-$WORKSPACE_DIR/chatapp3-golang}"
|
|
|
|
export WORKSPACE_DIR
|
|
export JAVA_REPO_DIR
|
|
export GOLANG_REPO_DIR
|
|
export LIKEI_LOCAL_JAVA_REPO_DIR="$JAVA_REPO_DIR"
|
|
export LIKEI_LOCAL_GOLANG_REPO_DIR="$GOLANG_REPO_DIR"
|
|
}
|
|
|
|
configure_local_repo_paths
|
|
|
|
trim_spaces() {
|
|
local value="${1:-}"
|
|
value="${value#"${value%%[![:space:]]*}"}"
|
|
value="${value%"${value##*[![:space:]]}"}"
|
|
printf '%s' "$value"
|
|
}
|
|
|
|
strip_wrapping_quotes() {
|
|
local value="${1:-}"
|
|
if [ "${#value}" -ge 2 ]; then
|
|
case "$value" in
|
|
\"*\")
|
|
printf '%s' "${value:1:${#value}-2}"
|
|
return 0
|
|
;;
|
|
\'*\')
|
|
printf '%s' "${value:1:${#value}-2}"
|
|
return 0
|
|
;;
|
|
esac
|
|
fi
|
|
printf '%s' "$value"
|
|
}
|
|
|
|
is_truthy() {
|
|
case "${1:-}" in
|
|
1|true|TRUE|True|yes|YES|Yes|y|Y|on|ON|On)
|
|
return 0
|
|
;;
|
|
*)
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
local_rocketmq_disabled() {
|
|
is_truthy "${LIKEI_ROCKETMQ_LOCAL_DISABLE:-true}"
|
|
}
|
|
|
|
configure_local_runtime_defaults() {
|
|
if [ -z "${LIKEI_LOCAL_OTHER_JAVA_OPTS_EXTRA+x}" ]; then
|
|
if local_rocketmq_disabled; then
|
|
export LIKEI_LOCAL_OTHER_JAVA_OPTS_EXTRA="-Dspring.autoconfigure.exclude=com.red.circle.component.mq.config.RocketMQAutoConfiguration"
|
|
else
|
|
export LIKEI_LOCAL_OTHER_JAVA_OPTS_EXTRA=""
|
|
fi
|
|
fi
|
|
}
|
|
|
|
load_local_env() {
|
|
if [ -f "$ENV_FILE" ]; then
|
|
while IFS= read -r raw_line || [ -n "$raw_line" ]; do
|
|
local line key value
|
|
line="$(trim_spaces "$raw_line")"
|
|
[ -n "$line" ] || continue
|
|
case "$line" in
|
|
\#*)
|
|
continue
|
|
;;
|
|
export\ *)
|
|
line="${line#export }"
|
|
;;
|
|
esac
|
|
case "$line" in
|
|
*=*)
|
|
key="${line%%=*}"
|
|
value="${line#*=}"
|
|
key="$(trim_spaces "$key")"
|
|
value="$(trim_spaces "$value")"
|
|
value="$(strip_wrapping_quotes "$value")"
|
|
export "$key=$value"
|
|
;;
|
|
esac
|
|
done < "$ENV_FILE"
|
|
fi
|
|
export LIKEI_ENV_FILE="$ENV_FILE"
|
|
export LIKEI_ENV_MODE="local"
|
|
configure_local_repo_paths
|
|
configure_local_runtime_defaults
|
|
}
|
|
|
|
ensure_docker_cli() {
|
|
if command -v docker >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
if [ -d "$DOCKER_APP_BIN_DIR" ]; then
|
|
export PATH="$DOCKER_APP_BIN_DIR:$PATH"
|
|
fi
|
|
command -v docker >/dev/null 2>&1
|
|
}
|
|
|
|
wait_for_docker() {
|
|
ensure_docker_cli || {
|
|
echo "docker CLI not found" >&2
|
|
exit 1
|
|
}
|
|
|
|
if docker info >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
|
|
if [ -d "/Applications/Docker.app" ]; then
|
|
open -a Docker >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
for _ in $(seq 1 120); do
|
|
if docker info >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
sleep 2
|
|
done
|
|
|
|
echo "docker daemon did not become ready in time" >&2
|
|
exit 1
|
|
}
|
|
|
|
compose() {
|
|
docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" "$@"
|
|
}
|
|
|
|
wait_http() {
|
|
local url="$1"
|
|
local retries="${2:-120}"
|
|
for _ in $(seq 1 "$retries"); do
|
|
if curl -fsS "$url" >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
sleep 2
|
|
done
|
|
echo "service did not become healthy in time: $url" >&2
|
|
exit 1
|
|
}
|
|
|
|
wait_tcp_port() {
|
|
local host="$1"
|
|
local port="$2"
|
|
local retries="${3:-120}"
|
|
for _ in $(seq 1 "$retries"); do
|
|
if nc -z "$host" "$port" >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
sleep 2
|
|
done
|
|
echo "tcp port did not become ready in time: $host:$port" >&2
|
|
exit 1
|
|
}
|
|
|
|
wait_container_healthy() {
|
|
local container_name="$1"
|
|
local retries="${2:-120}"
|
|
for _ in $(seq 1 "$retries"); do
|
|
local state
|
|
state="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$container_name" 2>/dev/null || true)"
|
|
if [ "$state" = "healthy" ] || [ "$state" = "running" ]; then
|
|
return 0
|
|
fi
|
|
sleep 2
|
|
done
|
|
echo "container did not become healthy in time: $container_name" >&2
|
|
exit 1
|
|
}
|
|
|
|
wait_rocketmq_cluster() {
|
|
local retries="${1:-120}"
|
|
for _ in $(seq 1 "$retries"); do
|
|
if docker exec chatapp3-local-rocketmq-broker sh mqadmin clusterList -n rocketmq-namesrv:9876 2>/dev/null | grep -q "DefaultCluster"; then
|
|
return 0
|
|
fi
|
|
sleep 2
|
|
done
|
|
echo "rocketmq cluster did not become ready in time: DefaultCluster" >&2
|
|
exit 1
|
|
}
|
|
|
|
wait_local_rocketmq() {
|
|
if local_rocketmq_disabled; then
|
|
return 0
|
|
fi
|
|
|
|
require_env LIKEI_LOCAL_ROCKETMQ_NAMESRV_PORT
|
|
require_env LIKEI_LOCAL_ROCKETMQ_PROXY_GRPC_PORT
|
|
|
|
wait_container_healthy chatapp3-local-rocketmq-namesrv 120
|
|
wait_container_healthy chatapp3-local-rocketmq-broker 120
|
|
wait_container_healthy chatapp3-local-rocketmq-proxy 120
|
|
wait_tcp_port 127.0.0.1 "${LIKEI_LOCAL_ROCKETMQ_NAMESRV_PORT}" 120
|
|
wait_rocketmq_cluster 120
|
|
wait_tcp_port 127.0.0.1 "${LIKEI_LOCAL_ROCKETMQ_PROXY_GRPC_PORT}" 120
|
|
}
|
|
|
|
require_env() {
|
|
local key="$1"
|
|
if [ -z "${!key:-}" ]; then
|
|
echo "required environment variable is missing: $key" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
java_major_version() {
|
|
if ! command -v java >/dev/null 2>&1; then
|
|
return 1
|
|
fi
|
|
|
|
local raw_version major
|
|
raw_version="$(java -version 2>&1 | awk -F '"' '/version/ {print $2; exit}')"
|
|
[ -n "$raw_version" ] || return 1
|
|
|
|
major="${raw_version%%.*}"
|
|
if [ "$major" = "1" ]; then
|
|
major="$(printf '%s\n' "$raw_version" | awk -F. '{print $2}')"
|
|
fi
|
|
|
|
printf '%s\n' "$major"
|
|
}
|
|
|
|
require_java_17() {
|
|
local major
|
|
major="$(java_major_version || true)"
|
|
if [ -z "$major" ]; then
|
|
echo "java not found; rebuilding local Java services requires JDK 17" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$major" != "17" ]; then
|
|
echo "rebuilding local Java services requires JDK 17; current java major version is $major" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
is_java_service() {
|
|
case "$1" in
|
|
gateway|auth|external|other|live|order|wallet|console|visual-monitor|scheduling|game-fruit)
|
|
return 0
|
|
;;
|
|
*)
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
java_artifact_path_for_service() {
|
|
case "$1" in
|
|
gateway) printf '%s\n' "$JAVA_REPO_DIR/rc-gateway/target/rc-gateway-1.0.0-local.jar" ;;
|
|
auth) printf '%s\n' "$JAVA_REPO_DIR/rc-auth/target/rc-auth-1.0.0-local.jar" ;;
|
|
external) printf '%s\n' "$JAVA_REPO_DIR/rc-service/rc-service-external/external-start/target/rc-service-external-1.0.0-local.jar" ;;
|
|
other) printf '%s\n' "$JAVA_REPO_DIR/rc-service/rc-service-other/other-start/target/rc-service-other-1.0.0-local.jar" ;;
|
|
live) printf '%s\n' "$JAVA_REPO_DIR/rc-service/rc-service-live/live-start/target/rc-service-live-1.0.0-local.jar" ;;
|
|
order) printf '%s\n' "$JAVA_REPO_DIR/rc-service/rc-service-order/order-start/target/rc-service-order-1.0.0-local.jar" ;;
|
|
wallet) printf '%s\n' "$JAVA_REPO_DIR/rc-service/rc-service-wallet/wallet-start/target/rc-service-wallet-1.0.0-local.jar" ;;
|
|
console) printf '%s\n' "$JAVA_REPO_DIR/rc-service/rc-service-console/console-start/target/rc-service-console-1.0.0-local.jar" ;;
|
|
visual-monitor) printf '%s\n' "$JAVA_REPO_DIR/rc-visual/visual-monitor/target/visual-monitor-1.0.0-local.jar" ;;
|
|
scheduling) printf '%s\n' "$JAVA_REPO_DIR/rc-scheduling/target/rc-scheduling-1.0.0-local.jar" ;;
|
|
game-fruit) printf '%s\n' "$JAVA_REPO_DIR/rc-service-game/game-fruit/target/game-fruit-1.0.0-local.jar" ;;
|
|
*)
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
all_local_java_jars_present() {
|
|
local service artifact_path
|
|
for service in gateway auth external other live order wallet console visual-monitor scheduling game-fruit; do
|
|
artifact_path="$(java_artifact_path_for_service "$service")" || return 1
|
|
if [ ! -f "$artifact_path" ]; then
|
|
echo "missing local jar: $artifact_path" >&2
|
|
return 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
service_port() {
|
|
local env_key
|
|
case "$1" in
|
|
gateway) env_key="LIKEI_LOCAL_GATEWAY_PORT" ;;
|
|
auth) env_key="LIKEI_LOCAL_AUTH_PORT" ;;
|
|
wallet) env_key="LIKEI_LOCAL_WALLET_PORT" ;;
|
|
other) env_key="LIKEI_LOCAL_OTHER_PORT" ;;
|
|
live) env_key="LIKEI_LOCAL_LIVE_PORT" ;;
|
|
order) env_key="LIKEI_LOCAL_ORDER_PORT" ;;
|
|
console) env_key="LIKEI_LOCAL_CONSOLE_PORT" ;;
|
|
scheduling) env_key="LIKEI_LOCAL_SCHEDULING_PORT" ;;
|
|
golang) env_key="LIKEI_LOCAL_GOLANG_PORT" ;;
|
|
external) env_key="LIKEI_LOCAL_EXTERNAL_PORT" ;;
|
|
visual-monitor) env_key="LIKEI_LOCAL_VISUAL_MONITOR_PORT" ;;
|
|
game-fruit) env_key="LIKEI_LOCAL_GAME_FRUIT_PORT" ;;
|
|
*)
|
|
return 1
|
|
;;
|
|
esac
|
|
require_env "$env_key"
|
|
printf '%s\n' "${!env_key}"
|
|
}
|
|
|
|
wait_service_port() {
|
|
local service="$1"
|
|
local retries="${2:-120}"
|
|
local port
|
|
port="$(service_port "$service")" || {
|
|
echo "unknown app service port: $service" >&2
|
|
exit 1
|
|
}
|
|
wait_tcp_port 127.0.0.1 "$port" "$retries"
|
|
}
|