mirror of
https://github.com/rommapp/romm.git
synced 2026-10-12 02:21:58 +00:00
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
145 lines
4.5 KiB
Bash
145 lines
4.5 KiB
Bash
#!/bin/bash
|
|
|
|
set -e
|
|
|
|
echo "Starting entrypoint script..."
|
|
|
|
# Create symlinks for frontend
|
|
if [[ -L /app/frontend/assets/romm/resources ]]; then
|
|
target=$(readlink "/app/frontend/assets/romm/resources")
|
|
|
|
# If the target is not the same as ${ROMM_BASE_PATH}/resources, recreate the symbolic link.
|
|
if [[ ${target} != "${ROMM_BASE_PATH}/resources" ]]; then
|
|
rm "/app/frontend/assets/romm/resources"
|
|
ln -s "${ROMM_BASE_PATH}/resources" "/app/frontend/assets/romm/resources"
|
|
fi
|
|
elif [[ ! -e /app/frontend/assets/romm/resources ]]; then
|
|
# Ensure parent directory exists before creating symbolic link
|
|
mkdir -p "/app/frontend/assets/romm"
|
|
ln -s "${ROMM_BASE_PATH}/resources" "/app/frontend/assets/romm/resources"
|
|
fi
|
|
|
|
# The ./frontend bind mount hides whatever the build wrote under /app/frontend,
|
|
# so link the image's emulator runtimes into the tree the dev server serves.
|
|
if [[ -n ${EMULATOR_ASSETS_DIR-} && -d ${EMULATOR_ASSETS_DIR} ]]; then
|
|
for runtime_dir in "${EMULATOR_ASSETS_DIR}"/*; do
|
|
target="/app/frontend/assets/$(basename "${runtime_dir}")"
|
|
mkdir -p "${target}"
|
|
for entry in "${runtime_dir}"/*; do
|
|
link="${target}/$(basename "${entry}")"
|
|
# Never replace checked-in art that shares a name with a runtime file.
|
|
if [[ -e ${link} && ! -L ${link} ]]; then
|
|
continue
|
|
fi
|
|
ln -sfn "${entry}" "${link}"
|
|
done
|
|
done
|
|
fi
|
|
|
|
# Define a signal handler to propagate termination signals
|
|
function handle_termination() {
|
|
echo "Terminating child processes..."
|
|
# Kill all background jobs
|
|
# trunk-ignore(shellcheck)
|
|
kill -TERM $(jobs -p) 2>/dev/null
|
|
}
|
|
|
|
# Trap SIGTERM and SIGINT signals
|
|
trap handle_termination SIGTERM SIGINT
|
|
|
|
# Set ROMM_AUTH_SECRET_KEY if not already set
|
|
if [[ -z ${ROMM_AUTH_SECRET_KEY-} ]]; then
|
|
ROMM_AUTH_SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
|
|
export ROMM_AUTH_SECRET_KEY
|
|
fi
|
|
|
|
# Start all services in the background
|
|
echo "Starting backend..."
|
|
cd /app/backend
|
|
if [[ ${DEV_MODE:-false} == "true" ]]; then
|
|
echo "Starting backend under debugpy on :5678..."
|
|
# Add --wait-for-client after --listen to pause until VSCode attaches.
|
|
uv run python -m debugpy --listen 0.0.0.0:5678 main.py &
|
|
else
|
|
uv run python main.py &
|
|
fi
|
|
|
|
# REDIS_SSL is a boolean to the app, so "false" and "0" mean plaintext.
|
|
REDIS_USERINFO=""
|
|
REDIS_SSL_VALUE="${REDIS_SSL-}"
|
|
case "${REDIS_SSL_VALUE,,}" in
|
|
1 | true | yes | on) REDIS_SCHEME="rediss" ;;
|
|
*) REDIS_SCHEME="redis" ;;
|
|
esac
|
|
if [[ -n ${REDIS_PASSWORD-} ]]; then
|
|
REDIS_USERINFO="${REDIS_USERNAME-}:${REDIS_PASSWORD}@"
|
|
elif [[ -n ${REDIS_USERNAME-} ]]; then
|
|
REDIS_USERINFO="${REDIS_USERNAME}@"
|
|
fi
|
|
REDIS_URL="${REDIS_SCHEME}://${REDIS_USERINFO}${REDIS_HOST:-127.0.0.1}:${REDIS_PORT:-6379}/${REDIS_DB:-0}"
|
|
|
|
echo "Starting RQ cron scheduler..."
|
|
# The URL carries the password, so it goes through RQ_REDIS_URL rather than
|
|
# --url, which would put it on a world-readable command line.
|
|
PYTHONPATH="/app/backend:${PYTHONPATH-}" \
|
|
RQ_REDIS_URL="${REDIS_URL}" \
|
|
rq cron \
|
|
--path /app/backend \
|
|
--logging-level "${LOGLEVEL:-INFO}" \
|
|
tasks.cron_config &
|
|
|
|
# Set PYTHONPATH so RQ can find the tasks module.
|
|
# Use a worker class that drops the noisy per-sweep "cleaning registries for
|
|
# queue" log line. The maintenance interval keeps its default (~10 min) so
|
|
# orphaned STARTED jobs and stale workers are still pruned promptly.
|
|
# --with-scheduler releases delayed jobs, which is how the watcher's rescans
|
|
# wait out their delay.
|
|
start_rq_worker() {
|
|
local name="$1"
|
|
shift
|
|
|
|
PYTHONPATH="/app/backend:${PYTHONPATH-}" \
|
|
RQ_REDIS_URL="${REDIS_URL}" \
|
|
rq worker \
|
|
--path /app/backend \
|
|
--worker-class handler.rq_worker.RomMWorker \
|
|
--pid "/tmp/${name}.pid" \
|
|
--logging_level "${LOGLEVEL:-INFO}" \
|
|
--with-scheduler \
|
|
"$@" &
|
|
}
|
|
|
|
echo "Starting RQ worker..."
|
|
start_rq_worker rq_worker high default low
|
|
|
|
# Scans get a worker of their own, see SCAN_QUEUE_NAME.
|
|
echo "Starting RQ scan worker..."
|
|
start_rq_worker rq_scan_worker scans
|
|
|
|
# Streaming teardowns get a worker of their own, see STREAMING_QUEUE_NAME.
|
|
echo "Starting RQ streaming worker..."
|
|
start_rq_worker rq_streaming_worker streaming
|
|
|
|
echo "Starting watcher..."
|
|
watchfiles \
|
|
--target-type command \
|
|
'uv run python watcher.py' \
|
|
/app/romm/library &
|
|
|
|
if [[ ${ENABLE_SYNC_FOLDER_WATCHER:-false} == "true" ]]; then
|
|
echo "Starting sync folder watcher..."
|
|
sync_base_path="${ROMM_BASE_PATH:-/romm}/sync"
|
|
mkdir -p "${sync_base_path}"
|
|
watchfiles \
|
|
--target-type command \
|
|
'uv run python sync_watcher.py' \
|
|
"${sync_base_path}" &
|
|
fi
|
|
|
|
# Start the frontend dev server
|
|
cd /app/frontend
|
|
npm run dev &
|
|
|
|
# Wait for all background processes
|
|
wait
|