#!/bin/sh # Usage: start.sh valkey|sentinel. valkey boots read-only as a replica of # 127.0.0.1:1 ("undecided") so peers can compare offsets; decide() then follows # the sentinels' master, a live peer master, or the highest-offset node. set -eu name="$(hostname)" sts="${name%-*}" self="${name}${DOMAIN_SUFFIX}" info() { timeout 3 valkey-cli -h "$1" info replication 2>/dev/null | tr -d '\r' || true } field() { printf '%s\n' "$1" | sed -n "s/^$2://p" } undecided() { [ "$(field "$1" master_host)" = 127.0.0.1 ] } choose_master() { deadline=$(($(date +%s) + 60)) while :; do best="" best_off=-1 answered=0 for i in 0 1 2; do peer="${sts}-${i}${DOMAIN_SUFFIX}" if [ "$peer" = "$self" ]; then r="$(info 127.0.0.1)" else m="$(timeout 3 valkey-cli -h "$peer" -p 26379 --raw sentinel get-master-addr-by-name rspamd 2>/dev/null | head -n1 || true)" [ -n "$m" ] && { echo "$m"; return; } r="$(info "$peer")" [ -n "$r" ] || continue answered=$((answered + 1)) [ "$(field "$r" role)" = master ] && { echo "$peer"; return; } fi undecided "$r" || continue off="$(field "$r" master_repl_offset)" [ "${off:-0}" -gt "$best_off" ] && best="$peer" best_off="${off:-0}" done if [ "$best" = "$self" ] && { [ "$answered" -eq 2 ] || [ "$(date +%s)" -ge "$deadline" ]; }; then echo "$self" return fi sleep 3 done } decide() { until valkey-cli ping >/dev/null 2>&1; do sleep 1; done master="$(choose_master)" target="$master 6379" [ "$master" = "$self" ] && target="no one" until valkey-cli replicaof $target; do sleep 1; done } if [ "$1" = sentinel ]; then until r="$(info 127.0.0.1)" && [ -n "$(field "$r" role)" ] && ! undecided "$r"; do sleep 2; done master="$self" [ "$(field "$r" role)" = master ] || master="$(field "$r" master_host)" cat > /sentinel/sentinel.conf <