Rocko's round 2 candidate, packet agents/rocko/work/s4-follow-up/
(build.patch c8cec070, candidate manifest 5b067a9d, 8/8 OK).
- Definite DM refusals wait the full 30-minute cap, counted from the
journal's last refusal, so five refusals span about two hours before
gave-up (lead decision 73). Unknown outcomes keep doubling.
- Broker close sends at host.mjs:144/150/184/188 pass a callback, which
closes the EPIPE window both reviewers found in round 1.
- README documents manual recovery for an open decision.
- trackers-boot test, X9, X14, and Darkwing's round 1 notes 1-4.
- The append type check stays out; Rocko's reason holds (both reviewers
agree).
Reviews: Darkwing approve (comment 26884), Filbert approve (26886).
Landing gate on b13fef4c plus the patch: every node suite and every
scripts/test-*.sh green, test-task 98/0.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
124 lines
4.8 KiB
Bash
Executable File
124 lines
4.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# `scripts/bus-service.sh render|install|uninstall|status [<business>]`:
|
|
# the systemd user unit that supervises `scripts/mosaic bus start <business>`
|
|
# (lead decision 70). The template is
|
|
# packages/cli/systemd/mosaic-bus.service.in; the rendered unit is
|
|
# [email protected] in the systemd user directory, one instance per
|
|
# business (mosaic-bus@<business>). Nothing here reads a capability, the
|
|
# binding or the token. See packages/cli/README.md, "Bus host".
|
|
#
|
|
# render print the rendered unit on stdout
|
|
# install [--dir DIR] [--no-reload]
|
|
# write the unit (write to a temp file, then
|
|
# rename) and run `systemctl --user daemon-reload`
|
|
# uninstall [--dir DIR] [--no-reload]
|
|
# remove the unit; refuses while an instance is active
|
|
# status <business> unit state, then `mosaic bus status`
|
|
#
|
|
# Exit codes: 0 ok, 1 operation failed, 4 usage.
|
|
set -euo pipefail
|
|
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
TEMPLATE="$REPO/packages/cli/systemd/mosaic-bus.service.in"
|
|
UNIT_NAME="[email protected]"
|
|
USAGE="usage: scripts/bus-service.sh render | install [--dir DIR] [--no-reload] | uninstall [--dir DIR] [--no-reload] | status <business>"
|
|
|
|
die() { echo "bus-service: $*" >&2; exit 1; }
|
|
usage() { echo "$USAGE" >&2; exit 4; }
|
|
|
|
render() {
|
|
[ -f "$TEMPLATE" ] || die "template missing: $TEMPLATE"
|
|
local node_dir
|
|
node_dir="$(dirname "$(command -v node || true)")"
|
|
[ -n "$node_dir" ] && [ "$node_dir" != "." ] || die "node not found on PATH"
|
|
local path="/usr/local/bin:/usr/bin:/bin"
|
|
case ":$path:" in *":$node_dir:"*) ;; *) path="$node_dir:$path" ;; esac
|
|
case "$REPO" in *@*|*'|'*) die "repository path contains a character the template cannot carry: $REPO" ;; esac
|
|
sed -e "s|@REPO@|$REPO|g" -e "s|@PATH@|$path|g" "$TEMPLATE"
|
|
}
|
|
|
|
UNIT_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
|
|
RELOAD=1
|
|
parse_flags() {
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--dir) [ $# -ge 2 ] || usage; UNIT_DIR="$2"; shift 2 ;;
|
|
--no-reload) RELOAD=0; shift ;;
|
|
*) usage ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
install_unit() {
|
|
parse_flags "$@"
|
|
mkdir -p "$UNIT_DIR"
|
|
local target="$UNIT_DIR/$UNIT_NAME" tmp
|
|
tmp="$(mktemp "$UNIT_DIR/.$UNIT_NAME.XXXXXX")"
|
|
render > "$tmp"
|
|
chmod 0644 "$tmp"
|
|
if [ -f "$target" ] && cmp -s "$tmp" "$target"; then
|
|
rm -f "$tmp"
|
|
echo "unchanged: $target"
|
|
else
|
|
mv -f "$tmp" "$target"
|
|
echo "written: $target"
|
|
fi
|
|
if [ "$RELOAD" = 1 ]; then
|
|
systemctl --user daemon-reload || die "daemon-reload failed"
|
|
echo "daemon-reload done"
|
|
fi
|
|
cat <<MSG
|
|
next, for one business (one per data root):
|
|
mkdir -m 0700 -p <dataRoot>/notify/<business> the notifier refuses a looser directory
|
|
write <dataRoot>/notify/<business>/notify.json, mode 0600:
|
|
{"notifyVersion": 1, "binding": "<discord binding>"} or "binding": null for no DMs
|
|
systemctl --user enable --now mosaic-bus@<business> start now and at login
|
|
systemctl --user status mosaic-bus@<business>
|
|
journalctl --user -u mosaic-bus@<business> -f the host's log
|
|
systemctl --user stop mosaic-bus@<business> SIGTERM; restartable
|
|
survive logout and reboot only with lingering on: loginctl enable-linger ${USER:-$(id -un)}
|
|
MSG
|
|
}
|
|
|
|
uninstall_unit() {
|
|
parse_flags "$@"
|
|
local target="$UNIT_DIR/$UNIT_NAME"
|
|
if [ "$RELOAD" = 1 ]; then
|
|
local active
|
|
active="$(systemctl --user list-units --no-legend --plain 'mosaic-bus@*' 2>/dev/null | awk '$3 == "active" || $3 == "activating" || $3 == "deactivating" {print $1}')"
|
|
[ -z "$active" ] || die "refusing: instance(s) still running: $(echo "$active" | tr '\n' ' ')stop them first"
|
|
fi
|
|
if [ -f "$target" ]; then
|
|
rm -f "$target"
|
|
echo "removed: $target"
|
|
else
|
|
echo "absent: $target"
|
|
fi
|
|
if [ "$RELOAD" = 1 ]; then
|
|
systemctl --user daemon-reload || die "daemon-reload failed"
|
|
echo "daemon-reload done"
|
|
fi
|
|
}
|
|
|
|
status_unit() {
|
|
[ $# -eq 1 ] || usage
|
|
local business="$1"
|
|
case "$business" in ''|*[!a-z0-9-]*) die "business id must be [a-z0-9-]+" ;; esac
|
|
local unit="mosaic-bus@$business.service"
|
|
echo "unit: $unit"
|
|
echo " enabled: $(systemctl --user is-enabled "$unit" 2>&1 || true)"
|
|
echo " active: $(systemctl --user is-active "$unit" 2>&1 || true)"
|
|
systemctl --user show "$unit" -p MainPID -p NRestarts -p ExecMainStartTimestamp -p Result 2>/dev/null | sed 's/^/ /'
|
|
"$REPO/scripts/mosaic" bus status | sed 's/^/ /' || true
|
|
}
|
|
|
|
[ $# -ge 1 ] || usage
|
|
cmd="$1"; shift
|
|
case "$cmd" in
|
|
render) [ $# -eq 0 ] || usage; render ;;
|
|
install) install_unit "$@" ;;
|
|
uninstall) uninstall_unit "$@" ;;
|
|
status) status_unit "$@" ;;
|
|
-h|--help) echo "$USAGE" ;;
|
|
*) usage ;;
|
|
esac
|