Coverage for src / local_deep_research / database / models / active_research.py: 94%
17 statements
« prev ^ index » next coverage.py v7.12.0, created at 2026-01-11 00:51 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2026-01-11 00:51 +0000
1"""
2Model for tracking active research processes per user.
4As noted by djpetti: "Is there a reason this isn't in `models.py`?"
5Response: The codebase follows a domain-driven organization where models are
6separated into individual files by functionality (auth.py, cache.py, research.py, etc.)
7rather than a single models.py file. This provides better maintainability and follows
8the established pattern in the models/ directory.
9"""
11from sqlalchemy import JSON, Boolean, Column, Index, Integer, String
12from sqlalchemy_utc import UtcDateTime, utcnow
14from .base import Base
17class UserActiveResearch(Base):
18 """
19 Track active research processes for each user.
20 Allows multiple concurrent researches per user.
21 """
23 __tablename__ = "user_active_researches"
25 # Composite primary key: username + research_id
26 username = Column(String(100), primary_key=True)
27 research_id = Column(String(36), primary_key=True) # UUID
29 # Status tracking
30 status = Column(String(50), default="in_progress")
31 started_at = Column(UtcDateTime, server_default=utcnow(), nullable=False)
32 last_heartbeat = Column(
33 UtcDateTime, server_default=utcnow(), nullable=False
34 )
36 # Process information
37 thread_id = Column(String(100)) # Thread identifier
38 pid = Column(Integer) # Process ID if using multiprocessing
40 # Settings snapshot
41 settings_snapshot = Column(JSON) # Complete settings used for this research
43 # Termination flag
44 termination_requested = Column(Boolean, default=False)
46 # Indexes for performance
47 __table_args__ = (
48 Index("idx_user_active_research", "username", "status"),
49 Index("idx_research_heartbeat", "last_heartbeat"),
50 )
52 def __repr__(self):
53 return f"<UserActiveResearch(user='{self.username}', research='{self.research_id}', status='{self.status}')>"