Coverage for src / local_deep_research / library / download_management / models / __init__.py: 97%
39 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-14 23:55 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-14 23:55 +0000
1"""
2Database Models for Download Management
4Contains ORM models for tracking resource download status and retry logic.
5"""
7from datetime import UTC, datetime
8from enum import Enum
9from functools import partial
10from typing import Optional
12from sqlalchemy import DateTime, Integer, String, Text
13from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
16class Base(DeclarativeBase):
17 pass
20class FailureType(str, Enum):
21 """Enum for failure types - ensures consistency across the codebase"""
23 NOT_FOUND = "not_found"
24 FORBIDDEN = "forbidden"
25 GONE = "gone"
26 RATE_LIMITED = "rate_limited"
27 SERVER_ERROR = "server_error"
28 RECAPTCHA_PROTECTION = "recaptcha_protection"
29 INCOMPATIBLE_FORMAT = "incompatible_format"
30 TIMEOUT = "timeout"
31 NETWORK_ERROR = "network_error"
32 UNKNOWN_ERROR = "unknown_error"
35class DownloadStatus(str, Enum):
36 """Status values for resource download tracking."""
38 AVAILABLE = "available"
39 TEMPORARILY_FAILED = "temporarily_failed"
40 PERMANENTLY_FAILED = "permanently_failed"
43class ResourceDownloadStatus(Base):
44 """Database model for tracking resource download status"""
46 __tablename__ = "resource_download_status"
48 id: Mapped[int] = mapped_column(Integer, primary_key=True)
49 resource_id: Mapped[int] = mapped_column(
50 Integer, unique=True, nullable=False, index=True
51 )
53 # Status tracking
54 status: Mapped[str] = mapped_column(
55 String(50), nullable=False, default="available"
56 ) # available, temporarily_failed, permanently_failed
57 failure_type: Mapped[Optional[str]] = mapped_column(
58 String(100), nullable=True
59 ) # not_found, rate_limited, timeout, etc.
60 failure_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
62 # Retry timing
63 retry_after_timestamp: Mapped[Optional[datetime]] = mapped_column(
64 DateTime, nullable=True
65 ) # When this can be retried (NULL = permanent)
66 last_attempt_at: Mapped[Optional[datetime]] = mapped_column(
67 DateTime, nullable=True
68 )
69 permanent_failure_at: Mapped[Optional[datetime]] = mapped_column(
70 DateTime, nullable=True
71 ) # When permanently failed
73 # Statistics
74 total_retry_count: Mapped[int] = mapped_column(Integer, default=0)
75 today_retry_count: Mapped[int] = mapped_column(Integer, default=0)
77 # Timestamps
78 created_at: Mapped[Optional[datetime]] = mapped_column(
79 DateTime, default=partial(datetime.now, UTC)
80 )
81 updated_at: Mapped[Optional[datetime]] = mapped_column(
82 DateTime,
83 default=partial(datetime.now, UTC),
84 onupdate=partial(datetime.now, UTC),
85 )
87 def __repr__(self) -> str:
88 return f"<ResourceDownloadStatus(resource_id={self.resource_id}, status='{self.status}', failure_type='{self.failure_type}')>"