340 lines
11 KiB
Bash
340 lines
11 KiB
Bash
#!/bin/bash
|
|
|
|
# Start script for alias.memory_service.service.app.server
|
|
# This script checks and starts Redis and Qdrant services before starting the memory service
|
|
|
|
set -e # Exit on error
|
|
|
|
# Function to print messages
|
|
print_info() {
|
|
echo "[INFO] $1"
|
|
}
|
|
|
|
print_warn() {
|
|
echo "[WARN] $1"
|
|
}
|
|
|
|
print_error() {
|
|
echo "[ERROR] $1"
|
|
}
|
|
|
|
# Function to load .env file
|
|
load_env_file() {
|
|
local env_file="$1"
|
|
local script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
|
|
# If no custom path provided, use default: parent directory (.env file)
|
|
if [ -z "$env_file" ]; then
|
|
env_file="$(dirname "$script_dir")/.env"
|
|
fi
|
|
|
|
if [ -f "$env_file" ]; then
|
|
print_info "Loading environment variables from $env_file"
|
|
# Export variables from .env file, ignoring comments and empty lines
|
|
set -a
|
|
while IFS= read -r line || [ -n "$line" ]; do
|
|
# Skip comments and empty lines
|
|
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
|
[[ -z "${line// }" ]] && continue
|
|
|
|
# Export the variable
|
|
export "$line" 2>/dev/null || true
|
|
done < "$env_file"
|
|
set +a
|
|
else
|
|
print_warn ".env file not found at $env_file, using default environment variables"
|
|
fi
|
|
}
|
|
|
|
# Parse command line arguments
|
|
ENV_FILE=""
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--env-file|-e)
|
|
ENV_FILE="$2"
|
|
shift 2
|
|
;;
|
|
--help|-h)
|
|
echo "Usage: $0 [OPTIONS]"
|
|
echo ""
|
|
echo "Options:"
|
|
echo " -e, --env-file PATH Path to .env file (default: ../.env)"
|
|
echo " -h, --help Show this help message"
|
|
exit 0
|
|
;;
|
|
*)
|
|
print_error "Unknown option: $1"
|
|
echo "Use --help for usage information"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Load .env file before reading configuration
|
|
load_env_file "$ENV_FILE"
|
|
|
|
# Configuration (after loading .env)
|
|
REDIS_HOST="${USER_PROFILING_REDIS_SERVER:-localhost}"
|
|
REDIS_PORT="${USER_PROFILING_REDIS_PORT:-6379}"
|
|
QDRANT_HOST="${QDRANT_HOST:-localhost}"
|
|
QDRANT_PORT="${QDRANT_PORT:-6333}"
|
|
|
|
REDIS_CONTAINER_NAME="user-profiling-redis"
|
|
QDRANT_CONTAINER_NAME="user-profiling-qdrant"
|
|
|
|
# Function to check if a port is open
|
|
check_port() {
|
|
local host=$1
|
|
local port=$2
|
|
# Try using nc (netcat) first, which is more reliable and cross-platform
|
|
if command -v nc &> /dev/null; then
|
|
if nc -z "$host" "$port" 2>/dev/null; then
|
|
return 0
|
|
fi
|
|
fi
|
|
# Fallback to bash TCP check (works on Linux and macOS)
|
|
if bash -c "exec 3<>/dev/tcp/$host/$port" 2>/dev/null; then
|
|
exec 3<&-
|
|
exec 3>&-
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
# Function to check if Redis is running
|
|
check_redis() {
|
|
# First try to ping Redis directly (most reliable method)
|
|
if command -v redis-cli &> /dev/null; then
|
|
if redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" ping &> /dev/null; then
|
|
return 0
|
|
fi
|
|
fi
|
|
# Fallback to port check if redis-cli is not available
|
|
if check_port "$REDIS_HOST" "$REDIS_PORT"; then
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
# Function to check if Qdrant is running
|
|
check_qdrant() {
|
|
# First check if any Qdrant container is running (most reliable)
|
|
if docker ps --format '{{.Names}}' | grep -q "qdrant"; then
|
|
# Check if the port is accessible
|
|
if check_port "$QDRANT_HOST" "$QDRANT_PORT"; then
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# Check if port is open
|
|
if check_port "$QDRANT_HOST" "$QDRANT_PORT"; then
|
|
# Try to check Qdrant health endpoint
|
|
if curl -s -f "http://$QDRANT_HOST:$QDRANT_PORT/health" &> /dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
# If port is open but health check fails, still consider it running
|
|
# (port being allocated usually means service is running)
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
# Function to check if Docker is available
|
|
check_docker() {
|
|
if command -v docker &> /dev/null; then
|
|
if docker info &> /dev/null; then
|
|
return 0
|
|
fi
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
# Function to start Redis using Docker
|
|
start_redis_docker() {
|
|
print_info "Starting Redis container..."
|
|
|
|
# Check if container exists
|
|
if docker ps -a --format '{{.Names}}' | grep -q "^${REDIS_CONTAINER_NAME}$"; then
|
|
# Container exists, check if it's running
|
|
if docker ps --format '{{.Names}}' | grep -q "^${REDIS_CONTAINER_NAME}$"; then
|
|
print_info "Redis container is already running."
|
|
return 0
|
|
else
|
|
print_info "Starting existing Redis container..."
|
|
docker start "$REDIS_CONTAINER_NAME"
|
|
fi
|
|
else
|
|
# Create and start new container
|
|
print_info "Creating and starting new Redis container..."
|
|
docker run -d \
|
|
--name "$REDIS_CONTAINER_NAME" \
|
|
-p "${REDIS_PORT}:6379" \
|
|
-v redis_data:/data \
|
|
redis:latest \
|
|
redis-server --appendonly yes
|
|
fi
|
|
|
|
# Wait for Redis to be ready
|
|
print_info "Waiting for Redis to be ready..."
|
|
max_retries=30
|
|
for i in $(seq 1 $max_retries); do
|
|
if check_redis; then
|
|
print_info "Redis is ready!"
|
|
return 0
|
|
fi
|
|
sleep 1
|
|
if [ $((i % 5)) -eq 0 ]; then
|
|
print_warn "Still waiting for Redis... ($i/$max_retries)"
|
|
fi
|
|
done
|
|
|
|
print_error "Redis failed to start within $max_retries seconds."
|
|
return 1
|
|
}
|
|
|
|
# Function to start Qdrant using Docker
|
|
start_qdrant_docker() {
|
|
print_info "Starting Qdrant container..."
|
|
|
|
# Check if port is already in use by another process/container
|
|
if check_port "$QDRANT_HOST" "$QDRANT_PORT"; then
|
|
print_warn "Port $QDRANT_PORT is already in use. Checking if it's a Qdrant service..."
|
|
# Check if it's our container
|
|
if docker ps --format '{{.Names}}' | grep -q "^${QDRANT_CONTAINER_NAME}$"; then
|
|
print_info "Qdrant container is already running."
|
|
return 0
|
|
fi
|
|
# Check if any container is using this port
|
|
if docker ps --format '{{.Names}} {{.Ports}}' | grep -q ":$QDRANT_PORT"; then
|
|
# Check if it's a Qdrant container
|
|
qdrant_container=$(docker ps --format '{{.Names}} {{.Ports}}' | grep ":$QDRANT_PORT" | grep -i qdrant | head -1 | awk '{print $1}')
|
|
if [ -n "$qdrant_container" ]; then
|
|
print_info "Port $QDRANT_PORT is in use by Qdrant container '$qdrant_container'. Using existing service."
|
|
return 0
|
|
fi
|
|
# Verify it's actually a Qdrant service by checking health endpoint
|
|
if curl -s -f "http://$QDRANT_HOST:$QDRANT_PORT/health" &> /dev/null 2>&1; then
|
|
print_info "Port $QDRANT_PORT is in use by another Qdrant container. Using existing service."
|
|
return 0
|
|
else
|
|
# Port is open, assume it's Qdrant even if health check fails
|
|
print_info "Port $QDRANT_PORT is in use. Assuming Qdrant service is running."
|
|
return 0
|
|
fi
|
|
fi
|
|
# Port is in use but not by a container - verify it's Qdrant
|
|
if curl -s -f "http://$QDRANT_HOST:$QDRANT_PORT/health" &> /dev/null 2>&1; then
|
|
print_info "Port $QDRANT_PORT is in use by a Qdrant service. Using existing service."
|
|
return 0
|
|
fi
|
|
# Port is open, assume it's Qdrant
|
|
print_info "Port $QDRANT_PORT is in use. Assuming Qdrant service is running."
|
|
return 0
|
|
fi
|
|
|
|
# Create storage directory if it doesn't exist
|
|
QDRANT_STORAGE_DIR="${HOME}/.qdrant_storage"
|
|
mkdir -p "$QDRANT_STORAGE_DIR"
|
|
|
|
# Check if container exists
|
|
if docker ps -a --format '{{.Names}}' | grep -q "^${QDRANT_CONTAINER_NAME}$"; then
|
|
# Container exists, check if it's running
|
|
if docker ps --format '{{.Names}}' | grep -q "^${QDRANT_CONTAINER_NAME}$"; then
|
|
print_info "Qdrant container is already running."
|
|
return 0
|
|
else
|
|
print_info "Starting existing Qdrant container..."
|
|
# Check if the port is already in use before starting
|
|
if check_port "$QDRANT_HOST" "$QDRANT_PORT"; then
|
|
# Check if any Qdrant container is using this port
|
|
qdrant_container=$(docker ps --format '{{.Names}} {{.Ports}}' | grep ":$QDRANT_PORT" | grep -i qdrant | head -1 | awk '{print $1}')
|
|
if [ -n "$qdrant_container" ]; then
|
|
print_info "Port $QDRANT_PORT is already in use by Qdrant container '$qdrant_container'. Skipping container start."
|
|
return 0
|
|
fi
|
|
# Port is in use, assume it's Qdrant (even if health check fails)
|
|
print_info "Port $QDRANT_PORT is already in use. Assuming Qdrant service is running. Skipping container start."
|
|
return 0
|
|
fi
|
|
docker start "$QDRANT_CONTAINER_NAME"
|
|
fi
|
|
else
|
|
# Create and start new container
|
|
print_info "Creating and starting new Qdrant container..."
|
|
docker run -d \
|
|
--name "$QDRANT_CONTAINER_NAME" \
|
|
-p "${QDRANT_PORT}:6333" \
|
|
-p "6334:6334" \
|
|
-v "${QDRANT_STORAGE_DIR}:/qdrant/storage" \
|
|
qdrant/qdrant:latest
|
|
fi
|
|
|
|
# Wait for Qdrant to be ready
|
|
print_info "Waiting for Qdrant to be ready..."
|
|
max_retries=30
|
|
for i in $(seq 1 $max_retries); do
|
|
if check_qdrant; then
|
|
print_info "Qdrant is ready!"
|
|
return 0
|
|
fi
|
|
sleep 1
|
|
if [ $((i % 5)) -eq 0 ]; then
|
|
print_warn "Still waiting for Qdrant... ($i/$max_retries)"
|
|
fi
|
|
done
|
|
|
|
print_error "Qdrant failed to start within $max_retries seconds."
|
|
return 1
|
|
}
|
|
|
|
# Main execution
|
|
main() {
|
|
print_info "Starting Memory Service..."
|
|
print_info "Checking dependencies..."
|
|
|
|
# Check Redis
|
|
print_info "Checking Redis at $REDIS_HOST:$REDIS_PORT..."
|
|
if check_redis; then
|
|
print_info "Redis is already running."
|
|
else
|
|
print_warn "Redis is not running."
|
|
if check_docker; then
|
|
start_redis_docker || exit 1
|
|
else
|
|
print_error "Docker is not available. Please start Redis manually or install Docker."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Check Qdrant
|
|
print_info "Checking Qdrant at $QDRANT_HOST:$QDRANT_PORT..."
|
|
if check_qdrant; then
|
|
print_info "Qdrant is already running."
|
|
else
|
|
print_warn "Qdrant is not running."
|
|
if check_docker; then
|
|
start_qdrant_docker || exit 1
|
|
else
|
|
print_error "Docker is not available. Please start Qdrant manually or install Docker."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Start the memory service
|
|
print_info "All dependencies are ready. Starting memory service..."
|
|
print_info "Running: python -m alias.memory_service.service.app.server"
|
|
|
|
# Set environment variables if not already set
|
|
export USER_PROFILING_REDIS_SERVER="${USER_PROFILING_REDIS_SERVER:-localhost}"
|
|
export USER_PROFILING_REDIS_PORT="${USER_PROFILING_REDIS_PORT:-6379}"
|
|
export QDRANT_HOST="${QDRANT_HOST:-localhost}"
|
|
export QDRANT_PORT="${QDRANT_PORT:-6333}"
|
|
|
|
# Run the service
|
|
python -m alias.memory_service.service.app.server
|
|
}
|
|
|
|
# Run main function
|
|
main "$@"
|
|
|