| """
|
| SQLAlchemy Database Models
|
| Defines all database tables for the crypto API monitoring system
|
| """
|
|
|
| from sqlalchemy import Column, Integer, String, Float, Boolean, DateTime, Text, ForeignKey, Enum
|
| from sqlalchemy.ext.declarative import declarative_base
|
| from sqlalchemy.orm import relationship
|
| from datetime import datetime
|
| import enum
|
|
|
| Base = declarative_base()
|
|
|
|
|
| class ProviderCategory(enum.Enum):
|
| """Provider category enumeration"""
|
| MARKET_DATA = "market_data"
|
| BLOCKCHAIN_EXPLORERS = "blockchain_explorers"
|
| NEWS = "news"
|
| SENTIMENT = "sentiment"
|
| ONCHAIN_ANALYTICS = "onchain_analytics"
|
| RPC_NODES = "rpc_nodes"
|
| CORS_PROXIES = "cors_proxies"
|
|
|
|
|
| class RateLimitType(enum.Enum):
|
| """Rate limit period type"""
|
| PER_MINUTE = "per_minute"
|
| PER_HOUR = "per_hour"
|
| PER_DAY = "per_day"
|
|
|
|
|
| class ConnectionStatus(enum.Enum): |
| """Connection attempt status""" |
| SUCCESS = "success" |
| FAILED = "failed" |
| TIMEOUT = "timeout" |
| RATE_LIMITED = "rate_limited" |
|
|
|
|
| class ProviderStatusEnum(enum.Enum): |
| """Legacy provider status enumeration.""" |
| UNKNOWN = "unknown" |
| ONLINE = "online" |
| DEGRADED = "degraded" |
| OFFLINE = "offline" |
|
|
|
|
| class Provider(Base):
|
| """API Provider configuration table"""
|
| __tablename__ = 'providers'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| name = Column(String(255), nullable=False, unique=True)
|
| category = Column(String(100), nullable=False)
|
| endpoint_url = Column(String(500), nullable=False)
|
| requires_key = Column(Boolean, default=False) |
| api_key_masked = Column(String(100), nullable=True) |
| rate_limit_type = Column(String(50), nullable=True) |
| rate_limit_value = Column(Integer, nullable=True) |
| timeout_ms = Column(Integer, default=10000) |
| priority_tier = Column(Integer, default=3) |
| status = Column(Enum(ProviderStatusEnum), default=ProviderStatusEnum.UNKNOWN) |
| created_at = Column(DateTime, default=datetime.utcnow) |
| updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) |
|
|
|
|
| connection_attempts = relationship("ConnectionAttempt", back_populates="provider", cascade="all, delete-orphan")
|
| data_collections = relationship("DataCollection", back_populates="provider", cascade="all, delete-orphan")
|
| rate_limit_usage = relationship("RateLimitUsage", back_populates="provider", cascade="all, delete-orphan")
|
| schedule_config = relationship("ScheduleConfig", back_populates="provider", uselist=False, cascade="all, delete-orphan")
|
|
|
|
|
| class ConnectionAttempt(Base):
|
| """Connection attempts log table"""
|
| __tablename__ = 'connection_attempts'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
| provider_id = Column(Integer, ForeignKey('providers.id'), nullable=False, index=True)
|
| endpoint = Column(String(500), nullable=False)
|
| status = Column(String(50), nullable=False)
|
| response_time_ms = Column(Integer, nullable=True)
|
| http_status_code = Column(Integer, nullable=True)
|
| error_type = Column(String(100), nullable=True)
|
| error_message = Column(Text, nullable=True)
|
| retry_count = Column(Integer, default=0)
|
| retry_result = Column(String(100), nullable=True)
|
|
|
|
|
| provider = relationship("Provider", back_populates="connection_attempts")
|
|
|
|
|
| class DataCollection(Base):
|
| """Data collections table"""
|
| __tablename__ = 'data_collections'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| provider_id = Column(Integer, ForeignKey('providers.id'), nullable=False, index=True)
|
| category = Column(String(100), nullable=False)
|
| scheduled_time = Column(DateTime, nullable=False)
|
| actual_fetch_time = Column(DateTime, nullable=False)
|
| data_timestamp = Column(DateTime, nullable=True)
|
| staleness_minutes = Column(Float, nullable=True)
|
| record_count = Column(Integer, default=0)
|
| payload_size_bytes = Column(Integer, default=0)
|
| data_quality_score = Column(Float, default=1.0)
|
| on_schedule = Column(Boolean, default=True)
|
| skip_reason = Column(String(255), nullable=True)
|
|
|
|
|
| provider = relationship("Provider", back_populates="data_collections")
|
|
|
|
|
| class RateLimitUsage(Base):
|
| """Rate limit usage tracking table"""
|
| __tablename__ = 'rate_limit_usage'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
| provider_id = Column(Integer, ForeignKey('providers.id'), nullable=False, index=True)
|
| limit_type = Column(String(50), nullable=False)
|
| limit_value = Column(Integer, nullable=False)
|
| current_usage = Column(Integer, nullable=False)
|
| percentage = Column(Float, nullable=False)
|
| reset_time = Column(DateTime, nullable=False)
|
|
|
|
|
| provider = relationship("Provider", back_populates="rate_limit_usage")
|
|
|
|
|
| class ScheduleConfig(Base):
|
| """Schedule configuration table"""
|
| __tablename__ = 'schedule_config'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| provider_id = Column(Integer, ForeignKey('providers.id'), nullable=False, unique=True)
|
| schedule_interval = Column(String(50), nullable=False)
|
| enabled = Column(Boolean, default=True)
|
| last_run = Column(DateTime, nullable=True)
|
| next_run = Column(DateTime, nullable=True)
|
| on_time_count = Column(Integer, default=0)
|
| late_count = Column(Integer, default=0)
|
| skip_count = Column(Integer, default=0)
|
|
|
|
|
| provider = relationship("Provider", back_populates="schedule_config")
|
|
|
|
|
| class ScheduleCompliance(Base):
|
| """Schedule compliance tracking table"""
|
| __tablename__ = 'schedule_compliance'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| provider_id = Column(Integer, ForeignKey('providers.id'), nullable=False, index=True)
|
| expected_time = Column(DateTime, nullable=False)
|
| actual_time = Column(DateTime, nullable=True)
|
| delay_seconds = Column(Integer, nullable=True)
|
| on_time = Column(Boolean, default=True)
|
| skip_reason = Column(String(255), nullable=True)
|
| timestamp = Column(DateTime, default=datetime.utcnow)
|
|
|
|
|
| class FailureLog(Base):
|
| """Detailed failure tracking table"""
|
| __tablename__ = 'failure_logs'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
| provider_id = Column(Integer, ForeignKey('providers.id'), nullable=False, index=True)
|
| endpoint = Column(String(500), nullable=False)
|
| error_type = Column(String(100), nullable=False, index=True)
|
| error_message = Column(Text, nullable=True)
|
| http_status = Column(Integer, nullable=True)
|
| retry_attempted = Column(Boolean, default=False)
|
| retry_result = Column(String(100), nullable=True)
|
| remediation_applied = Column(String(255), nullable=True)
|
|
|
|
|
| class Alert(Base):
|
| """Alerts table"""
|
| __tablename__ = 'alerts'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| timestamp = Column(DateTime, default=datetime.utcnow, nullable=False)
|
| provider_id = Column(Integer, ForeignKey('providers.id'), nullable=False)
|
| alert_type = Column(String(100), nullable=False)
|
| severity = Column(String(50), default="medium")
|
| message = Column(Text, nullable=False)
|
| acknowledged = Column(Boolean, default=False)
|
| acknowledged_at = Column(DateTime, nullable=True)
|
|
|
|
|
| class SystemMetrics(Base):
|
| """System-wide metrics table"""
|
| __tablename__ = 'system_metrics'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
| total_providers = Column(Integer, default=0)
|
| online_count = Column(Integer, default=0)
|
| degraded_count = Column(Integer, default=0)
|
| offline_count = Column(Integer, default=0)
|
| avg_response_time_ms = Column(Float, default=0)
|
| total_requests_hour = Column(Integer, default=0)
|
| total_failures_hour = Column(Integer, default=0)
|
| system_health = Column(String(50), default="healthy")
|
|
|
|
|
| class SourcePool(Base):
|
| """Source pools for intelligent rotation"""
|
| __tablename__ = 'source_pools'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| name = Column(String(255), nullable=False, unique=True)
|
| category = Column(String(100), nullable=False)
|
| description = Column(Text, nullable=True)
|
| rotation_strategy = Column(String(50), default="round_robin")
|
| enabled = Column(Boolean, default=True)
|
| created_at = Column(DateTime, default=datetime.utcnow)
|
| updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
|
| pool_members = relationship("PoolMember", back_populates="pool", cascade="all, delete-orphan")
|
| rotation_history = relationship("RotationHistory", back_populates="pool", cascade="all, delete-orphan")
|
|
|
|
|
| class PoolMember(Base):
|
| """Members of source pools"""
|
| __tablename__ = 'pool_members'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| pool_id = Column(Integer, ForeignKey('source_pools.id'), nullable=False, index=True)
|
| provider_id = Column(Integer, ForeignKey('providers.id'), nullable=False, index=True)
|
| priority = Column(Integer, default=1)
|
| weight = Column(Integer, default=1)
|
| enabled = Column(Boolean, default=True)
|
| last_used = Column(DateTime, nullable=True)
|
| use_count = Column(Integer, default=0)
|
| success_count = Column(Integer, default=0)
|
| failure_count = Column(Integer, default=0)
|
| created_at = Column(DateTime, default=datetime.utcnow)
|
|
|
|
|
| pool = relationship("SourcePool", back_populates="pool_members")
|
| provider = relationship("Provider")
|
|
|
|
|
| class RotationHistory(Base):
|
| """History of source rotations"""
|
| __tablename__ = 'rotation_history'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| pool_id = Column(Integer, ForeignKey('source_pools.id'), nullable=False, index=True)
|
| from_provider_id = Column(Integer, ForeignKey('providers.id'), nullable=True, index=True)
|
| to_provider_id = Column(Integer, ForeignKey('providers.id'), nullable=False, index=True)
|
| rotation_reason = Column(String(100), nullable=False)
|
| timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
| success = Column(Boolean, default=True)
|
| notes = Column(Text, nullable=True)
|
|
|
|
|
| pool = relationship("SourcePool", back_populates="rotation_history")
|
| from_provider = relationship("Provider", foreign_keys=[from_provider_id])
|
| to_provider = relationship("Provider", foreign_keys=[to_provider_id])
|
|
|
|
|
| class RotationState(Base):
|
| """Current rotation state for each pool"""
|
| __tablename__ = 'rotation_state'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| pool_id = Column(Integer, ForeignKey('source_pools.id'), nullable=False, unique=True, index=True)
|
| current_provider_id = Column(Integer, ForeignKey('providers.id'), nullable=True)
|
| last_rotation = Column(DateTime, nullable=True)
|
| next_rotation = Column(DateTime, nullable=True)
|
| rotation_count = Column(Integer, default=0)
|
| state_data = Column(Text, nullable=True)
|
| updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
|
| pool = relationship("SourcePool")
|
| current_provider = relationship("Provider")
|
|
|
|
|
|
|
|
|
|
|
|
|
| class MarketPrice(Base):
|
| """Market price data table"""
|
| __tablename__ = 'market_prices'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| symbol = Column(String(20), nullable=False, index=True)
|
| price_usd = Column(Float, nullable=False)
|
| market_cap = Column(Float, nullable=True)
|
| volume_24h = Column(Float, nullable=True)
|
| price_change_24h = Column(Float, nullable=True)
|
| timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
| source = Column(String(100), nullable=False)
|
|
|
|
|
| class NewsArticle(Base):
|
| """News articles table"""
|
| __tablename__ = 'news_articles'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| title = Column(String(500), nullable=False)
|
| content = Column(Text, nullable=True)
|
| source = Column(String(100), nullable=False, index=True)
|
| url = Column(String(1000), nullable=True)
|
| published_at = Column(DateTime, nullable=False, index=True)
|
| sentiment = Column(String(50), nullable=True)
|
| tags = Column(String(500), nullable=True)
|
| created_at = Column(DateTime, default=datetime.utcnow)
|
|
|
|
|
| class WhaleTransaction(Base):
|
| """Whale transactions table"""
|
| __tablename__ = 'whale_transactions'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| blockchain = Column(String(50), nullable=False, index=True)
|
| transaction_hash = Column(String(200), nullable=False, unique=True)
|
| from_address = Column(String(200), nullable=False)
|
| to_address = Column(String(200), nullable=False)
|
| amount = Column(Float, nullable=False)
|
| amount_usd = Column(Float, nullable=False, index=True)
|
| timestamp = Column(DateTime, nullable=False, index=True)
|
| source = Column(String(100), nullable=False)
|
| created_at = Column(DateTime, default=datetime.utcnow)
|
|
|
|
|
| class SentimentMetric(Base):
|
| """Sentiment metrics table"""
|
| __tablename__ = 'sentiment_metrics'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| metric_name = Column(String(100), nullable=False, index=True)
|
| value = Column(Float, nullable=False)
|
| classification = Column(String(50), nullable=False)
|
| timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
| source = Column(String(100), nullable=False)
|
|
|
|
|
| class GasPrice(Base):
|
| """Gas prices table"""
|
| __tablename__ = 'gas_prices'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| blockchain = Column(String(50), nullable=False, index=True)
|
| gas_price_gwei = Column(Float, nullable=False)
|
| fast_gas_price = Column(Float, nullable=True)
|
| standard_gas_price = Column(Float, nullable=True)
|
| slow_gas_price = Column(Float, nullable=True)
|
| timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
| source = Column(String(100), nullable=False)
|
|
|
|
|
| class BlockchainStat(Base):
|
| """Blockchain statistics table"""
|
| __tablename__ = 'blockchain_stats'
|
|
|
| id = Column(Integer, primary_key=True, autoincrement=True)
|
| blockchain = Column(String(50), nullable=False, index=True)
|
| latest_block = Column(Integer, nullable=True)
|
| total_transactions = Column(Integer, nullable=True)
|
| network_hashrate = Column(Float, nullable=True)
|
| difficulty = Column(Float, nullable=True)
|
| timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
| source = Column(String(100), nullable=False)
|
|
|