diff --git a/backend.js b/backend.js index 593a35f..7b7c120 100644 --- a/backend.js +++ b/backend.js @@ -57,9 +57,11 @@ const logger = { }, _write(streams, obj) { const line = JSON.stringify(obj) + '\n'; - const writable = streams.filter(Boolean); + const writable = streams.filter((s) => s && !s.destroyed && s.writable); if (writable.length > 0) { - for (const s of writable) s.write(line); + for (const s of writable) { + try { s.write(line); } catch (e) { console.error(`[backend] stream write error: ${e.message}`); } + } } else { console.log(line.trimEnd()); } @@ -210,8 +212,9 @@ app.post('/autofix/webhook', async (req, res) => { const rawBody = req.rawBody; if (!rawBody || !Buffer.isBuffer(rawBody)) { - logger.error('autofix.webhook', 'Missing rawBody — middleware misconfiguration', { requestId }); - return res.status(500).json({ ok: false, error: 'Internal server error', requestId }); + // Log as server-side misconfiguration but return 400 so senders don't retry indefinitely. + logger.error('autofix.webhook', 'Missing rawBody — raw-body middleware did not run', { requestId }); + return res.status(400).json({ ok: false, error: 'Bad request: missing body', requestId }); } if (!AUTOFIX_SECRET || !verifySignature(rawBody, sig)) { diff --git a/prod-run.sh b/prod-run.sh index 1ca91ff..47c4981 100755 --- a/prod-run.sh +++ b/prod-run.sh @@ -400,7 +400,12 @@ ENDPOINT_PORT="${ENDPOINT_PORT:-3001}" ENDPOINT_LOG_DIR="$LOG_DIR" ENDPOINT_LOG="$ENDPOINT_LOG_DIR/backend.log" ENDPOINT_ERR="$ENDPOINT_LOG_DIR/backend-error.log" -touch "$ENDPOINT_LOG" "$ENDPOINT_ERR" 2>/dev/null || true +if ! touch "$ENDPOINT_LOG" "$ENDPOINT_ERR" 2>/dev/null; then + warn "Cannot write to $ENDPOINT_LOG_DIR — falling back to /tmp for endpoint logs" + ENDPOINT_LOG="/tmp/runewager-backend.log" + ENDPOINT_ERR="/tmp/runewager-backend-error.log" + touch "$ENDPOINT_LOG" "$ENDPOINT_ERR" || true +fi if command -v systemctl >/dev/null 2>&1; then # Install/refresh the service unit from repo copy @@ -424,7 +429,8 @@ if command -v systemctl >/dev/null 2>&1; then say "runewager-endpoint restarted via systemd" else warn "systemctl restart runewager-endpoint failed — falling back to nohup" - pkill -f "node .*${PROJECT_DIR}/backend\.js" 2>/dev/null || true + _esc_dir="$(printf '%s' "$PROJECT_DIR" | sed 's/[.[\*^$()+?{|]/\\&/g')" + pkill -f "node .*${_esc_dir}/backend\.js" 2>/dev/null || true sleep 1 # Re-check port: another process may have bound it during the failed systemd restart window if is_port_listening "$ENDPOINT_PORT"; then @@ -439,7 +445,8 @@ if command -v systemctl >/dev/null 2>&1; then fi else # No systemd — direct nohup - pkill -f "node .*${PROJECT_DIR}/backend\.js" 2>/dev/null || true + _esc_dir="$(printf '%s' "$PROJECT_DIR" | sed 's/[.[\*^$()+?{|]/\\&/g')" + pkill -f "node .*${_esc_dir}/backend\.js" 2>/dev/null || true sleep 1 if is_port_listening "$ENDPOINT_PORT"; then free_port_if_conflicted "$ENDPOINT_PORT" "" || true diff --git a/runewager-endpoint.service b/runewager-endpoint.service index 469ed2d..5d74b4b 100644 --- a/runewager-endpoint.service +++ b/runewager-endpoint.service @@ -23,7 +23,8 @@ Type=simple WorkingDirectory=/var/www/html/Runewager # Clear any stale process holding port 3001 before each start to prevent EADDRINUSE crash-loops. # The '+' prefix runs this step as root so it can kill processes owned by any user. -ExecStartPre=+/bin/sh -c 'port=${ENDPOINT_PORT:-3001}; pid=$(lsof -t -i:"$port" 2>/dev/null || fuser "$port"/tcp 2>/dev/null || true); [ -n "$pid" ] && echo "[endpoint-prestart] killing stale PID $pid on port $port" && kill -9 $pid && sleep 1 || true' +# Graceful escalation: SIGTERM → 3s wait → SIGKILL (only if still alive). +ExecStartPre=+/bin/sh -c 'port=${ENDPOINT_PORT:-3001}; pid=$(lsof -t -i:"$port" 2>/dev/null || fuser -t "$port"/tcp 2>/dev/null || true); [ -z "$pid" ] && exit 0; echo "[endpoint-prestart] SIGTERM PID $pid on port $port"; kill -TERM "$pid" 2>/dev/null || true; sleep 3; kill -0 "$pid" 2>/dev/null && { echo "[endpoint-prestart] escalating to SIGKILL"; kill -KILL "$pid" 2>/dev/null || true; sleep 1; } || true' ExecStart=/usr/bin/node /var/www/html/Runewager/backend.js User=root Group=root