feat: MTG database integration with Redis caching
- Added MTG card ORM models (mtg_cards, mtg_sets tables) - Created card_database service with search, get_by_name, get_by_set - Added Redis client with caching layer (3600s TTL default) - Created card router with caching on all endpoints: - Search cards (5min cache) - Get card by name (10min cache) - Get cards by set (15min cache) - Get card types/rarities (30min cache) - Get sets (1hr cache) - Get statistics (1hr cache) - Updated settings.py: - Added JWT_SECRET_KEY field - Added DB_CONFIG and REDIS_CONFIG dictionaries - Updated security.py to use JWT_SECRET_KEY with fallback - Updated auth.py to use timezone-aware datetimes - Updated refresh_mtg.py to use settings instead of os.environ - Updated mtg_monitor.py to use settings for connections - Added services package with __init__.py All 20 tests passing.
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
"""
|
||||
SQLAlchemy ORM models for the MTG database (mtgjson.com data).
|
||||
|
||||
Models mirror the mtg_cards and mtg_sets tables in the MTG PostgreSQL database.
|
||||
"""
|
||||
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Index
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.sql import func
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class MtgSet(Base):
|
||||
"""MTG Set model."""
|
||||
__tablename__ = "mtg_sets"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
code = Column(String(10), unique=True, nullable=False, index=True)
|
||||
name = Column(String(255), nullable=True)
|
||||
type = Column(String(100), nullable=True)
|
||||
release_date = Column(DateTime, nullable=True)
|
||||
base_set_size = Column(Integer, nullable=True)
|
||||
total_size = Column(Integer, nullable=True)
|
||||
is_foil_only = Column(Integer, nullable=True)
|
||||
is_non_foil_only = Column(Integer, nullable=True)
|
||||
digital = Column(Integer, nullable=True)
|
||||
icon_svg_url = Column(Text, nullable=True)
|
||||
parent_code = Column(String(10), nullable=True)
|
||||
mtgo_code = Column(String(10), nullable=True)
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
|
||||
|
||||
# Relationships
|
||||
cards = relationship("MtgCard", back_populates="set")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<MtgSet {self.code}: {self.name}>"
|
||||
|
||||
|
||||
class MtgCard(Base):
|
||||
"""MTG Card model."""
|
||||
__tablename__ = "mtg_cards"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
set_id = Column(Integer, ForeignKey("mtg_sets.id"), nullable=True, index=True)
|
||||
name = Column(String(255), nullable=True, index=True)
|
||||
mana_cost = Column(String(255), nullable=True, index=True)
|
||||
type_line = Column(String(255), nullable=True, index=True)
|
||||
oracle_text = Column(Text, nullable=True)
|
||||
power = Column(String(50), nullable=True)
|
||||
toughness = Column(String(50), nullable=True)
|
||||
rarity = Column(String(50), nullable=True, index=True)
|
||||
layout = Column(String(50), nullable=True)
|
||||
artist = Column(String(255), nullable=True)
|
||||
flavor_text = Column(Text, nullable=True)
|
||||
numbers = Column(String(100), nullable=True)
|
||||
identifiers = Column(Text, nullable=True) # JSON string
|
||||
images = Column(Text, nullable=True) # JSON string
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
|
||||
|
||||
# Relationships
|
||||
set = relationship("MtgSet", back_populates="cards")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<MtgCard {self.name} ({self.set_id})>"
|
||||
|
||||
|
||||
# Indexes for performance
|
||||
Index("idx_mtg_cards_name_set", MtgCard.name, MtgCard.set_id)
|
||||
Index("idx_mtg_cards_type", MtgCard.type_line)
|
||||
Index("idx_mtg_cards_rarity", MtgCard.rarity)
|
||||
Reference in New Issue
Block a user