diff options
author | Jordan Cook <jordan.cook@pioneer.com> | 2022-04-19 20:27:26 -0500 |
---|---|---|
committer | Jordan Cook <jordan.cook@pioneer.com> | 2022-04-19 22:07:05 -0500 |
commit | 3fb12461d847e04884f66dcf64ff5cabc79cce91 (patch) | |
tree | 5ff350315febd8c50a3c55e92d137a927111513c /requests_cache/backends | |
parent | bb6446d6a975f1771cdb06a97e8b576330a63b0d (diff) | |
download | requests-cache-3fb12461d847e04884f66dcf64ff5cabc79cce91.tar.gz |
Store responses in DynamoDB as JSON documents instead of serialized binaries
Diffstat (limited to 'requests_cache/backends')
-rw-r--r-- | requests_cache/backends/__init__.py | 8 | ||||
-rw-r--r-- | requests_cache/backends/dynamodb.py | 35 | ||||
-rw-r--r-- | requests_cache/backends/mongodb.py | 6 |
3 files changed, 31 insertions, 18 deletions
diff --git a/requests_cache/backends/__init__.py b/requests_cache/backends/__init__.py index 250be7e..9f87908 100644 --- a/requests_cache/backends/__init__.py +++ b/requests_cache/backends/__init__.py @@ -15,17 +15,17 @@ logger = getLogger(__name__) # Import all backend classes for which dependencies are installed try: - from .dynamodb import DynamoDbCache, DynamoDbDict + from .dynamodb import DynamoDbCache, DynamoDbDict, DynamoDocumentDict except ImportError as e: - DynamoDbCache = DynamoDbDict = get_placeholder_class(e) # type: ignore + DynamoDbCache = DynamoDbDict = DynamoDocumentDict = get_placeholder_class(e) # type: ignore try: from .gridfs import GridFSCache, GridFSPickleDict except ImportError as e: GridFSCache = GridFSPickleDict = get_placeholder_class(e) # type: ignore try: - from .mongodb import MongoCache, MongoDict, MongoPickleDict + from .mongodb import MongoCache, MongoDict, MongoDocumentDict except ImportError as e: - MongoCache = MongoDict = MongoPickleDict = get_placeholder_class(e) # type: ignore + MongoCache = MongoDict = MongoDocumentDict = get_placeholder_class(e) # type: ignore try: from .redis import RedisCache, RedisDict, RedisHashDict except ImportError as e: diff --git a/requests_cache/backends/dynamodb.py b/requests_cache/backends/dynamodb.py index 17721f6..17f4661 100644 --- a/requests_cache/backends/dynamodb.py +++ b/requests_cache/backends/dynamodb.py @@ -12,6 +12,7 @@ from boto3.resources.base import ServiceResource from botocore.exceptions import ClientError from .._utils import get_valid_kwargs +from ..serializers import dynamodb_document_serializer from . import BaseCache, BaseStorage @@ -30,18 +31,16 @@ class DynamoDbCache(BaseCache): self, table_name: str = 'http_cache', connection: ServiceResource = None, **kwargs ): super().__init__(cache_name=table_name, **kwargs) - self.responses = DynamoDbDict(table_name, 'responses', connection=connection, **kwargs) + self.responses = DynamoDocumentDict( + table_name, 'responses', connection=connection, **kwargs + ) self.redirects = DynamoDbDict( table_name, 'redirects', connection=self.responses.connection, **kwargs ) class DynamoDbDict(BaseStorage): - """A dictionary-like interface for DynamoDB key-value store - - **Notes:** - * The actual table name on the Dynamodb server will be ``namespace:table_name`` - * In order to deal with how DynamoDB stores data, all values are serialized. + """A dictionary-like interface for DynamoDB table Args: table_name: DynamoDB table name @@ -54,7 +53,7 @@ class DynamoDbDict(BaseStorage): def __init__( self, table_name: str, - namespace: str = 'http_cache', + namespace: str, connection: ServiceResource = None, **kwargs, ): @@ -111,12 +110,10 @@ class DynamoDbDict(BaseStorage): # Depending on the serializer, the value may be either a string or Binary object raw_value = result['Item']['value'] - return self.serializer.loads( - raw_value.value if isinstance(raw_value, Binary) else raw_value - ) + return raw_value.value if isinstance(raw_value, Binary) else raw_value def __setitem__(self, key, value): - item = {**self.composite_key(key), 'value': self.serializer.dumps(value)} + item = {**self.composite_key(key), 'value': value} self._table.put_item(Item=item) def __delitem__(self, key): @@ -145,3 +142,19 @@ class DynamoDbDict(BaseStorage): def clear(self): self.bulk_delete((k for k in self)) + + +class DynamoDocumentDict(DynamoDbDict): + """Same as :class:`DynamoDbDict`, but serializes values before saving. + + By default, responses are only partially serialized into a DynamoDB-compatible document format. + """ + + def __init__(self, *args, serializer=None, **kwargs): + super().__init__(*args, serializer=serializer or dynamodb_document_serializer, **kwargs) + + def __getitem__(self, key): + return self.serializer.loads(super().__getitem__(key)) + + def __setitem__(self, key, item): + super().__setitem__(key, self.serializer.dumps(item)) diff --git a/requests_cache/backends/mongodb.py b/requests_cache/backends/mongodb.py index b48f2da..056d658 100644 --- a/requests_cache/backends/mongodb.py +++ b/requests_cache/backends/mongodb.py @@ -30,7 +30,7 @@ class MongoCache(BaseCache): def __init__(self, db_name: str = 'http_cache', connection: MongoClient = None, **kwargs): super().__init__(cache_name=db_name, **kwargs) - self.responses: MongoDict = MongoPickleDict( + self.responses: MongoDict = MongoDocumentDict( db_name, collection_name='responses', connection=connection, @@ -140,10 +140,10 @@ class MongoDict(BaseStorage): self.connection.close() -class MongoPickleDict(MongoDict): +class MongoDocumentDict(MongoDict): """Same as :class:`MongoDict`, but serializes values before saving. - By default, responses are only partially serialized into a MongoDB-compatible document mapping. + By default, responses are only partially serialized into a MongoDB-compatible document format. """ def __init__(self, *args, serializer=None, **kwargs): |