#!/bin/bash

set -eu -o pipefail

readonly script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly task_worker="${script_dir}/../taskworker.js"

if [[ ${EUID} -ne 0 ]]; then
    echo "This script should be run as root." > /dev/stderr
    exit 1
fi

if [[ $# -eq 0 ]]; then
    echo "No arguments supplied"
    exit 1
fi

if [[ "$1" == "--check" ]]; then
    echo "OK"
    exit 0
fi

readonly task_id="$1"
readonly logfile="$2"
readonly nice="$3"
readonly memory_limit_mb="$4" # SI units
readonly oom_score_adjust="$5"

readonly id=$(id -u $SUDO_USER)

readonly service_name="box-task-${task_id}"

systemctl reset-failed "${service_name}" 2>/dev/null || true

options="-p TimeoutStopSec=10s -p MemoryMax=${memory_limit_mb}M -p OOMScoreAdjust=${oom_score_adjust} --wait"

# systemd-run is used to create resource limited tasks. such tasks are in separate cgroup and won't get affected by box start/stop.
# However, we want task to not run when box code is stopped. If dashboard is down, nothing should run in the background.
# Besides, if tasks do continue running, box code needs complex state reconcilation logic on start up.
# To stop tasks on box stop, we could use BindsTo=box.service. While this stops all tasks on systemctl stop, it restarts tasks on systemctl restart!
# Another approach was to use --scope but this is incompatible with --wait (and then we have to start polling status to get exit code)
# So, the implemented solution is to kill the tasks manually on exit by handing SIGTERM with KillMode=mixed which calls stopAllTasks
# As an additional precaution, box start also calls stopAllTasks

# it seems systemd-run does not return the exit status of the process despite --wait but atleast it waits
if ! systemd-run --unit "${service_name}" --wait --uid=${id} --gid=${id} \
    -p TimeoutStopSec=2s -p MemoryMax=${memory_limit_mb}M -p OOMScoreAdjust=${oom_score_adjust} --nice "${nice}" \
    --setenv HOME=${HOME} --setenv USER=${SUDO_USER} --setenv BOX_ENV=${BOX_ENV} --setenv NODE_ENV=production \
    "${task_worker}" "${task_id}" "${logfile}"; then
    echo "Service ${service_name} failed to run" # this only happens if the path to task worker itself is wrong
fi

# ExecMainCode=0 means killed by signal in ExecMainStatus. ExecMainCode=1 means exited cleanly with code in ExecMainStatus
exit_code=$(systemctl show "${service_name}" -p ExecMainCode | sed 's/ExecMainCode=//g')
exit_status=$(systemctl show "${service_name}" -p ExecMainStatus | sed 's/ExecMainStatus=//g')

echo "Service ${service_name} finished with exit code ${exit_code} and status ${exit_status}"
exit "${exit_status}"
