optimized events
This commit is contained in:
@@ -87,6 +87,8 @@ install -d -m 0755 \
|
||||
"$WATERMAPS_DATA_DIR" \
|
||||
"$WATERMAPS_DATA_DIR/geofabrik" \
|
||||
"$WATERMAPS_DATA_DIR/local" \
|
||||
"$WATERMAPS_DATA_DIR/postgres" \
|
||||
"$WATERMAPS_DATA_DIR/tmp" \
|
||||
"$WATERMAPS_DATA_DIR/certbot" \
|
||||
"$WATERMAPS_DATA_DIR/certbot/www" \
|
||||
"$WATERMAPS_DATA_DIR/certbot/letsencrypt" \
|
||||
@@ -95,6 +97,12 @@ install -d -m 0755 \
|
||||
"$WATERMAPS_RUNTIME_DIR/nginx/conf.d" \
|
||||
"$WATERMAPS_RUNTIME_DIR/locks"
|
||||
|
||||
# postgis/postgis uses the Debian postgres UID/GID 999. Keeping PGDATA on the
|
||||
# mounted Hetzner volume makes event data survive image deployments and host
|
||||
# reboots; the official entrypoint can still repair ownership inside PGDATA.
|
||||
chown 999:999 "$WATERMAPS_DATA_DIR/postgres"
|
||||
chmod 0700 "$WATERMAPS_DATA_DIR/postgres"
|
||||
|
||||
if [[ ! -f "$WATERMAPS_RUNTIME_DIR/nginx/conf.d/default.conf" ]]; then
|
||||
install -m 0644 \
|
||||
"$WM_DEPLOY_DIR/nginx/bootstrap.conf" \
|
||||
|
||||
@@ -33,6 +33,16 @@ wm_load_env() {
|
||||
|
||||
wm_require_safe_absolute_dir "$WATERMAPS_DATA_DIR"
|
||||
wm_require_safe_absolute_dir "$WATERMAPS_RUNTIME_DIR"
|
||||
wm_validate_postgres_password
|
||||
}
|
||||
|
||||
wm_validate_postgres_password() {
|
||||
local password="${WATERMAPS_POSTGRES_PASSWORD:-}"
|
||||
|
||||
[[ "${#password}" -ge 24 &&
|
||||
"$password" != *[[:space:]]* &&
|
||||
"$password" != *REPLACE* ]] ||
|
||||
wm_die "WATERMAPS_POSTGRES_PASSWORD muss ein gesetztes Secret mit mindestens 24 Zeichen ohne Leerzeichen sein."
|
||||
}
|
||||
|
||||
wm_require_safe_absolute_dir() {
|
||||
@@ -162,6 +172,10 @@ wm_route_marker() {
|
||||
printf '%s/local/.germany-netherlands-fairways.ready\n' "$WATERMAPS_DATA_DIR"
|
||||
}
|
||||
|
||||
wm_marine_marker() {
|
||||
printf '%s/local/.marine-features.ready\n' "$WATERMAPS_DATA_DIR"
|
||||
}
|
||||
|
||||
wm_acquire_route_lock() {
|
||||
install -d -m 0755 "$WATERMAPS_RUNTIME_DIR/locks"
|
||||
exec 9>"$WATERMAPS_RUNTIME_DIR/locks/route-update.lock"
|
||||
@@ -288,6 +302,107 @@ wm_route_data_files_ready() {
|
||||
return 0
|
||||
}
|
||||
|
||||
wm_geofabrik_checksum() {
|
||||
local region="$1"
|
||||
local checksum_file="$WATERMAPS_DATA_DIR/geofabrik/${region}-latest.osm.pbf.md5"
|
||||
local checksum
|
||||
|
||||
[[ -s "$checksum_file" ]] || return 1
|
||||
checksum="$(awk 'NR == 1 { print tolower($1) }' "$checksum_file")"
|
||||
[[ "$checksum" =~ ^[0-9a-f]{32}$ ]] || return 1
|
||||
printf '%s\n' "$checksum"
|
||||
}
|
||||
|
||||
wm_postgres_query() {
|
||||
local query="$1"
|
||||
|
||||
wm_compose exec --no-TTY postgres \
|
||||
psql \
|
||||
--no-psqlrc \
|
||||
--username seacompass \
|
||||
--dbname seacompass \
|
||||
--tuples-only \
|
||||
--no-align \
|
||||
--field-separator '|' \
|
||||
--set ON_ERROR_STOP=1 \
|
||||
--command "$query"
|
||||
}
|
||||
|
||||
wm_marine_features_ready() {
|
||||
local marker germany_checksum netherlands_checksum database_counts
|
||||
local total_count harbour_count lock_count bridge_count
|
||||
local marker_format marker_source marker_germany marker_netherlands
|
||||
local marker_total marker_harbours marker_locks marker_bridges
|
||||
|
||||
marker="$(wm_marine_marker)"
|
||||
if [[ ! -s "$marker" ]]; then
|
||||
wm_log "Bereitschaftsmarker für Marine-Features fehlt: $marker"
|
||||
return 1
|
||||
fi
|
||||
|
||||
germany_checksum="$(wm_geofabrik_checksum germany 2>/dev/null || true)"
|
||||
netherlands_checksum="$(wm_geofabrik_checksum netherlands 2>/dev/null || true)"
|
||||
if [[ -z "$germany_checksum" || -z "$netherlands_checksum" ]]; then
|
||||
wm_log "Geofabrik-Prüfsummen für den Marine-Feature-Stand fehlen oder sind ungültig."
|
||||
return 1
|
||||
fi
|
||||
|
||||
marker_format="$(wm_marker_value "$marker" format_version 2>/dev/null || true)"
|
||||
marker_source="$(wm_marker_value "$marker" source 2>/dev/null || true)"
|
||||
marker_germany="$(wm_marker_value "$marker" germany_md5 2>/dev/null || true)"
|
||||
marker_netherlands="$(wm_marker_value "$marker" netherlands_md5 2>/dev/null || true)"
|
||||
marker_total="$(wm_marker_value "$marker" total_osm_features 2>/dev/null || true)"
|
||||
marker_harbours="$(wm_marker_value "$marker" harbour_count 2>/dev/null || true)"
|
||||
marker_locks="$(wm_marker_value "$marker" lock_count 2>/dev/null || true)"
|
||||
marker_bridges="$(wm_marker_value "$marker" bridge_count 2>/dev/null || true)"
|
||||
|
||||
if [[ "$marker_format" != "1" ||
|
||||
"$marker_source" != "germany+netherlands" ||
|
||||
"$marker_germany" != "$germany_checksum" ||
|
||||
"$marker_netherlands" != "$netherlands_checksum" ]]; then
|
||||
wm_log "Marine-Feature-Marker passt nicht zu den aktuellen Deutschland-/Niederlande-Snapshots."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! database_counts="$(
|
||||
wm_postgres_query "
|
||||
SELECT
|
||||
count(*)::bigint,
|
||||
count(*) FILTER (WHERE layer = 'harbours')::bigint,
|
||||
count(*) FILTER (WHERE layer = 'locks')::bigint,
|
||||
count(*) FILTER (WHERE layer = 'bridges')::bigint
|
||||
FROM marine_features
|
||||
WHERE source = 'osm';
|
||||
"
|
||||
)"; then
|
||||
wm_log "Marine-Feature-Tabellen sind in PostGIS nicht abfragbar."
|
||||
return 1
|
||||
fi
|
||||
database_counts="${database_counts//[[:space:]]/}"
|
||||
IFS='|' read -r total_count harbour_count lock_count bridge_count <<<"$database_counts"
|
||||
|
||||
for count in "$total_count" "$harbour_count" "$lock_count" "$bridge_count"; do
|
||||
if [[ ! "$count" =~ ^[1-9][0-9]*$ ]]; then
|
||||
wm_log "PostGIS enthält keine vollständigen OSM-Hafen-/Schleusen-/Brückendaten."
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$marker_total" != "$total_count" ||
|
||||
"$marker_harbours" != "$harbour_count" ||
|
||||
"$marker_locks" != "$lock_count" ||
|
||||
"$marker_bridges" != "$bridge_count" ]]; then
|
||||
wm_log "Marine-Feature-Marker stimmt nicht mit den OSM-Zeilen in PostGIS überein."
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
wm_assert_marine_features() {
|
||||
wm_marine_features_ready ||
|
||||
wm_die "Marine-Features sind nicht vollständig in PostGIS bereit."
|
||||
}
|
||||
|
||||
wm_wait_for_health() {
|
||||
local service="$1"
|
||||
local timeout_seconds="${2:-180}"
|
||||
@@ -479,3 +594,44 @@ wm_smoke_test_route() {
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
wm_smoke_test_features() {
|
||||
wm_compose exec --no-TTY watermaps node --input-type=module --eval '
|
||||
const params = new URLSearchParams({
|
||||
bbox: "7.118483884871649,53.302596677614666,7.543960668999219,53.50669706666667",
|
||||
layers: "harbours,locks,bridges"
|
||||
});
|
||||
const response = await fetch(`http://127.0.0.1:5174/api/features?${params}`);
|
||||
if (!response.ok) {
|
||||
console.error("Feature-Smoke-Test", response.status, await response.text());
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const collection = await response.json();
|
||||
const features = Array.isArray(collection.features) ? collection.features : [];
|
||||
const layers = new Set(features.map((feature) => feature?.properties?.layer));
|
||||
const contactFeature = features.find((feature) =>
|
||||
["harbours", "locks"].includes(feature?.properties?.layer)
|
||||
&& typeof feature?.properties?.phone === "string"
|
||||
&& feature.properties.phone.trim().length > 0
|
||||
);
|
||||
if (
|
||||
collection?.metadata?.source !== "postgis"
|
||||
|| !layers.has("harbours")
|
||||
|| !layers.has("locks")
|
||||
|| !layers.has("bridges")
|
||||
|| !contactFeature
|
||||
) {
|
||||
console.error(
|
||||
"PostGIS-Feature-Prüfung für die Emden–Aurich-Teststrecke fehlgeschlagen.",
|
||||
JSON.stringify({
|
||||
source: collection?.metadata?.source,
|
||||
featureCount: features.length,
|
||||
layers: [...layers],
|
||||
hasCallableHarbourOrLock: Boolean(contactFeature)
|
||||
})
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
+28
-12
@@ -69,12 +69,16 @@ wm_finish_deployment() {
|
||||
if [[ -n "$rollback_images_file" && -f "$rollback_images_file" ]]; then
|
||||
wm_log "Deployment fehlgeschlagen; vorheriges Container-Release wird wiederhergestellt."
|
||||
wm_use_images_env "$rollback_images_file"
|
||||
wm_compose up --detach --no-build --remove-orphans watermaps nginx
|
||||
wm_compose up --detach --no-build --remove-orphans postgres watermaps nginx
|
||||
wm_wait_for_health postgres 240
|
||||
wm_wait_for_health watermaps 240
|
||||
wm_wait_for_health nginx 120
|
||||
if wm_route_data_ready; then
|
||||
wm_smoke_test_route
|
||||
fi
|
||||
if wm_marine_features_ready; then
|
||||
wm_smoke_test_features
|
||||
fi
|
||||
else
|
||||
wm_log "Deployment fehlgeschlagen; für das erste Release existiert noch kein Rollback."
|
||||
fi
|
||||
@@ -99,7 +103,7 @@ requested_app_image="$(wm_env_value "$images_env_file" WATERMAPS_APP_IMAGE)"
|
||||
requested_route_data_image="$(wm_env_value "$images_env_file" WATERMAPS_ROUTE_DATA_IMAGE)"
|
||||
|
||||
wm_log "Container-Images für Commit $revision werden aus den Registries geladen."
|
||||
wm_compose --profile maintenance pull watermaps nginx certbot route-data
|
||||
wm_compose --profile maintenance pull watermaps postgres nginx certbot route-data
|
||||
|
||||
resolved_app_image="$(wm_resolve_image_digest "$requested_app_image")"
|
||||
resolved_route_data_image="$(wm_resolve_image_digest "$requested_route_data_image")"
|
||||
@@ -114,30 +118,42 @@ resolved_images_file="$(
|
||||
chmod 0644 "$resolved_images_file"
|
||||
wm_use_images_env "$resolved_images_file"
|
||||
|
||||
wm_log "Commit $revision wird mit unveränderlichen Image-Digests gestartet."
|
||||
wm_compose up --detach --no-build --remove-orphans watermaps nginx
|
||||
wm_log "Persistentes PostGIS wird vor App und Datenimport gestartet."
|
||||
wm_compose up --detach --no-build postgres
|
||||
wm_wait_for_health postgres 240
|
||||
|
||||
wm_wait_for_health watermaps 240
|
||||
wm_wait_for_health nginx 120
|
||||
|
||||
route_rebuild_required=false
|
||||
data_update_required=false
|
||||
update_args=()
|
||||
if [[ "${WATERMAPS_REBUILD_ROUTE_DATA:-false}" == "true" ]]; then
|
||||
route_rebuild_required=true
|
||||
data_update_required=true
|
||||
update_args+=(--force)
|
||||
elif ! wm_route_data_ready; then
|
||||
route_rebuild_required=true
|
||||
data_update_required=true
|
||||
fi
|
||||
if [[ "${WATERMAPS_REBUILD_MARINE_DATA:-false}" == "true" ]]; then
|
||||
data_update_required=true
|
||||
update_args+=(--force-marine)
|
||||
elif ! wm_marine_features_ready; then
|
||||
data_update_required=true
|
||||
fi
|
||||
|
||||
if [[ "$route_rebuild_required" == "true" ]]; then
|
||||
wm_log "Deutschland- und Niederlande-Routingdaten werden sicher vorbereitet."
|
||||
if [[ "$data_update_required" == "true" ]]; then
|
||||
wm_log "Deutschland-/Niederlande-Routingdaten und Marine-Features werden sicher vorbereitet."
|
||||
WATERMAPS_ROUTE_LOCK_HELD=true \
|
||||
"$WM_DEPLOY_DIR/scripts/update-route-data.sh" "${update_args[@]}"
|
||||
fi
|
||||
|
||||
wm_assert_route_data
|
||||
wm_assert_marine_features
|
||||
|
||||
wm_log "Commit $revision wird erst mit validierten Routing- und Ereignisdaten gestartet."
|
||||
wm_compose up --detach --no-build --remove-orphans postgres watermaps nginx
|
||||
|
||||
wm_wait_for_health postgres 240
|
||||
wm_wait_for_health watermaps 240
|
||||
wm_wait_for_health nginx 120
|
||||
wm_smoke_test_route
|
||||
wm_smoke_test_features
|
||||
|
||||
release_images_file="$WATERMAPS_RUNTIME_DIR/deployments/$revision.env"
|
||||
install -m 0644 "$resolved_images_file" "$release_images_file"
|
||||
|
||||
Executable
+158
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
cd /workspace
|
||||
|
||||
database_url="${DATABASE_URL:-}"
|
||||
geofabrik_dir="${WATERMAPS_GEOFABRIK_DIR:-/workspace/data/geofabrik}"
|
||||
marker_file="${WATERMAPS_MARINE_MARKER_PATH:-/workspace/data/local/.marine-features.ready}"
|
||||
temporary_root="${TMPDIR:-/tmp}"
|
||||
pbf_paths=(
|
||||
"$geofabrik_dir/germany-latest.osm.pbf"
|
||||
"$geofabrik_dir/netherlands-latest.osm.pbf"
|
||||
)
|
||||
|
||||
if [[ -z "$database_url" ]]; then
|
||||
printf 'Fehler: DATABASE_URL ist für den Marine-Feature-Import erforderlich.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -x /workspace/scripts/import-geofabrik.sh ]]; then
|
||||
printf 'Fehler: scripts/import-geofabrik.sh fehlt oder ist nicht ausführbar.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$marker_file")" "$temporary_root"
|
||||
export TMPDIR="$temporary_root"
|
||||
|
||||
declare -A source_checksums
|
||||
for pbf_path in "${pbf_paths[@]}"; do
|
||||
if [[ ! -s "$pbf_path" ]]; then
|
||||
printf 'Fehler: Geofabrik-Snapshot fehlt oder ist leer: %s\n' "$pbf_path" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
checksum_file="${pbf_path}.md5"
|
||||
if [[ ! -s "$checksum_file" ]]; then
|
||||
printf 'Fehler: Geofabrik-Prüfsumme fehlt: %s\n' "$checksum_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
expected_checksum="$(awk 'NR == 1 { print tolower($1) }' "$checksum_file")"
|
||||
if [[ ! "$expected_checksum" =~ ^[0-9a-f]{32}$ ]]; then
|
||||
printf 'Fehler: Ungültige Geofabrik-Prüfsumme in %s\n' "$checksum_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
actual_checksum="$(md5sum "$pbf_path" | awk '{ print $1 }')"
|
||||
if [[ "$actual_checksum" != "$expected_checksum" ]]; then
|
||||
printf 'Fehler: Geofabrik-Snapshot stimmt nicht mit seiner Prüfsumme überein: %s\n' "$pbf_path" >&2
|
||||
exit 1
|
||||
fi
|
||||
source_checksums["$(basename "$pbf_path" -latest.osm.pbf)"]="$actual_checksum"
|
||||
done
|
||||
|
||||
# Every imported OSM row receives updated_at=now(). The shared database
|
||||
# timestamp lets us remove disappeared OSM objects only after both regional
|
||||
# imports completed and passed the sanity checks. Other sources such as EuRIS
|
||||
# and facility-website enrichments are deliberately preserved.
|
||||
import_started_epoch="$(
|
||||
psql "$database_url" \
|
||||
--no-psqlrc \
|
||||
--tuples-only \
|
||||
--no-align \
|
||||
--set ON_ERROR_STOP=1 \
|
||||
--command "SELECT extract(epoch FROM clock_timestamp());"
|
||||
)"
|
||||
import_started_epoch="${import_started_epoch//[[:space:]]/}"
|
||||
if [[ ! "$import_started_epoch" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
|
||||
printf 'Fehler: Datenbank lieferte keinen gültigen Importzeitpunkt.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for pbf_path in "${pbf_paths[@]}"; do
|
||||
printf 'Importiere Marine-Features aus %s\n' "$(basename "$pbf_path")"
|
||||
DATABASE_URL="$database_url" /workspace/scripts/import-geofabrik.sh "$pbf_path"
|
||||
done
|
||||
|
||||
fresh_counts="$(
|
||||
psql "$database_url" \
|
||||
--no-psqlrc \
|
||||
--tuples-only \
|
||||
--no-align \
|
||||
--field-separator '|' \
|
||||
--set ON_ERROR_STOP=1 \
|
||||
--command "
|
||||
SELECT
|
||||
count(*)::bigint,
|
||||
count(*) FILTER (WHERE layer = 'harbours')::bigint,
|
||||
count(*) FILTER (WHERE layer = 'locks')::bigint,
|
||||
count(*) FILTER (WHERE layer = 'bridges')::bigint
|
||||
FROM marine_features
|
||||
WHERE source = 'osm'
|
||||
AND updated_at >= to_timestamp($import_started_epoch);
|
||||
"
|
||||
)"
|
||||
fresh_counts="${fresh_counts//[[:space:]]/}"
|
||||
IFS='|' read -r fresh_total fresh_harbours fresh_locks fresh_bridges <<<"$fresh_counts"
|
||||
for count in "$fresh_total" "$fresh_harbours" "$fresh_locks" "$fresh_bridges"; do
|
||||
if [[ ! "$count" =~ ^[1-9][0-9]*$ ]]; then
|
||||
printf 'Fehler: Der neue OSM-Import enthält keine vollständigen Hafen-/Schleusen-/Brückendaten.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
psql "$database_url" \
|
||||
--no-psqlrc \
|
||||
--set ON_ERROR_STOP=1 \
|
||||
--command "
|
||||
BEGIN;
|
||||
DELETE FROM marine_features
|
||||
WHERE source = 'osm'
|
||||
AND updated_at < to_timestamp($import_started_epoch);
|
||||
DELETE FROM marine_fairway_edges
|
||||
WHERE source = 'osm'
|
||||
AND updated_at < to_timestamp($import_started_epoch);
|
||||
COMMIT;
|
||||
ANALYZE marine_features;
|
||||
ANALYZE marine_fairway_edges;
|
||||
"
|
||||
|
||||
final_counts="$(
|
||||
psql "$database_url" \
|
||||
--no-psqlrc \
|
||||
--tuples-only \
|
||||
--no-align \
|
||||
--field-separator '|' \
|
||||
--set ON_ERROR_STOP=1 \
|
||||
--command "
|
||||
SELECT
|
||||
count(*)::bigint,
|
||||
count(*) FILTER (WHERE layer = 'harbours')::bigint,
|
||||
count(*) FILTER (WHERE layer = 'locks')::bigint,
|
||||
count(*) FILTER (WHERE layer = 'bridges')::bigint
|
||||
FROM marine_features
|
||||
WHERE source = 'osm';
|
||||
"
|
||||
)"
|
||||
final_counts="${final_counts//[[:space:]]/}"
|
||||
IFS='|' read -r total_osm_features harbour_count lock_count bridge_count <<<"$final_counts"
|
||||
|
||||
temporary_marker="$(mktemp "$(dirname "$marker_file")/.marine-features-ready.XXXXXX")"
|
||||
{
|
||||
printf 'format_version=1\n'
|
||||
printf 'generated_at=%s\n' "$(date --utc +%Y-%m-%dT%H:%M:%SZ)"
|
||||
printf 'source=germany+netherlands\n'
|
||||
printf 'germany_md5=%s\n' "${source_checksums[germany]}"
|
||||
printf 'netherlands_md5=%s\n' "${source_checksums[netherlands]}"
|
||||
printf 'total_osm_features=%s\n' "$total_osm_features"
|
||||
printf 'harbour_count=%s\n' "$harbour_count"
|
||||
printf 'lock_count=%s\n' "$lock_count"
|
||||
printf 'bridge_count=%s\n' "$bridge_count"
|
||||
} >"$temporary_marker"
|
||||
chmod 0644 "$temporary_marker"
|
||||
mv -f "$temporary_marker" "$marker_file"
|
||||
|
||||
printf 'Marine-Features sind bereit: %s OSM-Objekte (%s Häfen, %s Schleusen, %s Brücken)\n' \
|
||||
"$total_osm_features" "$harbour_count" "$lock_count" "$bridge_count"
|
||||
@@ -71,4 +71,56 @@ if wm_route_data_ready; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf 'Routingdaten- und Markerprüfungen: OK\n'
|
||||
mkdir -p "$WATERMAPS_DATA_DIR/geofabrik"
|
||||
printf '%s germany-latest.osm.pbf\n' \
|
||||
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' \
|
||||
>"$WATERMAPS_DATA_DIR/geofabrik/germany-latest.osm.pbf.md5"
|
||||
printf '%s netherlands-latest.osm.pbf\n' \
|
||||
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' \
|
||||
>"$WATERMAPS_DATA_DIR/geofabrik/netherlands-latest.osm.pbf.md5"
|
||||
|
||||
cat >"$(wm_marine_marker)" <<'MARKER'
|
||||
format_version=1
|
||||
generated_at=2026-07-28T00:00:00Z
|
||||
source=germany+netherlands
|
||||
germany_md5=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
netherlands_md5=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
total_osm_features=100
|
||||
harbour_count=10
|
||||
lock_count=5
|
||||
bridge_count=20
|
||||
MARKER
|
||||
|
||||
wm_postgres_query() {
|
||||
printf '100|10|5|20\n'
|
||||
}
|
||||
wm_marine_features_ready
|
||||
|
||||
wm_postgres_query() {
|
||||
printf '100|10|0|20\n'
|
||||
}
|
||||
if wm_marine_features_ready; then
|
||||
printf 'Marine-Feature-Marker wurde trotz fehlender Schleusen akzeptiert.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wm_postgres_query() {
|
||||
printf '99|10|5|20\n'
|
||||
}
|
||||
if wm_marine_features_ready; then
|
||||
printf 'Marine-Feature-Marker wurde trotz abweichendem Datenbankbestand akzeptiert.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if grep -Eq 'DATABASE_URL:[[:space:]]*""' \
|
||||
"$ROOT_DIR/docker-compose.yml" \
|
||||
"$ROOT_DIR/deploy/compose.production.yml"; then
|
||||
printf 'Compose trennt die App weiterhin explizit von PostGIS.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -Fq 'condition: service_healthy' "$ROOT_DIR/deploy/compose.production.yml"
|
||||
grep -Fq '/ready' "$ROOT_DIR/deploy/compose.production.yml"
|
||||
grep -Fq 'source: ${WATERMAPS_DATA_DIR:-/srv/watermaps-data}/postgres' \
|
||||
"$ROOT_DIR/deploy/compose.production.yml"
|
||||
|
||||
printf 'Routingdaten-, Marine-Feature- und Compose-Prüfungen: OK\n'
|
||||
|
||||
@@ -16,6 +16,7 @@ mkdir -p "$FAKE_BIN" "$DATA_DIR/local" "$RUNTIME_DIR"
|
||||
cat >"$ENV_FILE" <<EOF
|
||||
WATERMAPS_DATA_DIR=$DATA_DIR
|
||||
WATERMAPS_RUNTIME_DIR=$RUNTIME_DIR
|
||||
WATERMAPS_POSTGRES_PASSWORD=0123456789abcdef0123456789abcdef
|
||||
EOF
|
||||
|
||||
cat >"$IMAGES_ENV_FILE" <<'EOF'
|
||||
@@ -48,6 +49,11 @@ if [[ "${1:-}" == "inspect" ]]; then
|
||||
fi
|
||||
|
||||
arguments=" $* "
|
||||
if [[ "$arguments" == *" ps --quiet postgres "* ]]; then
|
||||
printf 'postgres-test-container\n'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$arguments" == *" ps --quiet watermaps "* ]]; then
|
||||
printf 'watermaps-test-container\n'
|
||||
exit 0
|
||||
@@ -55,6 +61,13 @@ fi
|
||||
|
||||
if [[ "$arguments" == *" run "*" route-data "* ||
|
||||
"$arguments" == *" run "*" route-data" ]]; then
|
||||
mkdir -p "$WATERMAPS_DATA_DIR/geofabrik"
|
||||
printf '%s germany-latest.osm.pbf\n' \
|
||||
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' \
|
||||
>"$WATERMAPS_DATA_DIR/geofabrik/germany-latest.osm.pbf.md5"
|
||||
printf '%s netherlands-latest.osm.pbf\n' \
|
||||
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' \
|
||||
>"$WATERMAPS_DATA_DIR/geofabrik/netherlands-latest.osm.pbf.md5"
|
||||
route_file="$WATERMAPS_DATA_DIR/local/.germany-netherlands-fairways.candidate.json"
|
||||
marker_file="$WATERMAPS_DATA_DIR/local/.germany-netherlands-fairways.candidate.ready"
|
||||
cat >"$route_file" <<JSON
|
||||
@@ -86,6 +99,27 @@ JSON
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$arguments" == *" run "*" marine-data "* ||
|
||||
"$arguments" == *" run "*" marine-data" ]]; then
|
||||
cat >"$WATERMAPS_DATA_DIR/local/.marine-features.ready" <<'MARKER'
|
||||
format_version=1
|
||||
generated_at=2026-07-28T00:00:00Z
|
||||
source=germany+netherlands
|
||||
germany_md5=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
netherlands_md5=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
total_osm_features=100
|
||||
harbour_count=10
|
||||
lock_count=5
|
||||
bridge_count=20
|
||||
MARKER
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$arguments" == *" exec --no-TTY postgres "* ]]; then
|
||||
printf '100|10|5|20\n'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$arguments" == *" exec --no-TTY watermaps "* ]]; then
|
||||
active_file="$WATERMAPS_DATA_DIR/local/germany-netherlands-fairways.json"
|
||||
active_revision="$(jq --raw-output '.revision // 0' "$active_file" 2>/dev/null || true)"
|
||||
|
||||
@@ -13,11 +13,22 @@ if [[ "$(id -u)" -ne 0 ]]; then
|
||||
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."
|
||||
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
|
||||
@@ -26,6 +37,9 @@ if [[ "${WATERMAPS_ROUTE_LOCK_HELD:-false}" != "true" ]]; then
|
||||
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")"
|
||||
@@ -58,6 +72,16 @@ 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" ]] &&
|
||||
@@ -78,8 +102,8 @@ wm_restore_previous_route() {
|
||||
|
||||
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
|
||||
wm_log "Watermaps läuft noch nicht; wiederhergestellte Routingdaten werden beim App-Start getestet."
|
||||
return 0
|
||||
fi
|
||||
|
||||
wm_compose restart watermaps
|
||||
@@ -156,8 +180,10 @@ 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 und Routingindex sind unverändert."
|
||||
wm_log "Geofabrik-Snapshots, Routingindex und Marine-Features sind aktuell."
|
||||
rm -f "$candidate_file" "$candidate_marker"
|
||||
exit 0
|
||||
fi
|
||||
@@ -186,8 +212,18 @@ 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
|
||||
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"
|
||||
|
||||
@@ -124,9 +124,9 @@ printf '[watermaps] Warte auf Cloud-init und das persistente Hetzner-Volume.\n'
|
||||
ssh "${WM_SSH_OPTIONS[@]}" "$WM_SSH_TARGET" \
|
||||
"cloud-init status --wait && ${remote_prefix}systemctl start watermaps-volume-setup.service && mountpoint --quiet /srv/watermaps-data"
|
||||
|
||||
printf '[watermaps] Übertrage Deployment-Dateien nach %s:/opt/watermaps/deploy\n' "$WM_SSH_TARGET"
|
||||
printf '[watermaps] Übertrage Deployment-Dateien und Datenbankschema nach %s:/opt/watermaps\n' "$WM_SSH_TARGET"
|
||||
ssh "${WM_SSH_OPTIONS[@]}" "$WM_SSH_TARGET" \
|
||||
"${remote_prefix}install -d -m 0755 /opt/watermaps /opt/watermaps/deploy"
|
||||
"${remote_prefix}install -d -m 0755 /opt/watermaps /opt/watermaps/deploy /opt/watermaps/database"
|
||||
|
||||
rsync \
|
||||
--archive \
|
||||
@@ -140,6 +140,14 @@ rsync \
|
||||
"$WM_DEPLOY_DIR/" \
|
||||
"$WM_SSH_TARGET:/opt/watermaps/deploy/"
|
||||
|
||||
rsync \
|
||||
--archive \
|
||||
--chmod=F644 \
|
||||
--rsync-path="$rsync_path" \
|
||||
-e "ssh ${WM_SSH_OPTIONS[*]@Q}" \
|
||||
"$WM_LOCAL_ROOT_DIR/database/schema.sql" \
|
||||
"$WM_SSH_TARGET:/opt/watermaps/database/schema.sql"
|
||||
|
||||
rsync \
|
||||
--archive \
|
||||
--chmod=F600 \
|
||||
|
||||
Reference in New Issue
Block a user