ready for testing
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m58s
Run linting on the backend code / Build (pull_request) Successful in 28s
Run testing on the backend code / Build (pull_request) Failing after 13m25s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 26s
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m58s
Run linting on the backend code / Build (pull_request) Successful in 28s
Run testing on the backend code / Build (pull_request) Failing after 13m25s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 26s
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
"""Module defining the caching strategy for overpass requests."""
|
||||
import os
|
||||
import xml.etree.ElementTree as ET
|
||||
import hashlib
|
||||
import time
|
||||
|
||||
from ..constants import OSM_CACHE_DIR
|
||||
from ..constants import OSM_CACHE_DIR, OSM_TYPES
|
||||
|
||||
|
||||
def get_cache_key(query: str) -> str:
|
||||
@@ -13,14 +13,9 @@ def get_cache_key(query: str) -> str:
|
||||
"""
|
||||
return hashlib.md5(query.encode('utf-8')).hexdigest()
|
||||
|
||||
|
||||
class CachingStrategyBase:
|
||||
"""
|
||||
Base class for implementing caching strategies.
|
||||
|
||||
This class defines the structure for a caching strategy with basic methods
|
||||
that must be implemented by subclasses. Subclasses should define how to
|
||||
retrieve, store, and close the cache.
|
||||
"""
|
||||
def get(self, key):
|
||||
"""Retrieve the cached data associated with the provided key."""
|
||||
@@ -30,6 +25,15 @@ class CachingStrategyBase:
|
||||
"""Store data in the cache with the specified key."""
|
||||
raise NotImplementedError('Subclass should implement set')
|
||||
|
||||
def set_hollow(self, key, cell: tuple, osm_types: OSM_TYPES,
|
||||
selector: str, conditions=[], out='center'):
|
||||
"""Create a hollow (empty) cache entry with a specific key."""
|
||||
raise NotImplementedError('Subclass should implement set_hollow')
|
||||
|
||||
def fill_hollow(self, key, value):
|
||||
"""Fill in the cache for an existing hollow entry."""
|
||||
raise NotImplementedError('Subclass should implement fill_hollow')
|
||||
|
||||
def close(self):
|
||||
"""Clean up or close any resources used by the caching strategy."""
|
||||
|
||||
@@ -37,22 +41,10 @@ class CachingStrategyBase:
|
||||
class XMLCache(CachingStrategyBase):
|
||||
"""
|
||||
A caching strategy that stores and retrieves data in XML format.
|
||||
|
||||
This class provides methods to cache data as XML files in a specified directory.
|
||||
The directory is automatically suffixed with '_XML' to distinguish it from other
|
||||
caching strategies. The data is stored and retrieved using XML serialization.
|
||||
|
||||
Args:
|
||||
cache_dir (str): The base directory where XML cache files will be stored.
|
||||
Defaults to 'OSM_CACHE_DIR' with a '_XML' suffix.
|
||||
|
||||
Methods:
|
||||
get(key): Retrieve cached data from a XML file associated with the given key.
|
||||
set(key, value): Store data in a XML file with the specified key.
|
||||
"""
|
||||
def __init__(self, cache_dir=OSM_CACHE_DIR):
|
||||
# Add the class name as a suffix to the directory
|
||||
self._cache_dir = f'{cache_dir}_XML'
|
||||
self._cache_dir = f'{cache_dir}'
|
||||
if not os.path.exists(self._cache_dir):
|
||||
os.makedirs(self._cache_dir)
|
||||
|
||||
@@ -68,7 +60,6 @@ class XMLCache(CachingStrategyBase):
|
||||
tree = ET.parse(filename)
|
||||
return tree.getroot() # Return the root element of the parsed XML
|
||||
except ET.ParseError:
|
||||
# print(f"Error parsing cached XML file: {filename}")
|
||||
return None
|
||||
return None
|
||||
|
||||
@@ -77,25 +68,41 @@ class XMLCache(CachingStrategyBase):
|
||||
filename = self._filename(key)
|
||||
tree = ET.ElementTree(value) # value is expected to be an ElementTree root element
|
||||
try:
|
||||
# Write the XML data to a file
|
||||
with open(filename, 'wb') as file:
|
||||
tree.write(file, encoding='utf-8', xml_declaration=True)
|
||||
except IOError as e:
|
||||
raise IOError(f"Error writing to cache file: {filename} - {e}") from e
|
||||
|
||||
def set_hollow(self, key, cell: tuple, osm_types: OSM_TYPES,
|
||||
selector: str, conditions=[], out='center'):
|
||||
"""Create an empty placeholder cache entry for a future fill."""
|
||||
hollow_key = f'hollow_{key}'
|
||||
filename = self._filename(hollow_key)
|
||||
|
||||
# Create the root element <cache>
|
||||
root = ET.Element("params")
|
||||
# Add sub-elements with provided values
|
||||
ET.SubElement(root, "key").text = key
|
||||
ET.SubElement(root, "cell").text = f"({cell[0]}, {cell[1]})"
|
||||
ET.SubElement(root, "osm_types").text = ','.join(osm_types)
|
||||
ET.SubElement(root, "selector").text = selector
|
||||
ET.SubElement(root, "conditions").text = ','.join(conditions) if conditions else "none"
|
||||
ET.SubElement(root, "out").text = out
|
||||
|
||||
# Create an ElementTree object from the root
|
||||
tree = ET.ElementTree(root)
|
||||
|
||||
# Write the XML to the file
|
||||
with open(filename, 'wb') as file:
|
||||
tree.write(file, encoding='utf-8', xml_declaration=True)
|
||||
|
||||
def close(self):
|
||||
"""Cleanup method, if needed."""
|
||||
pass
|
||||
|
||||
class CachingStrategy:
|
||||
"""
|
||||
A class to manage different caching strategies.
|
||||
|
||||
This class provides an interface to switch between different caching strategies
|
||||
(e.g., XMLCache, JSONCache) dynamically. It allows caching data in different formats,
|
||||
depending on the strategy being used. By default, it uses the XMLCache strategy.
|
||||
|
||||
Attributes:
|
||||
__strategy (CachingStrategyBase): The currently active caching strategy.
|
||||
__strategies (dict): A mapping between strategy names (as strings) and their corresponding
|
||||
classes, allowing dynamic selection of caching strategies.
|
||||
"""
|
||||
__strategy = XMLCache() # Default caching strategy
|
||||
__strategies = {
|
||||
@@ -104,37 +111,31 @@ class CachingStrategy:
|
||||
|
||||
@classmethod
|
||||
def use(cls, strategy_name='XML', **kwargs):
|
||||
"""
|
||||
Set the caching strategy based on the strategy_name provided.
|
||||
|
||||
Args:
|
||||
strategy_name (str): The name of the caching strategy (e.g., 'XML').
|
||||
**kwargs: Additional keyword arguments to pass when initializing the strategy.
|
||||
"""
|
||||
# If a previous strategy exists, close it
|
||||
if cls.__strategy:
|
||||
cls.__strategy.close()
|
||||
|
||||
# Retrieve the strategy class based on the strategy name
|
||||
strategy_class = cls.__strategies.get(strategy_name)
|
||||
|
||||
if not strategy_class:
|
||||
raise ValueError(f"Unknown caching strategy: {strategy_name}")
|
||||
|
||||
# Instantiate the new strategy with the provided arguments
|
||||
cls.__strategy = strategy_class(**kwargs)
|
||||
return cls.__strategy
|
||||
|
||||
@classmethod
|
||||
def get(cls, key):
|
||||
"""Get data from the current strategy's cache."""
|
||||
if not cls.__strategy:
|
||||
raise RuntimeError("Caching strategy has not been set.")
|
||||
return cls.__strategy.get(key)
|
||||
|
||||
@classmethod
|
||||
def set(cls, key, value):
|
||||
"""Set data in the current strategy's cache."""
|
||||
if not cls.__strategy:
|
||||
raise RuntimeError("Caching strategy has not been set.")
|
||||
cls.__strategy.set(key, value)
|
||||
|
||||
@classmethod
|
||||
def set_hollow(cls, key, cell: tuple, osm_types: OSM_TYPES,
|
||||
selector: str, conditions=[], out='center'):
|
||||
"""Create a hollow cache entry."""
|
||||
cls.__strategy.set_hollow(key, cell, osm_types, selector, conditions, out)
|
||||
|
||||
@classmethod
|
||||
def fill_hollow(cls, key, value):
|
||||
"""Fill in the hollow cache entry with actual data."""
|
||||
cls.__strategy.fill_hollow(key, value)
|
||||
|
Reference in New Issue
Block a user