Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
385
vendor/ruvector/crates/ruvector-postgres/docker/dev.sh
vendored
Executable file
385
vendor/ruvector/crates/ruvector-postgres/docker/dev.sh
vendored
Executable file
@@ -0,0 +1,385 @@
|
||||
#!/usr/bin/env bash
|
||||
# RuVector-Postgres Development Environment
|
||||
# Starts PostgreSQL with hot-reload support for extension development
|
||||
|
||||
set -e # Exit on error
|
||||
set -u # Exit on undefined variable
|
||||
set -o pipefail # Exit on pipe failure
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
|
||||
CONTAINER_NAME="ruvector-postgres-dev"
|
||||
IMAGE_NAME="ruvector-postgres:dev"
|
||||
POSTGRES_PORT="${POSTGRES_PORT:-5432}"
|
||||
POSTGRES_USER="${POSTGRES_USER:-postgres}"
|
||||
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-postgres}"
|
||||
POSTGRES_DB="${POSTGRES_DB:-ruvector_dev}"
|
||||
|
||||
# Detect OS
|
||||
OS_TYPE="$(uname -s)"
|
||||
case "${OS_TYPE}" in
|
||||
Linux*) PLATFORM="linux";;
|
||||
Darwin*) PLATFORM="macos";;
|
||||
*) PLATFORM="unknown";;
|
||||
esac
|
||||
|
||||
# Functions
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[✓]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[⚠]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[✗]${NC} $1"
|
||||
}
|
||||
|
||||
log_cmd() {
|
||||
echo -e "${CYAN}[$]${NC} $1"
|
||||
}
|
||||
|
||||
check_dependencies() {
|
||||
log_info "Checking dependencies..."
|
||||
|
||||
# Check Docker
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker is not installed. Please install Docker first."
|
||||
exit 1
|
||||
fi
|
||||
log_success "Docker found"
|
||||
|
||||
# Check cargo-pgrx
|
||||
if ! command -v cargo-pgrx &> /dev/null; then
|
||||
log_warn "cargo-pgrx not found. Installing..."
|
||||
cargo install cargo-pgrx --version 0.12.6 --locked
|
||||
fi
|
||||
log_success "cargo-pgrx found"
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
log_info "Stopping development environment..."
|
||||
docker stop "${CONTAINER_NAME}" 2>/dev/null || true
|
||||
docker rm "${CONTAINER_NAME}" 2>/dev/null || true
|
||||
}
|
||||
|
||||
wait_for_postgres() {
|
||||
log_info "Waiting for PostgreSQL to be ready..."
|
||||
local max_attempts=30
|
||||
local attempt=1
|
||||
|
||||
while [ ${attempt} -le ${max_attempts} ]; do
|
||||
if docker exec "${CONTAINER_NAME}" pg_isready -U "${POSTGRES_USER}" &>/dev/null; then
|
||||
log_success "PostgreSQL is ready!"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo -n "."
|
||||
sleep 1
|
||||
attempt=$((attempt + 1))
|
||||
done
|
||||
|
||||
log_error "PostgreSQL failed to become ready"
|
||||
docker logs "${CONTAINER_NAME}"
|
||||
return 1
|
||||
}
|
||||
|
||||
build_extension() {
|
||||
log_info "Building ruvector-postgres extension..."
|
||||
|
||||
cd "${PROJECT_ROOT}/crates/ruvector-postgres"
|
||||
|
||||
# Build with pgrx
|
||||
cargo pgrx install --pg-config "$(which pg_config)" --release
|
||||
|
||||
log_success "Extension built and installed"
|
||||
}
|
||||
|
||||
start_dev_container() {
|
||||
log_info "Starting development PostgreSQL container..."
|
||||
|
||||
# Create volume for data persistence
|
||||
docker volume create "${CONTAINER_NAME}_data" || true
|
||||
|
||||
# Start PostgreSQL container
|
||||
docker run -d \
|
||||
--name "${CONTAINER_NAME}" \
|
||||
-p "${POSTGRES_PORT}:5432" \
|
||||
-e POSTGRES_USER="${POSTGRES_USER}" \
|
||||
-e POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \
|
||||
-e POSTGRES_DB="${POSTGRES_DB}" \
|
||||
-v "${CONTAINER_NAME}_data:/var/lib/postgresql/data" \
|
||||
-v "${HOME}/.pgrx:/home/postgres/.pgrx:ro" \
|
||||
--health-cmd="pg_isready -U ${POSTGRES_USER}" \
|
||||
--health-interval=5s \
|
||||
--health-timeout=5s \
|
||||
--health-retries=5 \
|
||||
postgres:16-bookworm
|
||||
|
||||
log_success "Container started: ${CONTAINER_NAME}"
|
||||
}
|
||||
|
||||
setup_extension() {
|
||||
log_info "Setting up extension in database..."
|
||||
|
||||
# Create extension
|
||||
docker exec -it "${CONTAINER_NAME}" psql -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -c "CREATE EXTENSION IF NOT EXISTS ruvector_postgres CASCADE;" || {
|
||||
log_warn "Extension not yet installed. Run 'cargo pgrx install' first."
|
||||
return 1
|
||||
}
|
||||
|
||||
log_success "Extension loaded successfully"
|
||||
}
|
||||
|
||||
show_connection_info() {
|
||||
local connection_string="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:${POSTGRES_PORT}/${POSTGRES_DB}"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${GREEN} RuVector-Postgres Development Environment Ready!${NC}"
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
echo -e "${CYAN}Connection String:${NC}"
|
||||
echo -e " ${connection_string}"
|
||||
echo ""
|
||||
echo -e "${CYAN}Quick Connect Commands:${NC}"
|
||||
log_cmd "psql ${connection_string}"
|
||||
log_cmd "docker exec -it ${CONTAINER_NAME} psql -U ${POSTGRES_USER} -d ${POSTGRES_DB}"
|
||||
echo ""
|
||||
echo -e "${CYAN}Development Workflow:${NC}"
|
||||
echo -e " 1. Make changes to extension code"
|
||||
echo -e " 2. Rebuild: ${YELLOW}cargo pgrx install${NC}"
|
||||
echo -e " 3. Reload: ${YELLOW}docker exec ${CONTAINER_NAME} psql -U ${POSTGRES_USER} -d ${POSTGRES_DB} -c 'DROP EXTENSION ruvector_postgres CASCADE; CREATE EXTENSION ruvector_postgres;'${NC}"
|
||||
echo ""
|
||||
echo -e "${CYAN}Useful Commands:${NC}"
|
||||
log_cmd "cargo pgrx test pg16 # Run tests"
|
||||
log_cmd "cargo pgrx package # Create distributable package"
|
||||
log_cmd "docker logs -f ${CONTAINER_NAME} # View PostgreSQL logs"
|
||||
log_cmd "docker stop ${CONTAINER_NAME} # Stop development environment"
|
||||
echo ""
|
||||
echo -e "${CYAN}Container Info:${NC}"
|
||||
echo -e " Name: ${CONTAINER_NAME}"
|
||||
echo -e " Port: ${POSTGRES_PORT}"
|
||||
echo -e " User: ${POSTGRES_USER}"
|
||||
echo -e " Database: ${POSTGRES_DB}"
|
||||
echo -e " Platform: ${PLATFORM}"
|
||||
echo ""
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
watch_and_reload() {
|
||||
log_info "Starting file watcher for hot-reload..."
|
||||
log_warn "File watching requires 'cargo-watch'. Install with: cargo install cargo-watch"
|
||||
|
||||
cd "${PROJECT_ROOT}/crates/ruvector-postgres"
|
||||
|
||||
cargo watch -x "pgrx install" -s "docker exec ${CONTAINER_NAME} psql -U ${POSTGRES_USER} -d ${POSTGRES_DB} -c 'DROP EXTENSION IF EXISTS ruvector_postgres CASCADE; CREATE EXTENSION ruvector_postgres;'"
|
||||
}
|
||||
|
||||
show_usage() {
|
||||
cat << EOF
|
||||
RuVector-Postgres Development Environment
|
||||
|
||||
Usage: $0 [OPTIONS] [COMMAND]
|
||||
|
||||
Commands:
|
||||
start Start development environment (default)
|
||||
stop Stop development environment
|
||||
restart Restart development environment
|
||||
logs Show PostgreSQL logs
|
||||
psql Open psql shell
|
||||
watch Start file watcher for hot-reload
|
||||
rebuild Rebuild and reload extension
|
||||
status Show container status
|
||||
|
||||
Options:
|
||||
-p, --port PORT PostgreSQL port (default: 5432)
|
||||
-u, --user USER PostgreSQL user (default: postgres)
|
||||
-d, --database DB PostgreSQL database (default: ruvector_dev)
|
||||
-b, --background Start in background (default)
|
||||
-f, --foreground Start in foreground with logs
|
||||
-h, --help Show this help message
|
||||
|
||||
Environment Variables:
|
||||
POSTGRES_PORT PostgreSQL port (default: 5432)
|
||||
POSTGRES_USER PostgreSQL user (default: postgres)
|
||||
POSTGRES_PASSWORD PostgreSQL password (default: postgres)
|
||||
POSTGRES_DB PostgreSQL database (default: ruvector_dev)
|
||||
|
||||
Examples:
|
||||
# Start development environment
|
||||
$0 start
|
||||
|
||||
# Start with custom port
|
||||
$0 --port 5433 start
|
||||
|
||||
# Open psql shell
|
||||
$0 psql
|
||||
|
||||
# Watch for changes and auto-reload
|
||||
$0 watch
|
||||
|
||||
# View logs
|
||||
$0 logs
|
||||
EOF
|
||||
}
|
||||
|
||||
cmd_start() {
|
||||
check_dependencies
|
||||
|
||||
# Stop existing container if running
|
||||
docker stop "${CONTAINER_NAME}" 2>/dev/null || true
|
||||
docker rm "${CONTAINER_NAME}" 2>/dev/null || true
|
||||
|
||||
start_dev_container
|
||||
wait_for_postgres
|
||||
|
||||
# Try to setup extension if already built
|
||||
setup_extension || log_warn "Run 'cargo pgrx install' to build and install the extension"
|
||||
|
||||
show_connection_info
|
||||
}
|
||||
|
||||
cmd_stop() {
|
||||
cleanup
|
||||
log_success "Development environment stopped"
|
||||
}
|
||||
|
||||
cmd_restart() {
|
||||
cmd_stop
|
||||
sleep 2
|
||||
cmd_start
|
||||
}
|
||||
|
||||
cmd_logs() {
|
||||
docker logs -f "${CONTAINER_NAME}"
|
||||
}
|
||||
|
||||
cmd_psql() {
|
||||
docker exec -it "${CONTAINER_NAME}" psql -U "${POSTGRES_USER}" -d "${POSTGRES_DB}"
|
||||
}
|
||||
|
||||
cmd_rebuild() {
|
||||
log_info "Rebuilding extension..."
|
||||
cd "${PROJECT_ROOT}/crates/ruvector-postgres"
|
||||
cargo pgrx install --release
|
||||
|
||||
log_info "Reloading extension in database..."
|
||||
docker exec "${CONTAINER_NAME}" psql -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" << 'EOF'
|
||||
DROP EXTENSION IF EXISTS ruvector_postgres CASCADE;
|
||||
CREATE EXTENSION ruvector_postgres;
|
||||
SELECT extname, extversion FROM pg_extension WHERE extname = 'ruvector_postgres';
|
||||
EOF
|
||||
|
||||
log_success "Extension rebuilt and reloaded!"
|
||||
}
|
||||
|
||||
cmd_status() {
|
||||
if docker ps --filter "name=${CONTAINER_NAME}" --format "{{.Names}}" | grep -q "${CONTAINER_NAME}"; then
|
||||
log_success "Container ${CONTAINER_NAME} is running"
|
||||
docker ps --filter "name=${CONTAINER_NAME}"
|
||||
echo ""
|
||||
show_connection_info
|
||||
else
|
||||
log_warn "Container ${CONTAINER_NAME} is not running"
|
||||
echo "Start with: $0 start"
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
local command="start"
|
||||
local foreground=false
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
start|stop|restart|logs|psql|watch|rebuild|status)
|
||||
command="$1"
|
||||
shift
|
||||
;;
|
||||
-p|--port)
|
||||
POSTGRES_PORT="$2"
|
||||
shift 2
|
||||
;;
|
||||
-u|--user)
|
||||
POSTGRES_USER="$2"
|
||||
shift 2
|
||||
;;
|
||||
-d|--database)
|
||||
POSTGRES_DB="$2"
|
||||
shift 2
|
||||
;;
|
||||
-b|--background)
|
||||
foreground=false
|
||||
shift
|
||||
;;
|
||||
-f|--foreground)
|
||||
foreground=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
show_usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown option: $1"
|
||||
show_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Execute command
|
||||
case "${command}" in
|
||||
start)
|
||||
cmd_start
|
||||
if [ "${foreground}" == "true" ]; then
|
||||
cmd_logs
|
||||
fi
|
||||
;;
|
||||
stop)
|
||||
cmd_stop
|
||||
;;
|
||||
restart)
|
||||
cmd_restart
|
||||
;;
|
||||
logs)
|
||||
cmd_logs
|
||||
;;
|
||||
psql)
|
||||
cmd_psql
|
||||
;;
|
||||
watch)
|
||||
watch_and_reload
|
||||
;;
|
||||
rebuild)
|
||||
cmd_rebuild
|
||||
;;
|
||||
status)
|
||||
cmd_status
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown command: ${command}"
|
||||
show_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user