fix: close qdrant archive restore race
This commit is contained in:
+67
-21
@@ -29,9 +29,29 @@ done
|
||||
}
|
||||
[ -r "$input" ] || { echo "backup input is not readable" >&2; exit 2; }
|
||||
|
||||
input_dir=$(dirname "$input")
|
||||
input_name=$(basename "$input")
|
||||
expected_volume_name="${project_name}_${volume_role}"
|
||||
private_archive_dir=
|
||||
private_archive_path=
|
||||
cleanup() {
|
||||
status=$?
|
||||
if [ -n "${private_archive_dir:-}" ] && [ -d "${private_archive_dir:-}" ]; then
|
||||
rm -rf "$private_archive_dir"
|
||||
fi
|
||||
if [ "${restart_qdrant:-0}" -eq 1 ]; then
|
||||
docker compose --project-name "$project_name" start qdrant >/dev/null
|
||||
fi
|
||||
exit "$status"
|
||||
}
|
||||
trap cleanup EXIT HUP INT TERM
|
||||
|
||||
private_archive_dir=$(mktemp -d "${TMPDIR:-/tmp}/qdrant-archive.XXXXXX")
|
||||
private_archive_path="$private_archive_dir/archive.tar"
|
||||
umask 077
|
||||
cp "$input" "$private_archive_path"
|
||||
chmod 0600 "$private_archive_path"
|
||||
|
||||
input_dir=$private_archive_dir
|
||||
input_name=$(basename "$private_archive_path")
|
||||
|
||||
resolve_volume() {
|
||||
names=$(docker volume ls \
|
||||
@@ -60,7 +80,7 @@ validate_volume_metadata() {
|
||||
}
|
||||
|
||||
validate_archive_paths() {
|
||||
paths=$(tar -tf "$input") || {
|
||||
paths=$(tar -tf "$private_archive_path") || {
|
||||
echo "archive listing failed" >&2
|
||||
exit 2
|
||||
}
|
||||
@@ -102,7 +122,7 @@ EOF
|
||||
}
|
||||
|
||||
validate_archive_types() {
|
||||
tar -tvf "$input" | while IFS= read -r entry; do
|
||||
tar -tvf "$private_archive_path" | while IFS= read -r entry; do
|
||||
[ -n "$entry" ] || continue
|
||||
type=$(printf '%.1s' "$entry")
|
||||
case "$type" in
|
||||
@@ -124,7 +144,7 @@ validate_archive_types() {
|
||||
}
|
||||
|
||||
validate_archive_manifest() {
|
||||
manifest=$(tar -xOf "$input" manifest.env 2>/dev/null) || {
|
||||
manifest=$(tar -xOf "$private_archive_path" manifest.env 2>/dev/null) || {
|
||||
echo "archive manifest could not be read" >&2
|
||||
exit 2
|
||||
}
|
||||
@@ -134,25 +154,59 @@ validate_archive_manifest() {
|
||||
manifest_role=
|
||||
manifest_helper=
|
||||
created_utc=
|
||||
seen=
|
||||
format_count=0
|
||||
project_count=0
|
||||
volume_count=0
|
||||
role_count=0
|
||||
helper_count=0
|
||||
created_count=0
|
||||
while IFS='=' read -r key value; do
|
||||
[ -n "$key" ] || continue
|
||||
case "$key" in
|
||||
format) format=$value ;;
|
||||
project_name) manifest_project=$value ;;
|
||||
volume_name) manifest_volume=$value ;;
|
||||
volume_role) manifest_role=$value ;;
|
||||
helper_image) manifest_helper=$value ;;
|
||||
created_utc) created_utc=$value ;;
|
||||
format)
|
||||
format_count=$((format_count + 1))
|
||||
[ "$format_count" -eq 1 ] || { echo "archive manifest contains duplicate keys" >&2; exit 2; }
|
||||
format=$value
|
||||
;;
|
||||
project_name)
|
||||
project_count=$((project_count + 1))
|
||||
[ "$project_count" -eq 1 ] || { echo "archive manifest contains duplicate keys" >&2; exit 2; }
|
||||
manifest_project=$value
|
||||
;;
|
||||
volume_name)
|
||||
volume_count=$((volume_count + 1))
|
||||
[ "$volume_count" -eq 1 ] || { echo "archive manifest contains duplicate keys" >&2; exit 2; }
|
||||
manifest_volume=$value
|
||||
;;
|
||||
volume_role)
|
||||
role_count=$((role_count + 1))
|
||||
[ "$role_count" -eq 1 ] || { echo "archive manifest contains duplicate keys" >&2; exit 2; }
|
||||
manifest_role=$value
|
||||
;;
|
||||
helper_image)
|
||||
helper_count=$((helper_count + 1))
|
||||
[ "$helper_count" -eq 1 ] || { echo "archive manifest contains duplicate keys" >&2; exit 2; }
|
||||
manifest_helper=$value
|
||||
;;
|
||||
created_utc)
|
||||
created_count=$((created_count + 1))
|
||||
[ "$created_count" -eq 1 ] || { echo "archive manifest contains duplicate keys" >&2; exit 2; }
|
||||
created_utc=$value
|
||||
;;
|
||||
*)
|
||||
echo "archive manifest contains unexpected fields" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
seen="$seen $key"
|
||||
done <<EOF
|
||||
$manifest
|
||||
EOF
|
||||
[ "$format_count" -eq 1 ] || { echo "archive manifest is incomplete" >&2; exit 2; }
|
||||
[ "$project_count" -eq 1 ] || { echo "archive manifest is incomplete" >&2; exit 2; }
|
||||
[ "$volume_count" -eq 1 ] || { echo "archive manifest is incomplete" >&2; exit 2; }
|
||||
[ "$role_count" -eq 1 ] || { echo "archive manifest is incomplete" >&2; exit 2; }
|
||||
[ "$helper_count" -eq 1 ] || { echo "archive manifest is incomplete" >&2; exit 2; }
|
||||
[ "$created_count" -eq 1 ] || { echo "archive manifest is incomplete" >&2; exit 2; }
|
||||
[ "$format" = "$archive_format" ] || { echo "archive format is unsupported" >&2; exit 2; }
|
||||
[ "$manifest_project" = "$project_name" ] || { echo "archive project does not match restore target" >&2; exit 2; }
|
||||
[ "$manifest_volume" = "$expected_volume_name" ] || { echo "archive volume does not match restore target" >&2; exit 2; }
|
||||
@@ -170,14 +224,6 @@ validate_volume_metadata "$volume_name"
|
||||
|
||||
running_container=$(docker compose --project-name "$project_name" ps --status running -q qdrant)
|
||||
restart_qdrant=0
|
||||
cleanup() {
|
||||
status=$?
|
||||
if [ "$restart_qdrant" -eq 1 ]; then
|
||||
docker compose --project-name "$project_name" start qdrant >/dev/null
|
||||
fi
|
||||
exit "$status"
|
||||
}
|
||||
trap cleanup EXIT HUP INT TERM
|
||||
|
||||
if [ -n "$running_container" ]; then
|
||||
docker compose --project-name "$project_name" stop qdrant >/dev/null
|
||||
|
||||
Reference in New Issue
Block a user