Handle Wikidata API errors with proper HTTP responses (429, 503)
Also retry on RequestException and raise QueryError on non-200 responses. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d75d617d11
commit
1442620ece
2 changed files with 15 additions and 2 deletions
|
|
@ -110,13 +110,16 @@ Row = dict[str, dict[str, typing.Any]]
|
||||||
Hit = dict[str, str | int | None]
|
Hit = dict[str, str | int | None]
|
||||||
|
|
||||||
|
|
||||||
@backoff.on_exception(backoff.expo, QueryError, max_tries=5)
|
@backoff.on_exception(backoff.expo, (QueryError, RequestException), max_tries=5)
|
||||||
def wdqs(query: str) -> list[Row]:
|
def wdqs(query: str) -> list[Row]:
|
||||||
"""Pass query to the Wikidata Query Service."""
|
"""Pass query to the Wikidata Query Service."""
|
||||||
r = requests.post(
|
r = requests.post(
|
||||||
wikidata_query_api_url, data={"query": query, "format": "json"}, headers=headers
|
wikidata_query_api_url, data={"query": query, "format": "json"}, headers=headers
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not r.ok:
|
||||||
|
raise QueryError(query, r)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return typing.cast(list[Row], r.json()["results"]["bindings"])
|
return typing.cast(list[Row], r.json()["results"]["bindings"])
|
||||||
except requests.exceptions.JSONDecodeError:
|
except requests.exceptions.JSONDecodeError:
|
||||||
|
|
|
||||||
12
lookup.py
12
lookup.py
|
|
@ -10,6 +10,7 @@ import traceback
|
||||||
import typing
|
import typing
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
|
import requests.exceptions
|
||||||
import sqlalchemy.exc
|
import sqlalchemy.exc
|
||||||
import werkzeug.debug.tbtools
|
import werkzeug.debug.tbtools
|
||||||
from flask import Flask, jsonify, redirect, render_template, request, url_for
|
from flask import Flask, jsonify, redirect, render_template, request, url_for
|
||||||
|
|
@ -375,7 +376,16 @@ def index() -> str | Response:
|
||||||
return jsonify(coords={"lat": lat, "lon": lon}, error=error_msg)
|
return jsonify(coords={"lat": lat, "lon": lon}, error=error_msg)
|
||||||
|
|
||||||
needs_commons = request.args.get("needs_commons", "true").lower() != "false"
|
needs_commons = request.args.get("needs_commons", "true").lower() != "false"
|
||||||
result = lat_lon_to_wikidata(lat, lon, needs_commons=needs_commons)["result"]
|
try:
|
||||||
|
result = lat_lon_to_wikidata(lat, lon, needs_commons=needs_commons)["result"]
|
||||||
|
except (wikidata.QueryError, wikidata.APIResponseError) as e:
|
||||||
|
r = e.r if isinstance(e, wikidata.QueryError) else e.response
|
||||||
|
if r.status_code == 429:
|
||||||
|
extra = {"Retry-After": r.headers["Retry-After"]} if "Retry-After" in r.headers else {}
|
||||||
|
return jsonify(error="Rate limited by Wikidata, please try again later"), 429, extra
|
||||||
|
return jsonify(error=f"Wikidata query failed (HTTP {r.status_code}), please try again later"), 503
|
||||||
|
except requests.exceptions.RequestException:
|
||||||
|
return jsonify(error="Could not connect to Wikidata, please try again later"), 503
|
||||||
result.pop("element", None)
|
result.pop("element", None)
|
||||||
result.pop("geojson", None)
|
result.pop("geojson", None)
|
||||||
if logging_enabled:
|
if logging_enabled:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue