Files
watermaps/deploy/scripts/update-route-data.sh
T
BuTzZ 593dbd5f85
Test and publish container images / test (push) Successful in 2m26s
Test and publish container images / publish (push) Failing after 3s
optimized events
2026-07-28 14:36:47 +02:00

244 lines
7.3 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
WM_DEPLOY_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# shellcheck source=common.sh
source "$WM_DEPLOY_DIR/scripts/common.sh"
wm_load_env
wm_assert_data_mount
if [[ "$(id -u)" -ne 0 ]]; then
wm_die "Dieses Skript muss als root ausgeführt werden."
fi
force_rebuild=false
force_marine_import=false
while [[ "$#" -gt 0 ]]; do
case "$1" in
--force)
force_rebuild=true
shift
;;
--force-marine)
force_marine_import=true
shift
;;
*)
wm_die "Unbekanntes Argument für update-route-data.sh: $1"
;;
esac
done
install -d -m 0755 "$WATERMAPS_RUNTIME_DIR/locks" "$WATERMAPS_DATA_DIR/local"
if [[ "${WATERMAPS_ROUTE_LOCK_HELD:-false}" != "true" ]]; then
if ! wm_acquire_route_lock; then
exit 0
fi
fi
wm_compose up --detach --no-build postgres
wm_wait_for_health postgres 240
route_file="$(wm_route_file)"
route_marker="$(wm_route_marker)"
route_dir="$(dirname "$route_file")"
candidate_file="$route_dir/.germany-netherlands-fairways.candidate.json"
candidate_marker="$route_dir/.germany-netherlands-fairways.candidate.ready"
backup_file="$route_dir/.germany-netherlands-fairways.previous.json"
backup_marker="$route_dir/.germany-netherlands-fairways.previous.ready"
transaction_file="$WATERMAPS_RUNTIME_DIR/locks/route-update.transaction"
container_candidate="/workspace/data/local/$(basename "$candidate_file")"
container_candidate_marker="/workspace/data/local/$(basename "$candidate_marker")"
transaction_active=false
rollback_restored_previous=false
wm_copy_route_atomically() {
local source_file="$1"
local destination_file="$2"
local temporary_file
temporary_file="$(mktemp "$(dirname "$destination_file")/.route-copy.XXXXXX")"
if ! cp --reflink=auto "$source_file" "$temporary_file"; then
rm -f "$temporary_file"
return 1
fi
chmod 0644 "$temporary_file"
mv -f "$temporary_file" "$destination_file"
}
wm_watermaps_is_running() {
[[ -n "$(wm_compose ps --quiet watermaps)" ]]
}
wm_update_marine_features() {
if [[ "$force_marine_import" == "true" ]] || ! wm_marine_features_ready; then
wm_log "Häfen, Schleusen und Brücken werden aus den verifizierten Geofabrik-Snapshots importiert."
wm_compose --profile maintenance run --rm marine-data
else
wm_log "Marine-Features in PostGIS sind bereits aktuell."
fi
wm_assert_marine_features
}
wm_restore_previous_route() {
rollback_restored_previous=false
if [[ -s "$backup_file" && -s "$backup_marker" ]] &&
wm_route_data_files_ready "$backup_file" "$backup_marker"; then
if ! wm_copy_route_atomically "$backup_file" "$route_file" ||
! wm_write_route_marker "$route_file" "$route_marker" ||
! wm_route_data_ready; then
rm -f "$route_file" "$route_marker"
return 1
fi
rollback_restored_previous=true
return 0
fi
rm -f "$route_file" "$route_marker"
return 1
}
wm_restart_after_restore() {
if ! wm_watermaps_is_running; then
wm_log "Watermaps läuft noch nicht; wiederhergestellte Routingdaten werden beim App-Start getestet."
return 0
fi
wm_compose restart watermaps
wm_wait_for_health watermaps 240 || return 1
if [[ "$rollback_restored_previous" == "true" ]]; then
wm_smoke_test_route
fi
}
wm_rollback_transaction() {
local restore_status=0
if ! wm_restore_previous_route; then
restore_status=1
fi
rm -f "$transaction_file"
transaction_active=false
if ! wm_restart_after_restore; then
return 1
fi
return "$restore_status"
}
wm_cleanup_on_exit() {
local status=$?
trap - EXIT HUP INT TERM
set +e
if [[ "$transaction_active" == "true" ]]; then
wm_log "Unvollständige Routingaktivierung wird zurückgerollt."
wm_rollback_transaction
fi
rm -f "$candidate_file" "$candidate_marker"
exit "$status"
}
trap wm_cleanup_on_exit EXIT
trap 'exit 130' HUP INT TERM
# A hard interruption cannot run shell traps. The durable transaction marker
# makes the next invocation restore the last validated index before proceeding.
if [[ -e "$transaction_file" ]]; then
wm_log "Unterbrochene Routingaktualisierung erkannt; letzter gültiger Stand wird wiederhergestellt."
if wm_restore_previous_route; then
wm_restart_after_restore ||
wm_die "Der wiederhergestellte Routingindex bestand den Routentest nicht."
else
wm_restart_after_restore ||
wm_log "Es existierte noch kein vorheriger Routingindex; aktiver Marker wurde entfernt."
fi
rm -f "$transaction_file"
fi
rm -f "$candidate_file" "$candidate_marker"
previous_ready=false
if wm_route_data_ready; then
previous_ready=true
if [[ "$force_rebuild" != "true" ]]; then
cp --reflink=auto "$route_file" "$candidate_file"
chmod 0644 "$candidate_file"
fi
fi
wm_log "Deutschland-/Niederlande-Routingdaten werden in einer Stagingdatei gebaut."
if ! wm_compose --profile maintenance run --rm \
--env "WATERMAPS_LOCAL_FAIRWAYS_PATH=$container_candidate" \
--env "WATERMAPS_ROUTE_MARKER_PATH=$container_candidate_marker" \
route-data; then
wm_die "Der Datenaufbau ist fehlgeschlagen; der aktive Index wurde nicht verändert."
fi
if ! wm_route_data_files_ready "$candidate_file" "$candidate_marker"; then
wm_die "Der neu gebaute Routingindex oder sein Bereitschaftsmarker ist ungültig."
fi
wm_update_marine_features
if [[ "$previous_ready" == "true" ]] && cmp --silent "$candidate_file" "$route_file"; then
wm_log "Geofabrik-Snapshots, Routingindex und Marine-Features sind aktuell."
rm -f "$candidate_file" "$candidate_marker"
exit 0
fi
if [[ "$previous_ready" == "true" ]]; then
wm_copy_route_atomically "$route_file" "$backup_file"
wm_write_route_marker "$backup_file" "$backup_marker"
wm_route_data_files_ready "$backup_file" "$backup_marker" ||
wm_die "Der bisherige Routingindex konnte nicht sicher gesichert werden."
else
rm -f "$backup_file" "$backup_marker"
fi
temporary_transaction="$(mktemp "$WATERMAPS_RUNTIME_DIR/locks/.route-update-transaction.XXXXXX")"
{
printf 'started_at=%s\n' "$(date --utc +%Y-%m-%dT%H:%M:%SZ)"
printf 'had_previous=%s\n' "$previous_ready"
} >"$temporary_transaction"
chmod 0644 "$temporary_transaction"
mv -f "$temporary_transaction" "$transaction_file"
transaction_active=true
mv -f "$candidate_file" "$route_file"
rm -f "$candidate_marker"
wm_write_route_marker "$route_file" "$route_marker"
wm_route_data_ready ||
wm_die "Der aktivierte Routingindex besitzt keinen gültigen Bereitschaftsmarker."
activation_valid=false
if wm_watermaps_is_running; then
wm_compose restart watermaps
if wm_wait_for_health watermaps 240 && wm_smoke_test_route; then
activation_valid=true
fi
else
wm_log "Watermaps läuft noch nicht; Routing- und Feature-API werden beim App-Start getestet."
activation_valid=true
fi
if [[ "$activation_valid" == "true" ]]; then
rm -f "$transaction_file"
transaction_active=false
rm -f "$backup_file" "$backup_marker"
wm_log "Routingdaten-Update wurde erfolgreich aktiviert."
exit 0
fi
wm_log "Der neue Routingindex bestand die Routentests nicht; Rollback wird ausgeführt."
if wm_rollback_transaction; then
rm -f "$backup_file" "$backup_marker"
wm_die "Neuer Routingindex verworfen; der vorherige, erneut getestete Index ist aktiv."
fi
if [[ "$rollback_restored_previous" == "true" ]]; then
wm_die "Rollback-Dateien wurden wiederhergestellt, bestanden aber den Routentest nicht."
fi
wm_die "Neuer Routingindex verworfen; es existierte noch kein vorheriger gültiger Index."