Skip to content

Commit 5a32952

Browse files
Pigbibicodex
andauthored
Add Cloud Run health warmup scheduler (#342)
Co-authored-by: Codex <noreply@openai.com>
1 parent 033080c commit 5a32952

2 files changed

Lines changed: 74 additions & 1 deletion

File tree

.github/workflows/sync-cloud-run-env.yml

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,14 +1015,15 @@ jobs:
10151015
service_name,
10161016
timezone,
10171017
str(scheduler.get("main_time") or configured_time("CLOUD_SCHEDULER_MAIN_TIME", "45 15")),
1018+
str(scheduler.get("probe_time") or configured_time("CLOUD_SCHEDULER_PROBE_TIME", "35 9,15")),
10181019
]
10191020
)
10201021
)
10211022
PY
10221023
)
10231024
10241025
for update in "${scheduler_updates[@]}"; do
1025-
IFS=$'\t' read -r cloud_run_service market_timezone main_time <<< "${update}"
1026+
IFS=$'\t' read -r cloud_run_service market_timezone main_time warmup_time <<< "${update}"
10261027
if [ -z "${cloud_run_service}" ] || [ -z "${market_timezone}" ]; then
10271028
continue
10281029
fi
@@ -1077,6 +1078,24 @@ jobs:
10771078
desired_schedule="$(CURRENT_SCHEDULE="${current_schedule}" SCHEDULE_TIME="${main_time}" python - <<'PY'
10781079
import os
10791080
1081+
current_fields = os.environ["CURRENT_SCHEDULE"].split()
1082+
time_fields = os.environ["SCHEDULE_TIME"].split()
1083+
if len(current_fields) != 5:
1084+
raise SystemExit(f"Cloud Scheduler schedule must have 5 fields: {os.environ['CURRENT_SCHEDULE']!r}")
1085+
if len(time_fields) == 5:
1086+
print(" ".join(time_fields))
1087+
elif len(time_fields) == 2:
1088+
print(" ".join([*time_fields, *current_fields[2:]]))
1089+
else:
1090+
raise SystemExit(
1091+
f"Cloud Scheduler override must have 2 time fields or 5 cron fields: {os.environ['SCHEDULE_TIME']!r}"
1092+
)
1093+
PY
1094+
)"
1095+
1096+
desired_warmup_schedule="$(CURRENT_SCHEDULE="${desired_schedule}" SCHEDULE_TIME="${warmup_time}" python - <<'PY'
1097+
import os
1098+
10801099
current_fields = os.environ["CURRENT_SCHEDULE"].split()
10811100
time_fields = os.environ["SCHEDULE_TIME"].split()
10821101
if len(current_fields) != 5:
@@ -1115,6 +1134,46 @@ jobs:
11151134
--oidc-token-audience="${service_url}" \
11161135
--quiet
11171136
fi
1137+
1138+
warmup_job_name="${cloud_run_service%-service}-warmup-scheduler"
1139+
warmup_uri="${service_url}/healthz"
1140+
if gcloud scheduler jobs describe "${warmup_job_name}" \
1141+
--project="${GCP_PROJECT_ID}" \
1142+
--location="${scheduler_location}" >/dev/null 2>&1; then
1143+
echo "Updating Cloud Scheduler warmup ${warmup_job_name} to ${desired_warmup_schedule}."
1144+
gcloud scheduler jobs update http "${warmup_job_name}" \
1145+
--project="${GCP_PROJECT_ID}" \
1146+
--location="${scheduler_location}" \
1147+
--uri="${warmup_uri}" \
1148+
--schedule="${desired_warmup_schedule}" \
1149+
--time-zone="${market_timezone}" \
1150+
--http-method=GET \
1151+
--oidc-service-account-email="${GCP_SCHEDULER_SERVICE_ACCOUNT}" \
1152+
--oidc-token-audience="${service_url}" \
1153+
--attempt-deadline=60s \
1154+
--max-retry-attempts=2 \
1155+
--min-backoff=15s \
1156+
--max-backoff=60s \
1157+
--max-doublings=2 \
1158+
--quiet
1159+
else
1160+
echo "Creating Cloud Scheduler warmup ${warmup_job_name} at ${desired_warmup_schedule}."
1161+
gcloud scheduler jobs create http "${warmup_job_name}" \
1162+
--project="${GCP_PROJECT_ID}" \
1163+
--location="${scheduler_location}" \
1164+
--uri="${warmup_uri}" \
1165+
--schedule="${desired_warmup_schedule}" \
1166+
--time-zone="${market_timezone}" \
1167+
--http-method=GET \
1168+
--oidc-service-account-email="${GCP_SCHEDULER_SERVICE_ACCOUNT}" \
1169+
--oidc-token-audience="${service_url}" \
1170+
--attempt-deadline=60s \
1171+
--max-retry-attempts=2 \
1172+
--min-backoff=15s \
1173+
--max-backoff=60s \
1174+
--max-doublings=2 \
1175+
--quiet
1176+
fi
11181177
done
11191178
11201179
monitor_dispatch_service="$(printf '%s\n' "${scheduler_updates[@]}" | head -n 1 | cut -f1)"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from pathlib import Path
2+
3+
4+
def test_env_sync_creates_non_trading_health_warmup_with_retries() -> None:
5+
workflow = Path(".github/workflows/sync-cloud-run-env.yml").read_text(encoding="utf-8")
6+
7+
assert 'scheduler.get("probe_time")' in workflow
8+
assert 'warmup_job_name="${cloud_run_service%-service}-warmup-scheduler"' in workflow
9+
assert 'warmup_uri="${service_url}/healthz"' in workflow
10+
assert '--http-method=GET' in workflow
11+
assert '--max-retry-attempts=2' in workflow
12+
assert workflow.count('--max-retry-attempts=2') == 2
13+
assert '--attempt-deadline=60s' in workflow
14+
assert 'warmup_uri="${service_url}/probe"' not in workflow

0 commit comments

Comments
 (0)