feat(runner): Fixes and improvements (#259)

## Description

- Improves latency for runner
- Fixes bugs in entrypoint bash scripts
- Package updates, gstreamer 1.26 and workaround for it

Modified runner workflow to hopefully pull latest cachyos base image on
nightlies. This will cause a full build but for nightlies should be
fine?

Also removed the duplicate key-down workaround as we've enabled ordered
datachannels now. Increased retransmit to 2 from 0 to see if it'll help
with some network issues.

Marked as draft as I need to do bug testing still, I'll do it after
fever calms down 😅



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Enhanced deployment workflows with optimized container image
management.
- Improved audio and video processing for lower latency and better
synchronization.
  - Consolidated debugging options to ease command-line monitoring.

- **Refactor**
- Streamlined internal script flow and process handling for smoother
performance.
- Updated dependency management and communication protocols to boost
overall stability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
This commit is contained in:
Kristian Ollikainen
2025-04-13 23:13:09 +03:00
committed by GitHub
parent f408ec56cb
commit 9a6826b069
15 changed files with 1257 additions and 672 deletions

View File

@@ -1,222 +1,233 @@
#!/bin/bash
set -euo pipefail
# Make user directory owned by the default user
chown -f "$(id -nu):$(id -ng)" ~ || \
sudo chown -f "$(id -nu):$(id -ng)" ~ || \
chown -R -f -h --no-preserve-root "$(id -nu):$(id -ng)" ~ || \
sudo chown -R -f -h --no-preserve-root "$(id -nu):$(id -ng)" ~ || \
echo 'Failed to change user directory permissions, there may be permission issues'
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1"
}
# Source environment variables from envs.sh
if [ -f /etc/nestri/envs.sh ]; then
echo "Sourcing environment variables from envs.sh..."
source /etc/nestri/envs.sh
else
echo "envs.sh not found! Ensure it exists at /etc/nestri/envs.sh."
exit 1
fi
# Ensures user directory ownership
chown_user_directory() {
local user_group="$(id -nu):$(id -ng)"
chown -f "$user_group" ~ 2>/dev/null ||
sudo chown -f "$user_group" ~ 2>/dev/null ||
chown -R -f -h --no-preserve-root "$user_group" ~ 2>/dev/null ||
sudo chown -R -f -h --no-preserve-root "$user_group" ~ 2>/dev/null ||
log "Warning: Failed to change user directory permissions, there may be permission issues, continuing..."
}
# Parses resolution string
parse_resolution() {
local resolution="$1"
if [[ -z "$resolution" ]]; then
log "Error: No resolution provided"
return 1
fi
IFS='x' read -r width height <<< "$resolution"
if ! [[ "$width" =~ ^[0-9]+$ ]] || ! [[ "$height" =~ ^[0-9]+$ ]]; then
log "Error: Invalid resolution format. Expected: WIDTHxHEIGHT (e.g., 1920x1080), got: $resolution"
return 1
fi
export WIDTH="$width"
export HEIGHT="$height"
return 0
}
# Loads environment variables
load_envs() {
if [[ -f /etc/nestri/envs.sh ]]; then
log "Sourcing environment variables from envs.sh..."
source /etc/nestri/envs.sh
else
log "Error: envs.sh not found at /etc/nestri/envs.sh"
exit 1
fi
}
# Configuration
MAX_RETRIES=3
RETRY_COUNT=0
# Helper function to restart the chain
restart_chain() {
echo "Restarting nestri-server, compositor..."
# Start nestri-server
start_nestri_server
RETRY_COUNT=0
# Kills process if running
kill_if_running() {
local pid="$1"
local name="$2"
if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
log "Killing existing $name process (PID: $pid)..."
kill "$pid"
wait "$pid" 2>/dev/null || true
fi
}
# Function to start nestri-server
# Starts nestri-server
start_nestri_server() {
if [[ -n "${NESTRI_PID:-}" ]] && kill -0 "${NESTRI_PID}" 2 >/dev/null; then
echo "Killing existing nestri-server process..."
kill "${NESTRI_PID}"
fi
kill_if_running "${NESTRI_PID:-}" "nestri-server"
echo "Starting nestri-server..."
nestri-server $(echo $NESTRI_PARAMS) &
log "Starting nestri-server..."
nestri-server $NESTRI_PARAMS &
NESTRI_PID=$!
# Wait for Wayland display (wayland-1) to be ready
echo "Waiting for Wayland display 'wayland-1' to be ready..."
log "Waiting for Wayland display 'wayland-1'..."
WAYLAND_SOCKET="${XDG_RUNTIME_DIR}/wayland-1"
for _ in {1..15}; do # Wait up to 15 seconds
if [ -e "$WAYLAND_SOCKET" ]; then
echo "Wayland display 'wayland-1' is ready."
sleep 5 # necessary sleep - reduces chance that non-ready socket is used
for ((i=1; i<=15; i++)); do
if [[ -e "$WAYLAND_SOCKET" ]]; then
log "Wayland display 'wayland-1' ready."
sleep 3
start_compositor
return
fi
sleep 1
done
echo "Error: Wayland display 'wayland-1' did not appear. Incrementing retry count..."
((RETRY_COUNT++))
if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then
echo "Max retries reached for nestri-server. Exiting."
exit 1
fi
log "Error: Wayland display 'wayland-1' not available."
increment_retry "nestri-server"
restart_chain
}
# Function to start compositor (labwc)
# Starts compositor (labwc)
start_compositor() {
if [[ -n "${COMPOSITOR_PID:-}" ]] && kill -0 "${COMPOSITOR_PID}" 2 >/dev/null; then
echo "Killing existing compositor process..."
kill "${COMPOSITOR_PID}"
fi
kill_if_running "${COMPOSITOR_PID:-}" "compositor"
echo "Pre-configuring compositor..."
log "Pre-configuring compositor..."
mkdir -p "${HOME}/.config/labwc/"
echo '<?xml version="1.0" encoding="UTF-8"?><labwc_config><keyboard><default/></keyboard><mouse><default/><context name="Root"><mousebind button="Left" action="Press"/><mousebind button="Right" action="Press"/><mousebind button="Middle" action="Press"/></context></mouse></labwc_config>' > ~/.config/labwc/rc.xml
cat > ~/.config/labwc/rc.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<labwc_config>
<keyboard><default/></keyboard>
<mouse><default/>
<context name="Root">
<mousebind button="Left" action="Press"/>
<mousebind button="Right" action="Press"/>
<mousebind button="Middle" action="Press"/>
</context>
</mouse>
</labwc_config>
EOF
echo '<?xml version="1.0" encoding="UTF-8"?><openbox_menu></openbox_menu>' > ~/.config/labwc/menu.xml
echo "Starting compositor..."
log "Starting compositor..."
rm -rf /tmp/.X11-unix && mkdir -p /tmp/.X11-unix && chown nestri:nestri /tmp/.X11-unix
WAYLAND_DISPLAY=wayland-1 WLR_BACKENDS=wayland labwc &
COMPOSITOR_PID=$!
# Wait for compositor to initialize
echo "Waiting for compositor to initialize..."
log "Waiting for compositor to initialize..."
COMPOSITOR_SOCKET="${XDG_RUNTIME_DIR}/wayland-0"
for _ in {1..15}; do
if [ -e "$COMPOSITOR_SOCKET" ]; then
echo "compositor is initialized, wayland-0 output ready."
sleep 3 # necessary sleep - reduces chance that non-ready socket is used
for ((i=1; i<=15; i++)); do
if [[ -e "$COMPOSITOR_SOCKET" ]]; then
log "Compositor initialized, wayland-0 ready."
sleep 2
start_wlr_randr
return
fi
sleep 1
done
echo "Error: compositor did not initialize correctly. Incrementing retry count..."
((RETRY_COUNT++))
if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then
echo "Max retries reached for compositor. Exiting."
exit 1
fi
log "Error: Compositor did not initialize."
increment_retry "compositor"
start_compositor
}
# Function to run wlr-randr
# Configures resolution with wlr-randr
start_wlr_randr() {
echo "Configuring resolution with wlr-randr..."
log "Configuring resolution with wlr-randr..."
OUTPUT_NAME=$(WAYLAND_DISPLAY=wayland-0 wlr-randr --json | jq -r '.[] | select(.enabled == true) | .name' | head -n 1)
if [ -z "$OUTPUT_NAME" ]; then
echo "Error: No enabled outputs detected, exiting."
if [[ -z "$OUTPUT_NAME" ]]; then
log "Error: No enabled outputs detected."
exit 1
fi
# Retry logic for wlr-randr
local WLR_RETRIES=0
while ! WAYLAND_DISPLAY=wayland-0 wlr-randr --output "$OUTPUT_NAME" --custom-mode "$RESOLUTION"; do
echo "Error: Failed to configure wlr-randr. Retrying..."
log "Error: Failed to configure wlr-randr. Retrying..."
((WLR_RETRIES++))
if [ "$WLR_RETRIES" -ge "$MAX_RETRIES" ]; then
echo "Max retries reached for wlr-randr, exiting."
if [[ "$WLR_RETRIES" -ge "$MAX_RETRIES" ]]; then
log "Error: Max retries reached for wlr-randr."
exit 1
fi
sleep 2
done
echo "wlr-randr configuration successful."
sleep 2 # necessary sleep - makes sure resolution is changed before next step(s)
log "wlr-randr configuration successful."
sleep 2
}
# Function to start Steam
# Starts Steam
start_steam() {
if [[ -n "${STEAM_PID:-}" ]] && kill -0 "${STEAM_PID}" 2 >/dev/null; then
echo "Killing existing Steam process..."
kill "${STEAM_PID}"
fi
kill_if_running "${STEAM_PID:-}" "Steam"
echo "Starting Steam with -tenfoot..."
WAYLAND_DISPLAY=wayland-0 steam-native -tenfoot &
log "Starting Steam with -tenfoot..."
steam-native -tenfoot &
STEAM_PID=$!
# Verify Steam started successfully
sleep 2
if ! kill -0 "$STEAM_PID" 2>/dev/null; then
echo "Error: Steam failed to start."
log "Error: Steam failed to start."
return 1
fi
echo "Steam started successfully."
log "Steam started successfully."
return 0
}
# Main loop to monitor processes
# Increments retry counter
increment_retry() {
local component="$1"
((RETRY_COUNT++))
if [[ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]]; then
log "Error: Max retries reached for $component."
exit 1
fi
}
# Restarts the chain
restart_chain() {
log "Restarting nestri-server and compositor..."
RETRY_COUNT=0
start_nestri_server
}
# Cleans up processes
cleanup() {
log "Terminating processes..."
kill_if_running "${NESTRI_PID:-}" "nestri-server"
kill_if_running "${COMPOSITOR_PID:-}" "compositor"
kill_if_running "${STEAM_PID:-}" "Steam"
exit 0
}
# Monitor processes for unexpected exits
main_loop() {
trap 'echo "Terminating...";
if [[ -n "${NESTRI_PID:-}" ]] && kill -0 "${NESTRI_PID}" 2>/dev/null; then
kill "${NESTRI_PID}"
fi
if [[ -n "${COMPOSITOR_PID:-}" ]] && kill -0 "${COMPOSITOR_PID}" 2>/dev/null; then
kill "${COMPOSITOR_PID}"
fi
if [[ -n "${STEAM_PID:-}" ]] && kill -0 "${STEAM_PID}" 2>/dev/null; then
kill "${STEAM_PID}"
fi
exit 0' SIGINT SIGTERM
trap cleanup SIGINT SIGTERM
while true; do
# Wait for any child process to exit
wait -n
# Check which process exited
if ! kill -0 ${NESTRI_PID:-} 2 >/dev/null; then
echo "nestri-server crashed. Restarting chain..."
((RETRY_COUNT++))
if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then
echo "Max retries reached for nestri-server. Exiting."
exit 1
fi
sleep 1
# Check nestri-server
if [[ -n "${NESTRI_PID:-}" ]] && ! kill -0 "${NESTRI_PID}" 2>/dev/null; then
log "nestri-server died."
increment_retry "nestri-server"
restart_chain
start_steam || {
echo "Failed to restart Steam after chain restart."
((RETRY_COUNT++))
if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then
echo "Max retries reached. Exiting."
exit 1
fi
}
elif ! kill -0 ${COMPOSITOR_PID:-} 2 >/dev/null; then
echo "compositor crashed. Restarting compositor..."
((RETRY_COUNT++))
if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then
echo "Max retries reached for compositor. Exiting."
exit 1
fi
start_steam || increment_retry "Steam"
# Check compositor
elif [[ -n "${COMPOSITOR_PID:-}" ]] && ! kill -0 "${COMPOSITOR_PID}" 2>/dev/null; then
log "compositor died."
increment_retry "compositor"
start_compositor
start_steam || {
echo "Failed to restart Steam after compositor restart."
((RETRY_COUNT++))
if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then
echo "Max retries reached. Exiting."
exit 1
fi
}
elif ! kill -0 ${STEAM_PID:-} 2 >/dev/null; then
echo "Steam crashed. Restarting Steam..."
((RETRY_COUNT++))
if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then
echo "Max retries reached for Steam. Exiting."
exit 1
fi
start_steam
start_steam || increment_retry "Steam"
# Check Steam
elif [[ -n "${STEAM_PID:-}" ]] && ! kill -0 "${STEAM_PID}" 2>/dev/null; then
log "Steam died."
increment_retry "Steam"
start_steam || increment_retry "Steam"
fi
done
}
# Initialize retry counter
RETRY_COUNT=0
main() {
chown_user_directory
load_envs
#parse_resolution "${RESOLUTION:-1920x1080}" || exit 1 # Not used currently
restart_chain
start_steam || increment_retry "Steam"
main_loop
}
# Start the initial chain
restart_chain
# Start Steam after initial setup
start_steam
# Enter monitoring loop
main_loop
main