taler-monitoring/ladder/lib_wallet_serve.sh

156 lines
5.1 KiB
Bash

# ladder/lib_wallet_serve.sh — long-lived wallet daemon (harness-style)
#
# taler-harness uses WalletService + WalletClient over a unix socket so the
# wallet shepherd stays up while bank confirm + wirewatch complete. Mon e2e
# already mirrors that with `advanced serve`. Ladder historically used one-shot
# CLI only → coins often stayed pendingIncoming (OK_BANK) until pay-wait.
#
# Source after lib.sh. Callers set: SCRATCH, WDB, CLI_JS or WALLET_CLI, NODE_BIN.
# Optional: LADDER_WALLET_SERVE=1 (default), E2E_WALLET_SERVE (e2e alias).
#
# Public:
# wallet_serve_resolve_bins — NODE_BIN + CLI path
# wallet_serve_start — advanced serve --unix-path
# wallet_serve_stop — kill daemon
# wallet_serve_wcli args… — client via socket if up, else --wallet-db
# wallet_serve_install_trap — EXIT cleanup (idempotent)
: "${LADDER_WALLET_SERVE:=1}"
# e2e reuses same default name
: "${E2E_WALLET_SERVE:=${LADDER_WALLET_SERVE}}"
WSOCK="${WSOCK:-}"
WSERVE_PID="${WSERVE_PID:-}"
_WALLET_SERVE_TRAP_INSTALLED="${_WALLET_SERVE_TRAP_INSTALLED:-0}"
wallet_serve_resolve_bins() {
# Prefer explicit WALLET_CLI / CLI_JS (.mjs); else find_wallet_cli from lib.sh
if [ -z "${CLI_JS:-}" ] || [ ! -f "${CLI_JS:-}" ]; then
if [ -n "${WALLET_CLI:-}" ] && [ -f "${WALLET_CLI}" ]; then
CLI_JS="$WALLET_CLI"
elif command -v find_wallet_cli >/dev/null 2>&1; then
CLI_JS=$(find_wallet_cli 2>/dev/null || true)
fi
fi
if [ -n "${CLI_JS:-}" ] && [ -f "$CLI_JS" ]; then
WALLET_CLI="$CLI_JS"
fi
if [ -z "${NODE_BIN:-}" ] || [ ! -x "${NODE_BIN:-}" ]; then
NODE_BIN=$(command -v node 2>/dev/null || true)
fi
# PATH for taler-helper-sqlite3 (harness/e2e preflight)
local _path="${PATH:-}"
case ":${_path}:" in
*:/opt/homebrew/bin:*) ;;
*) _path="/opt/homebrew/bin:/usr/local/bin:${HOME}/.local/bin:${_path}" ;;
esac
PATH="$_path"
export PATH NODE_BIN CLI_JS WALLET_CLI
}
wallet_serve_stop() {
if [ -n "${WSERVE_PID:-}" ] && kill -0 "$WSERVE_PID" 2>/dev/null; then
kill "$WSERVE_PID" 2>/dev/null || true
wait "$WSERVE_PID" 2>/dev/null || true
fi
WSERVE_PID=""
if [ -n "${WSOCK:-}" ]; then
rm -f "$WSOCK" 2>/dev/null || true
fi
}
wallet_serve_start() {
# Returns 0 if serve is up (or intentionally disabled); 1 if wanted but failed.
wallet_serve_resolve_bins
local want="${LADDER_WALLET_SERVE:-1}"
# e2e callers may only set E2E_WALLET_SERVE
if [ "${E2E_WALLET_SERVE:-}" = "0" ]; then
want=0
fi
if [ "$want" != "1" ]; then
return 0
fi
if [ -z "${NODE_BIN:-}" ] || [ ! -x "${NODE_BIN}" ]; then
return 1
fi
if [ -z "${WALLET_CLI:-}" ] || [ ! -f "${WALLET_CLI}" ]; then
return 1
fi
if [ -z "${WDB:-}" ]; then
return 1
fi
if [ -z "${SCRATCH:-}" ]; then
SCRATCH=$(mktemp -d)
fi
WSOCK="${WSOCK:-$SCRATCH/wallet.sock}"
wallet_serve_stop
rm -f "$WSOCK"
# harness: daemon owns DB; clients use --wallet-connection only (no concurrent --wallet-db)
"$NODE_BIN" "$WALLET_CLI" --wallet-db="$WDB" --no-throttle --skip-defaults \
advanced serve --unix-path "$WSOCK" \
>"${SCRATCH}/wallet-serve.log" 2>&1 &
WSERVE_PID=$!
local i
for i in $(seq 1 50); do
if [ -S "$WSOCK" ] && kill -0 "$WSERVE_PID" 2>/dev/null; then
return 0
fi
# died early
if ! kill -0 "$WSERVE_PID" 2>/dev/null; then
break
fi
sleep 0.1
done
wallet_serve_stop
return 1
}
wallet_serve_install_trap() {
[ "${_WALLET_SERVE_TRAP_INSTALLED}" = "1" ] && return 0
_WALLET_SERVE_TRAP_INSTALLED=1
# Append to existing EXIT trap if any — stop serve first
# shellcheck disable=SC2064
trap 'wallet_serve_stop' EXIT
}
# Run wallet-cli: prefer live serve socket (harness WalletClient path).
# Optional first arg: max seconds (integer) → wrapped with timeout when available.
wallet_serve_wcli() {
wallet_serve_resolve_bins
local maxc=""
if [[ "${1:-}" =~ ^[0-9]+$ ]]; then
maxc=$1
shift
fi
local -a cmd
if [ -n "${NODE_BIN:-}" ] && [ -x "${NODE_BIN}" ] && [ -n "${WALLET_CLI:-}" ] && [ -f "${WALLET_CLI}" ]; then
if [ -n "${WSERVE_PID:-}" ] && [ -S "${WSOCK:-}" ] && kill -0 "$WSERVE_PID" 2>/dev/null; then
cmd=( "$NODE_BIN" "$WALLET_CLI" --wallet-connection="$WSOCK" --no-throttle "$@" )
else
cmd=( "$NODE_BIN" "$WALLET_CLI" --wallet-db="${WDB:?}" --no-throttle --skip-defaults "$@" )
fi
elif [ -n "${CLI_JS:-}" ] && [ -f "$CLI_JS" ]; then
if [ -n "${WSERVE_PID:-}" ] && [ -S "${WSOCK:-}" ]; then
cmd=( node "$CLI_JS" --wallet-connection="$WSOCK" --no-throttle "$@" )
else
cmd=( node "$CLI_JS" --wallet-db="${WDB:?}" --no-throttle "$@" )
fi
else
if [ -n "${WSERVE_PID:-}" ] && [ -S "${WSOCK:-}" ]; then
cmd=( taler-wallet-cli --wallet-connection="$WSOCK" --no-throttle "$@" )
else
cmd=( taler-wallet-cli --wallet-db="${WDB:?}" --no-throttle "$@" )
fi
fi
if [ -n "$maxc" ]; then
if command -v timeout >/dev/null 2>&1; then
timeout -k 2 "$maxc" "${cmd[@]}"
elif command -v gtimeout >/dev/null 2>&1; then
gtimeout --kill-after=2 "$maxc" "${cmd[@]}"
else
"${cmd[@]}"
fi
else
"${cmd[@]}"
fi
}