fix(deploy-mining): 支持 Docker 环境的数据库操作和迁移

- 添加 run_psql helper 函数自动检测 Docker 或本地 psql
- 修改 db_create/db_drop/db_status 使用 docker exec
- 修改 db_migrate 支持通过容器运行 prisma migration
- 修改 health_check/show_stats 支持 Docker 环境

解决在服务器 Docker 环境中 full-reset 失败的问题。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-11 23:38:06 -08:00
parent 5d880f011e
commit 5c302bfca8
1 changed files with 88 additions and 20 deletions

View File

@ -220,6 +220,29 @@ load_env() {
KAFKA_BROKERS="${KAFKA_BROKERS:-localhost:9092}"
REDIS_HOST="${REDIS_HOST:-localhost}"
REDIS_PORT="${REDIS_PORT:-6379}"
# Docker container names
POSTGRES_CONTAINER="${POSTGRES_CONTAINER:-postgres}"
KAFKA_CONTAINER="${KAFKA_CONTAINER:-kafka}"
}
# ===========================================================================
# Helper: Execute psql command (auto-detect Docker or local)
# ===========================================================================
run_psql() {
local db="$1"
local sql="$2"
# Try docker exec first (for production Docker environment)
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${POSTGRES_CONTAINER}$"; then
docker exec -e PGPASSWORD="$POSTGRES_PASSWORD" "$POSTGRES_CONTAINER" \
psql -h localhost -U "$POSTGRES_USER" -d "$db" -c "$sql" 2>/dev/null
return $?
fi
# Fall back to local psql
PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$db" -c "$sql" 2>/dev/null
return $?
}
# ===========================================================================
@ -238,9 +261,11 @@ db_create() {
for db in "${dbs_to_create[@]}"; do
log_step "Creating database: $db"
PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d postgres -c "CREATE DATABASE $db;" 2>/dev/null || {
if run_psql "postgres" "CREATE DATABASE $db;"; then
log_success "Database $db created"
else
log_warn "Database $db already exists or creation failed"
}
fi
done
log_success "Database creation completed"
@ -259,9 +284,11 @@ db_drop() {
for db in "${dbs_to_drop[@]}"; do
log_step "Dropping database: $db"
PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d postgres -c "DROP DATABASE IF EXISTS $db WITH (FORCE);" 2>/dev/null || {
if run_psql "postgres" "DROP DATABASE IF EXISTS $db WITH (FORCE);"; then
log_success "Database $db dropped"
else
log_warn "Failed to drop database $db"
}
fi
done
log_success "Database drop completed"
@ -282,9 +309,36 @@ db_migrate() {
service_dir="$SCRIPT_DIR/$service"
if [ -d "$service_dir/prisma" ]; then
log_step "Migrating: $service"
# Check if running in Docker environment (container exists)
local container_name="rwa-${service}"
if docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "^${container_name}$"; then
# Run migration inside the container
log_info "Running migration in container: $container_name"
docker start "$container_name" 2>/dev/null || true
sleep 2
docker exec "$container_name" npx prisma migrate deploy 2>/dev/null || \
docker exec "$container_name" npx prisma db push --accept-data-loss 2>/dev/null || {
log_warn "Container migration failed, trying to build and run temporary container..."
# Build and run a temporary container for migration
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" run --rm "$service" npx prisma migrate deploy 2>/dev/null || \
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" run --rm "$service" npx prisma db push --accept-data-loss 2>/dev/null || {
log_warn "Migration failed for $service"
}
}
elif command -v npx &>/dev/null; then
# Local development: use npx directly
cd "$service_dir"
npx prisma migrate deploy 2>/dev/null || npx prisma db push --accept-data-loss
cd "$SCRIPT_DIR"
else
# No npx and no container - try docker compose run
log_info "No local npx, using docker compose run for migration"
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" run --rm "$service" npx prisma migrate deploy 2>/dev/null || \
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" run --rm "$service" npx prisma db push --accept-data-loss 2>/dev/null || {
log_warn "Migration failed for $service"
}
fi
fi
done
@ -298,8 +352,15 @@ db_status() {
echo "────────────────────────────────────────────────────"
for db in "${MINING_DATABASES[@]}"; do
if PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$db" -c "SELECT 1" &>/dev/null; then
if run_psql "$db" "SELECT 1" &>/dev/null; then
# Get table count using run_psql helper
local table_count
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${POSTGRES_CONTAINER}$"; then
table_count=$(docker exec -e PGPASSWORD="$POSTGRES_PASSWORD" "$POSTGRES_CONTAINER" \
psql -h localhost -U "$POSTGRES_USER" -d "$db" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" 2>/dev/null | tr -d ' ')
else
table_count=$(PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$db" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" 2>/dev/null | tr -d ' ')
fi
echo -e "${GREEN}$db${NC}\t${GREEN}UP${NC}\t\t$table_count tables"
else
echo -e "${RED}$db${NC}\t\t${RED}DOWN${NC}\t\t-"
@ -684,7 +745,7 @@ health_check() {
# Check databases
echo -e "${BOLD}Databases:${NC}"
for db in "${MINING_DATABASES[@]}"; do
if PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$db" -c "SELECT 1" &>/dev/null; then
if run_psql "$db" "SELECT 1" &>/dev/null; then
echo -e " ${GREEN}${NC} $db"
else
echo -e " ${RED}${NC} $db"
@ -738,19 +799,26 @@ health_check() {
show_stats() {
print_section "2.0 System Statistics"
for db in "${MINING_DATABASES[@]}"; do
echo -e "${BOLD}Database: $db${NC}"
if PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$db" -c "SELECT 1" &>/dev/null; then
# Get table row counts
PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$db" -t -c "
local stats_sql="
SELECT tablename AS table,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC
LIMIT 10;
" 2>/dev/null || echo " Could not get table stats"
"
for db in "${MINING_DATABASES[@]}"; do
echo -e "${BOLD}Database: $db${NC}"
if run_psql "$db" "SELECT 1" &>/dev/null; then
# Get table stats using Docker or local psql
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${POSTGRES_CONTAINER}$"; then
docker exec -e PGPASSWORD="$POSTGRES_PASSWORD" "$POSTGRES_CONTAINER" \
psql -h localhost -U "$POSTGRES_USER" -d "$db" -t -c "$stats_sql" 2>/dev/null || echo " Could not get table stats"
else
PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$db" -t -c "$stats_sql" 2>/dev/null || echo " Could not get table stats"
fi
else
echo " Database not available"
fi