#!/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 if [[ "${1:-}" == "--force" ]]; then force_rebuild=true shift fi [[ "$#" -eq 0 ]] || wm_die "Unbekannte Argumente für update-route-data.sh." 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 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_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 nicht; wiederhergestellte Routingdaten können noch nicht getestet werden." return 1 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 --build \ --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 if [[ "$previous_ready" == "true" ]] && cmp --silent "$candidate_file" "$route_file"; then wm_log "Geofabrik-Snapshots und Routingindex sind unverändert." 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." wm_compose restart watermaps if wm_wait_for_health watermaps 240 && wm_smoke_test_route; 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."