Files
btcdata/scripts/fetch-year.sh
T
2026-09-30 17:52:41 +02:00

155 lines
4.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Usage: ./scripts/fetch-year.sh YEAR [--reverse]
# Fetches sequentially; prints JSON responses to stdout and errors to stderr.
set -euo pipefail
reverse=false
year=
for arg in "$@"; do
case "$arg" in
--reverse) reverse=true ;;
*)
if [[ -n $year ]]; then
echo "Usage: $0 YEAR [--reverse]" >&2
exit 1
fi
year=$arg
;;
esac
done
if [[ -z $year ]]; then
echo "Usage: $0 YEAR [--reverse]" >&2
exit 1
fi
if [[ ! $year =~ ^[0-9]{4}$ || $year == 0000 ]]; then
echo "YEAR must be a four-digit year from 0001 to 9999." >&2
exit 1
fi
year_number=$((10#$year))
days_in_month=(31 28 31 30 31 30 31 31 30 31 30 31)
if (( year_number % 400 == 0 || (year_number % 4 == 0 && year_number % 100 != 0) )); then
days_in_month[1]=29
fi
# Reuse a reachable service, or keep a port-forward alive while fetching.
service_ready() {
curl --fail --silent --output /dev/null --connect-timeout 1 --max-time 2 \
'http://localhost:4101/api/health'
}
forward_pid=
cleanup() {
if [[ -n $forward_pid ]]; then
kill "$forward_pid" 2>/dev/null || true
wait "$forward_pid" 2>/dev/null || true
forward_pid=
fi
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
wait_for_pod() {
local selector
# Use the service's selector rather than assuming a particular pod label.
if ! selector=$(kubectl -n sejs get svc btcdata --request-timeout=10s \
-o go-template='{{range $key, $value := .spec.selector}}{{$key}}={{$value}},{{end}}'); then
return 1
fi
selector=${selector%,}
if [[ -z $selector ]]; then
echo "Service sejs/btcdata has no pod selector." >&2
return 1
fi
echo "Waiting up to 5 minutes for btcdata pods to become Ready..." >&2
kubectl -n sejs wait --for=condition=Ready pod --selector="$selector" \
--timeout=300s --request-timeout=310s >&2
}
start_forward() {
local attempt
cleanup
if ! command -v kubectl >/dev/null 2>&1; then
echo "Service unavailable on localhost:4101 and kubectl is not installed." >&2
return 1
fi
if ! wait_for_pod; then
echo "btcdata pod readiness check failed; not opening a tunnel." >&2
return 1
fi
echo "Starting kubectl port-forward for sejs/btcdata..." >&2
kubectl -n sejs port-forward svc/btcdata 4101:4101 >&2 &
forward_pid=$!
for (( attempt = 0; attempt < 30; attempt++ )); do
if ! kill -0 "$forward_pid" 2>/dev/null; then
echo "Port-forward exited before the service became ready." >&2
cleanup
return 1
fi
if service_ready; then
return 0
fi
sleep 1
done
echo "Timed out waiting for the service on localhost:4101." >&2
cleanup
return 1
}
ensure_service() {
local retry
if service_ready; then
return 0
fi
for (( retry = 1; retry <= 3; retry++ )); do
echo "Recovering port-forward (attempt $retry/3)..." >&2
if start_forward; then
return 0
fi
if (( retry < 3 )); then
sleep 2
fi
done
echo "Unable to restore the service on localhost:4101." >&2
return 1
}
fetch_date() {
curl --fail --silent --show-error --connect-timeout 5 -X GET \
"http://localhost:4101/api/price/day/$1" \
-H "accept: application/json" --write-out '\n'
}
ensure_service || exit 1
# Generate dates without relying on platform-specific date command options.
status=0
for (( month_index = 0; month_index < 12; month_index++ )); do
month=$((month_index + 1))
if [[ $reverse == true ]]; then
month=$((12 - month_index))
fi
days=${days_in_month[month - 1]}
for (( day_index = 0; day_index < days; day_index++ )); do
day=$((day_index + 1))
if [[ $reverse == true ]]; then
day=$((days - day_index))
fi
printf -v date '%s-%02d-%02d' "$year" "$month" "$day"
if ! fetch_date "$date"; then
if ! service_ready; then
ensure_service || exit 1
echo "Retrying $date after tunnel recovery..." >&2
if fetch_date "$date"; then
continue
fi
fi
echo "Failed to fetch $date" >&2
status=1
fi
done
done
exit "$status"