mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-10-05 18:01:04 +01:00
Fix Google Books search cache failures (#958)
Recognises google error 503s as invalid results and does not add to results cache. Fixes #945
This commit is contained in:
@@ -47,6 +47,11 @@ _HTTP_STATUS_NOT_FOUND = HTTPStatus.NOT_FOUND
|
||||
|
||||
GOOGLE_BOOKS_BASE_URL = "https://www.googleapis.com/books/v1"
|
||||
|
||||
|
||||
class _GoogleBooksRequestError(Exception):
|
||||
"""Raised when Google Books does not return a usable API response."""
|
||||
|
||||
|
||||
# Sort mapping - Google only supports "relevance" and "newest"
|
||||
SORT_MAPPING: dict[SortOrder, str | None] = {
|
||||
SortOrder.RELEVANCE: None, # Default, no param needed
|
||||
@@ -117,7 +122,10 @@ class GoogleBooksProvider(MetadataProvider):
|
||||
f"{options.query}:{options.search_type.value}:{options.sort.value}:"
|
||||
f"{options.language}:{options.limit}:{options.page}:{fields_key}"
|
||||
)
|
||||
return self._search_cached(cache_key, options)
|
||||
try:
|
||||
return self._search_cached(cache_key, options)
|
||||
except _GoogleBooksRequestError:
|
||||
return []
|
||||
|
||||
@cacheable(
|
||||
ttl_key="METADATA_CACHE_SEARCH_TTL",
|
||||
@@ -166,18 +174,19 @@ class GoogleBooksProvider(MetadataProvider):
|
||||
if options.language:
|
||||
params["langRestrict"] = options.language
|
||||
|
||||
result = self._make_request("/volumes", params)
|
||||
if result is None:
|
||||
raise _GoogleBooksRequestError
|
||||
|
||||
books: list[BookMetadata] = []
|
||||
try:
|
||||
result = self._make_request("/volumes", params)
|
||||
if result:
|
||||
items = result.get("items", [])
|
||||
items = result.get("items", [])
|
||||
for item in items:
|
||||
book = self._parse_volume(item)
|
||||
if book:
|
||||
books.append(book)
|
||||
|
||||
for item in items:
|
||||
book = self._parse_volume(item)
|
||||
if book:
|
||||
books.append(book)
|
||||
|
||||
logger.info("Google Books search '%s' returned %s results", query, len(books))
|
||||
logger.info("Google Books search '%s' returned %s results", query, len(books))
|
||||
|
||||
except Exception:
|
||||
logger.exception("Google Books search error")
|
||||
|
||||
@@ -1,6 +1,59 @@
|
||||
import requests
|
||||
|
||||
from shelfmark.core.cache import get_metadata_cache
|
||||
from shelfmark.metadata_providers import MetadataSearchOptions
|
||||
from shelfmark.metadata_providers.googlebooks import GoogleBooksProvider
|
||||
|
||||
|
||||
class _GoogleBooksResponse:
|
||||
def __init__(self, payload):
|
||||
self._payload = payload
|
||||
|
||||
def raise_for_status(self):
|
||||
return None
|
||||
|
||||
def json(self):
|
||||
return self._payload
|
||||
|
||||
|
||||
class _FlakyGoogleBooksSession:
|
||||
def __init__(self):
|
||||
self.calls = 0
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
self.calls += 1
|
||||
if self.calls == 1:
|
||||
raise requests.Timeout
|
||||
return _GoogleBooksResponse(
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": "volume-1",
|
||||
"volumeInfo": {
|
||||
"title": "Recovered Book",
|
||||
"authors": ["Alice Author"],
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_googlebooks_search_does_not_cache_request_failures():
|
||||
get_metadata_cache().clear()
|
||||
provider = GoogleBooksProvider(api_key="test-key")
|
||||
session = _FlakyGoogleBooksSession()
|
||||
provider.session = session
|
||||
options = MetadataSearchOptions(query="Recovered Book")
|
||||
|
||||
assert provider.search(options) == []
|
||||
|
||||
result = provider.search(options)
|
||||
|
||||
assert session.calls == 2
|
||||
assert [book.title for book in result] == ["Recovered Book"]
|
||||
|
||||
|
||||
class TestGoogleBooksParseVolume:
|
||||
def test_parse_volume_returns_metadata_for_valid_payload(self):
|
||||
provider = GoogleBooksProvider(api_key="test-key")
|
||||
|
||||
Reference in New Issue
Block a user