#!/bin/bash
#     ___     ____    ___          _           #
#    / _ |   / __/___/ _/__ ____  (_)__ ____   #
#   / __ |_ / _// __/ _/ _ `/ _ \/ / _ `/ _ \  #
#  /_/ |_(_)___/_/ /_/ \_,_/_//_/_/\_,_/_//_/  #
################################################
#          BBB processing CPU timer             #
#          last modified 2026.10.12              #
################################################

set -euo pipefail

# Default schedule
# Reduce worker CPU weight at 16:00
# Restore worker CPU weight at 23:00
STOP_TIME="16:00"
START_TIME="23:00"

# CPU weights
# Lower weight reduces relative CPU share under contention
PEAK_WEIGHT=10

################################################
# Validate command-line parameters
################################################

# Accept either zero or two parameters
if [[ $# -ne 0 && $# -ne 2 ]]; then
    echo "Error: Provide either zero or two parameters."
    echo "Usage:"
    echo "  sudo bash $0"
    echo "  sudo bash $0 STOP_TIME START_TIME"
    echo "Example:"
    echo "  sudo bash $0 16:30 22:30"
    exit 1
fi

# Use custom schedule if provided
if [[ $# -eq 2 ]]; then
    STOP_TIME="$1"
    START_TIME="$2"
fi

# Validate time format (24-hour HH:MM)
validate_time() {
    if [[ ! "$1" =~ ^([01][0-9]|2[0-3]):[0-5][0-9]$ ]]; then
        echo "Error: Invalid time '$1'. Use HH:MM (00:00-23:59)." >&2
        exit 1
    fi
}

validate_time "$STOP_TIME"
validate_time "$START_TIME"

# Prevent identical stop and start times
if [[ "$STOP_TIME" == "$START_TIME" ]]; then
    echo "Error: STOP_TIME and START_TIME must differ." >&2
    exit 1
fi

# Require root privileges
if [[ "$EUID" -ne 0 ]]; then
    echo "Error: Run this script as root."
    echo "Example: sudo bash $0"
    exit 1
fi

################################################
# Disable old stop/start timers before replacing
# their units with CPU-weight timers
################################################

for unit in bbb-stop-processing.timer bbb-start-processing.timer; do
    if systemctl is-active --quiet "$unit" ||
       systemctl is-enabled --quiet "$unit" 2>/dev/null; then
        systemctl disable --now "$unit"
    fi
done

################################################
# Display selected schedule
################################################

echo "Configuring BBB recording worker CPU schedule..."
echo "Reduce CPU weight at: $STOP_TIME"
echo "Restore default weight at: $START_TIME"
echo "Peak CPU weight: $PEAK_WEIGHT"
echo "Normal CPU weight: not-set"

################################################
# Create worker CPU control script
################################################

cat > /usr/local/bin/bbb-set-worker-cpu.sh <<'SCRIPT'
#!/bin/bash
# Dynamically adjust CPU weight for the BBB recording worker
# This script does not stop or restart the worker service
# Only the drop-in created by this script is removed in normal mode

set -euo pipefail

DROPIN_DIR="/run/systemd/system/bbb-rap-resque-worker.service.d"
DROPIN_FILE="$DROPIN_DIR/99-bbb-processing-cpu.conf"

case "${1:-}" in
    peak)
        # Reduce the worker CPU weight during peak hours
        install -d -m 755 "$DROPIN_DIR"

        cat > "$DROPIN_FILE" <<'EOF'
[Service]
CPUWeight=10
EOF

        systemctl daemon-reload
        echo "Worker CPUWeight set to 10 ($(date))"
        ;;
    normal)
        # Remove only this script's override
        # Other service overrides are left untouched
        rm -f "$DROPIN_FILE"

        # Remove the directory only if it is empty
        rmdir "$DROPIN_DIR" 2>/dev/null || true

        systemctl daemon-reload
        echo "Worker CPUWeight override removed ($(date))"
        ;;
    *)
        echo "Usage: $0 {peak|normal}" >&2
        exit 1
        ;;
esac
SCRIPT

chmod 755 /usr/local/bin/bbb-set-worker-cpu.sh

################################################
# Create scripts for peak and off-peak periods
################################################

cat > /usr/local/bin/bbb-reduce-worker-cpu.sh <<'SCRIPT'
#!/bin/bash
# Reduce recording worker CPU weight during peak hours
exec /usr/local/bin/bbb-set-worker-cpu.sh peak
SCRIPT

cat > /usr/local/bin/bbb-restore-worker-cpu.sh <<'SCRIPT'
#!/bin/bash
# Restore the original inherited/default CPU weight
exec /usr/local/bin/bbb-set-worker-cpu.sh normal
SCRIPT

chmod 755 \
    /usr/local/bin/bbb-reduce-worker-cpu.sh \
    /usr/local/bin/bbb-restore-worker-cpu.sh

################################################
# Create systemd service for reducing CPU weight
################################################

cat > /etc/systemd/system/bbb-stop-processing.service <<'UNIT'
[Unit]
Description=Reduce CPU weight of BBB recording worker

[Service]
Type=oneshot
ExecStart=/usr/local/bin/bbb-reduce-worker-cpu.sh
UNIT

################################################
# Create systemd timer for reducing CPU weight
################################################

cat > /etc/systemd/system/bbb-stop-processing.timer <<EOF
[Unit]
Description=Reduce BBB recording worker CPU weight at ${STOP_TIME}

[Timer]
OnCalendar=*-*-* ${STOP_TIME}:00
Persistent=false

[Install]
WantedBy=timers.target
EOF

################################################
# Create systemd service for restoring CPU weight
################################################

cat > /etc/systemd/system/bbb-start-processing.service <<'UNIT'
[Unit]
Description=Restore CPU weight of BBB recording worker

[Service]
Type=oneshot
ExecStart=/usr/local/bin/bbb-restore-worker-cpu.sh
UNIT

################################################
# Create systemd timer for restoring CPU weight
################################################

cat > /etc/systemd/system/bbb-start-processing.timer <<EOF
[Unit]
Description=Restore BBB recording worker CPU weight at ${START_TIME}

[Timer]
OnCalendar=*-*-* ${START_TIME}:00
Persistent=false

[Install]
WantedBy=timers.target
EOF

################################################
# Create boot-time CPU weight initialization script
################################################

cat > /usr/local/bin/bbb-apply-worker-cpu.sh <<EOF
#!/bin/bash
# Apply the appropriate worker CPU weight after boot
# based on the current time and configured schedule

set -euo pipefail

STOP_TIME="${STOP_TIME}"
START_TIME="${START_TIME}"
NOW=\$(date +%H:%M)

if [[ "\$STOP_TIME" < "\$START_TIME" ]]; then
    if [[ "\$NOW" > "\$STOP_TIME" || "\$NOW" == "\$STOP_TIME" ]] &&
       [[ "\$NOW" < "\$START_TIME" ]]; then
        exec /usr/local/bin/bbb-set-worker-cpu.sh peak
    fi
else
    if [[ "\$NOW" > "\$STOP_TIME" || "\$NOW" == "\$STOP_TIME" ||
          "\$NOW" < "\$START_TIME" ]]; then
        exec /usr/local/bin/bbb-set-worker-cpu.sh peak
    fi
fi

exec /usr/local/bin/bbb-set-worker-cpu.sh normal
EOF

chmod 755 /usr/local/bin/bbb-apply-worker-cpu.sh

################################################
# Create boot-time initialization service
################################################

cat > /etc/systemd/system/bbb-apply-worker-cpu.service <<'UNIT'
[Unit]
Description=Apply BBB recording worker CPU weight at boot
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/bbb-apply-worker-cpu.sh

[Install]
WantedBy=multi-user.target
UNIT

################################################
# Reload systemd and activate the new timers
################################################

systemctl daemon-reload

systemctl enable --now bbb-stop-processing.timer
systemctl enable --now bbb-start-processing.timer

# Enable boot-time CPU weight initialization
systemctl enable bbb-apply-worker-cpu.service

# Apply the correct weight immediately
systemctl start bbb-apply-worker-cpu.service

################################################
# Display configuration and timer status
################################################

echo
echo "BBB recording worker CPU schedule configured."
echo "Peak period: $STOP_TIME to $START_TIME"
echo "Peak weight: $PEAK_WEIGHT"
echo "Normal weight: not-set"
echo

# Display the worker CPU settings
systemctl show bbb-rap-resque-worker.service \
    -p CPUWeight -p CPUQuota -p Nice

# Display the next scheduled timer activations
systemctl list-timers --all | grep 'bbb-' || true

# Display current date and time
date