# This script is automatocally generated by GH Copilot to wrap the command  
# to run Kustvakt server and creates thread dumps on SIGQUIT/SIGTERM at 
# data/threaddumps. Only fallback kill -3 since jstack and jcmd are only 
# available in jdk. 
#
# The script is intended to be used with and be placed at the same location as 
# a compose.yaml. 
 
#!/bin/sh
set -eu

# POSIX-compatible wrapper to start the original command and capture thread
# dumps into /kustvakt/data/threaddumps when the container receives SIGQUIT
# or SIGTERM. This avoids bash-specific syntax so it works with /bin/sh.

DUMP_DIR="/kustvakt/data/threaddumps"
mkdir -p "$DUMP_DIR"

# File where we collect the JVM's stderr stream so kill -3 output can be
# extracted when jcmd/jstack are not available.
STDERR_LOG="/kustvakt/data/logs/jvm-stderr.log"

child_pid=0

on_quit() {
  TS=$(date +"%Y%m%d-%H%M%S")
  FILE="$DUMP_DIR/threaddump-$TS.txt"
  echo "[wrapper] Creating thread dump to $FILE" >&2

  if command -v jcmd >/dev/null 2>&1; then
    echo "[wrapper] Running: jcmd $child_pid Thread.print" >&2
    if jcmd "$child_pid" Thread.print > "$FILE" 2>&1; then
      echo "[wrapper] jcmd wrote $FILE" >&2
    else
      echo "[wrapper] jcmd failed" >&2
    fi
  elif command -v jstack >/dev/null 2>&1; then
    echo "[wrapper] Running: jstack -l $child_pid" >&2
    if jstack -l "$child_pid" > "$FILE" 2>&1; then
      echo "[wrapper] jstack wrote $FILE" >&2
    else
      echo "[wrapper] jstack failed" >&2
    fi
  else
    # If we don't have jcmd/jstack, trigger JVM to print a thread dump to
    # stderr (kill -3) and capture the appended portion from the stderr log.
    MARKER="===THREAD_DUMP_MARKER $TS $child_pid ==="
    printf "%s\n" "$MARKER" >> "$STDERR_LOG" || true
    kill -3 "$child_pid" 2>/dev/null || true
    # give JVM a moment to write to stderr
    sleep 1

    # Extract the portion after the MARKER into the dump file.
    # Find the last occurrence of the marker and tail from the next line.
    if marker_line=$(grep -nF "$MARKER" "$STDERR_LOG" 2>/dev/null | tail -n 1 | cut -d: -f1); then
      if [ -n "$marker_line" ]; then
        # tail from marker_line+1
        start=$((marker_line + 1))
        if tail -n +$start "$STDERR_LOG" > "$FILE" 2>/dev/null; then
          echo "[wrapper] Extracted JVM stderr to $FILE" >&2
        else
          echo "[wrapper] Failed to extract JVM stderr to $FILE" >&2
        fi
      else
        # nothing found; create empty file so caller sees some output
        : > "$FILE" || true
      fi
    else
      : > "$FILE" || true
    fi
  fi

  # If the dump file is empty or missing, fall back to writing last 2000 lines
  if [ ! -s "$FILE" ]; then
    echo "[wrapper] $FILE is empty; writing fallback from $STDERR_LOG" >&2
    printf "[wrapper] Fallback thread dump (no jcmd/jstack output)\n" > "$FILE" || true
    tail -n 2000 "$STDERR_LOG" >> "$FILE" 2>/dev/null || true
    echo "[wrapper] Wrote fallback content to $FILE" >&2
  fi

  # Forward quit/term to child so it can shutdown
  kill -s QUIT "$child_pid" 2>/dev/null || kill -s TERM "$child_pid" 2>/dev/null || true
}

trap 'on_quit' QUIT TERM

if [ "$#" -eq 0 ]; then
  echo "[wrapper] No command provided to start Kustvakt" >&2
  exit 1
fi

first="$1"
shift

# Determine how to invoke the target process.
if command -v "$first" >/dev/null 2>&1; then
  # executable available in PATH
  set -- "$first" "$@"
else
  case "$first" in
    *.jar)
      if [ -f "/kustvakt/$first" ]; then
        set -- java -jar "/kustvakt/$first" "$@"
      else
        set -- java -jar "$first" "$@"
      fi
      ;;
    /*)
      if [ -f "$first" ]; then
        case "$first" in
          *.jar)
            set -- java -jar "$first" "$@"
            ;;
          *)
            set -- "$first" "$@"
            ;;
        esac
      else
        set -- "$first" "$@"
      fi
      ;;
    *)
      if [ -f "/kustvakt/$first" ]; then
        case "/kustvakt/$first" in
          *.jar)
            set -- java -jar "/kustvakt/$first" "$@"
            ;;
          *)
            set -- "/kustvakt/$first" "$@"
            ;;
        esac
      else
        set -- java -jar "$first" "$@"
      fi
      ;;
  esac
fi

WRAPPER_LOG="/kustvakt/data/logs/kustvakt-wrapper.log"
timestamp() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }

echo "[wrapper] Starting child: $*" | tee -a "$WRAPPER_LOG" >&2

# Start the child in background and capture its PID.
# Prefer starting the child in a separate session so it does not receive
# the initial container signal (which docker sends to PID 1). We then
# explicitly forward QUIT/TERM to the child after creating the dump.
if command -v setsid >/dev/null 2>&1; then
  echo "[$(timestamp)] wrapper: starting child with setsid" >> "$WRAPPER_LOG" || true
  setsid "$@" >>"$STDERR_LOG" 2>&1 &
else
  echo "[$(timestamp)] wrapper: setsid not available; starting child normally" >> "$WRAPPER_LOG" || true
  "$@" >>"$STDERR_LOG" 2>&1 &
fi
child_pid=$!

# Record the child's PID to a file and wrapper log for easier debugging
echo "$child_pid" > /kustvakt/data/kustvakt-child.pid 2>/dev/null || true
echo "[$(timestamp)] wrapper: child_pid=$child_pid (pid file: /kustvakt/data/kustvakt-child.pid)" >> "$WRAPPER_LOG" || true

# Wait for the child and propagate exit code
wait "$child_pid"
exit_code=$?
exit $exit_code