Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/server/domain/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,18 @@ class AssetPrice:

def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary representation."""
# Handle both datetime and date objects for timestamp
ts = self.timestamp
if isinstance(ts, datetime):
ts = ts.isoformat()
elif hasattr(ts, 'isoformat'): # date object
ts = ts.isoformat()

return {
"ticker": self.ticker,
"price": float(self.price) if self.price else None,
"currency": self.currency,
"timestamp": (
self.timestamp.isoformat()
if isinstance(self.timestamp, datetime)
else self.timestamp
),
"timestamp": ts,
"volume": float(self.volume) if self.volume else None,
"open_price": float(self.open_price) if self.open_price else None,
"high_price": float(self.high_price) if self.high_price else None,
Expand Down
42 changes: 41 additions & 1 deletion src/server/infrastructure/cache/redis_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,52 @@ async def get(self, key: str) -> Optional[Any]:

async def set(self, key: str, value: Any, ttl: Optional[int] = None) -> bool:
try:
await self._cache.set(key, value, ttl=ttl or self._ttl_default)
# Serialize value for JSON storage (handles datetime objects)
serialized = self._serialize_value(value)
await self._cache.set(key, serialized, ttl=ttl or self._ttl_default)
return True
except Exception as e:
logger.error(f"❌ Cache set error for {key}: {e}")
return False

def _serialize_value(self, value: Any) -> Any:
"""Serialize value for JSON storage, handling datetime objects."""
# Pydantic model: use mode='json' to convert datetime to ISO strings
if hasattr(value, 'model_dump'):
return value.model_dump(mode='json')

# Dataclass with to_dict method
if hasattr(value, 'to_dict'):
result = value.to_dict()
# Recursively handle nested datetime objects
return self._serialize_dict(result)

# List of items
if isinstance(value, list):
return [self._serialize_value(item) for item in value]

# Dict with potential datetime values
if isinstance(value, dict):
return self._serialize_dict(value)

return value

def _serialize_dict(self, data: dict) -> dict:
"""Recursively serialize dict values, converting datetime to ISO strings."""
from datetime import date, datetime

result = {}
for k, v in data.items():
if isinstance(v, (datetime, date)):
result[k] = v.isoformat()
elif isinstance(v, dict):
result[k] = self._serialize_dict(v)
elif isinstance(v, list):
result[k] = [self._serialize_value(item) for item in v]
else:
result[k] = v
return result

async def delete(self, key: str) -> bool:
try:
await self._cache.delete(key)
Expand Down