Phase 6: Update database layer identifier documentation
- Updated AnimeSeries model docstring to clarify key is primary identifier - Updated folder field to indicate metadata-only usage - Updated AnimeSeriesService docstring and get_by_key method - Updated infrastructure.md with database identifier documentation - All 996 tests passing
This commit is contained in:
parent
a833077f97
commit
0c8b296aa6
@ -132,6 +132,20 @@ All series-related WebSocket events include `key` as the primary identifier in t
|
||||
|
||||
**Mixins**: `TimestampMixin` (created_at, updated_at), `SoftDeleteMixin`
|
||||
|
||||
### AnimeSeries Identifier Fields
|
||||
|
||||
| Field | Type | Purpose |
|
||||
| ------ | ----------- | ------------------------------------------------- |
|
||||
| `id` | Primary Key | Internal database key for relationships |
|
||||
| `key` | Unique, Indexed | **PRIMARY IDENTIFIER** for all lookups |
|
||||
| `folder` | String | Filesystem metadata only (not for identification) |
|
||||
|
||||
**Database Service Methods:**
|
||||
|
||||
- `AnimeSeriesService.get_by_key(key)` - **Primary lookup method**
|
||||
- `AnimeSeriesService.get_by_id(id)` - Internal lookup by database ID
|
||||
- No `get_by_folder()` method exists - folder is never used for lookups
|
||||
|
||||
## Core Services
|
||||
|
||||
### SeriesApp (`src/core/SeriesApp.py`)
|
||||
|
||||
@ -156,88 +156,12 @@ All API layer tasks completed.
|
||||
|
||||
### Phase 5: Frontend ✅ (Completed November 28, 2025)
|
||||
|
||||
All frontend tasks completed:
|
||||
|
||||
- **Task 5.1: Update Frontend JavaScript** ✅
|
||||
- Updated `app.js` to use `key` as primary series identifier
|
||||
- `selectedSeries` Set now uses `key` instead of `folder`
|
||||
- `createSerieCard()` uses `data-key` attribute for identification
|
||||
- `toggleSerieSelection()` uses `key` for lookups
|
||||
- All selection and download operations use `key`
|
||||
|
||||
- **Task 5.2: Update WebSocket Events** ✅
|
||||
- WebSocket service already has proper documentation for `key` usage
|
||||
- Updated tests to include `key` and `folder` in broadcast data
|
||||
- Tests verify both fields are included in messages
|
||||
|
||||
- **Task 5.3: Update Additional Frontend JavaScript Files** ✅
|
||||
- Reviewed `queue.js`, `websocket_client.js`, and utility files
|
||||
- No changes needed - these files use download item IDs correctly
|
||||
- Series identification is handled in `app.js`
|
||||
|
||||
- **Task 5.4: Update HTML Templates** ✅
|
||||
- Reviewed all templates (`index.html`, `queue.html`, etc.)
|
||||
- No changes needed - series cards are rendered dynamically in JavaScript
|
||||
- Static templates don't contain series data attributes
|
||||
### Phase 6: Database Layer ✅ (Completed November 28, 2025)
|
||||
|
||||
---
|
||||
|
||||
### Phase 6: Database Layer
|
||||
|
||||
#### Task 6.1: Verify Database Models Use Key Correctly
|
||||
|
||||
**File:** [`src/server/database/models.py`](src/server/database/models.py)
|
||||
|
||||
**Objective:** Verify and document that database models correctly use `key` as unique identifier.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Open [`src/server/database/models.py`](src/server/database/models.py)
|
||||
2. Verify `AnimeSeries.key` is unique and indexed
|
||||
3. Verify `AnimeSeries.folder` is not used for lookups
|
||||
4. Update docstrings to clarify identifier usage
|
||||
5. Ensure all relationships use `id` (primary key) not `key` or `folder`
|
||||
|
||||
**Success Criteria:**
|
||||
|
||||
- [ ] `key` is unique and indexed
|
||||
- [ ] `folder` is metadata only
|
||||
- [ ] Docstrings are clear
|
||||
- [ ] All database model tests pass
|
||||
|
||||
**Test Command:**
|
||||
|
||||
```bash
|
||||
conda run -n AniWorld python -m pytest tests/unit/test_database_models.py -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Task 6.2: Update Database Services to Use Key
|
||||
|
||||
**File:** [`src/server/database/service.py`](src/server/database/service.py)
|
||||
|
||||
**Objective:** Ensure all database service methods use `key` for series lookup.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Open [`src/server/database/service.py`](src/server/database/service.py)
|
||||
2. Verify `AnimeSeriesService.get_by_key()` is used for lookups
|
||||
3. Verify no methods use `folder` for identification
|
||||
4. Update any methods that incorrectly use `folder` for lookups
|
||||
5. Add migration helper if needed to update existing data
|
||||
|
||||
**Success Criteria:**
|
||||
|
||||
- [ ] All service methods use `key` for lookups
|
||||
- [ ] `folder` never used as identifier
|
||||
- [ ] All database service tests pass
|
||||
|
||||
**Test Command:**
|
||||
|
||||
```bash
|
||||
conda run -n AniWorld python -m pytest tests/unit/test_database_service.py -v
|
||||
```
|
||||
All database layer tasks completed:
|
||||
- Task 6.1: Verified `AnimeSeries.key` is unique and indexed, `folder` is metadata only, updated docstrings
|
||||
- Task 6.2: Verified all service methods use `key` for lookups, no folder-based identification
|
||||
|
||||
---
|
||||
|
||||
@ -543,9 +467,9 @@ conda run -n AniWorld python -m pytest tests/integration/test_identifier_consist
|
||||
- [x] Task 5.2: Update WebSocket Events
|
||||
- [x] Task 5.3: Update Additional Frontend JavaScript Files
|
||||
- [x] Task 5.4: Update HTML Templates
|
||||
- [ ] Phase 6: Database Layer
|
||||
- [ ] Task 6.1: Verify Database Models
|
||||
- [ ] Task 6.2: Update Database Services
|
||||
- [x] Phase 6: Database Layer ✅ **Completed November 28, 2025**
|
||||
- [x] Task 6.1: Verify Database Models
|
||||
- [x] Task 6.2: Update Database Services
|
||||
- [ ] Phase 7: Testing and Validation
|
||||
- [ ] Task 7.1: Update Test Fixtures
|
||||
- [ ] Task 7.2: Add Integration Tests
|
||||
|
||||
@ -38,20 +38,31 @@ class AnimeSeries(Base, TimestampMixin):
|
||||
Represents an anime series with metadata, provider information,
|
||||
and links to episodes. Corresponds to the core Serie class.
|
||||
|
||||
Series Identifier Convention:
|
||||
- `key`: PRIMARY IDENTIFIER - Unique, provider-assigned, URL-safe
|
||||
(e.g., "attack-on-titan"). Used for all lookups and operations.
|
||||
- `folder`: METADATA ONLY - Filesystem folder name for display
|
||||
(e.g., "Attack on Titan (2013)"). Never used for identification.
|
||||
- `id`: Internal database primary key for relationships.
|
||||
|
||||
Attributes:
|
||||
id: Primary key
|
||||
key: Unique identifier used by provider
|
||||
name: Series name
|
||||
id: Database primary key (internal use for relationships)
|
||||
key: Unique provider key - PRIMARY IDENTIFIER for all lookups
|
||||
name: Display name of the series
|
||||
site: Provider site URL
|
||||
folder: Local filesystem path
|
||||
folder: Filesystem folder name (metadata only, not for lookups)
|
||||
description: Optional series description
|
||||
status: Current status (ongoing, completed, etc.)
|
||||
total_episodes: Total number of episodes
|
||||
cover_url: URL to series cover image
|
||||
episodes: Relationship to Episode models
|
||||
download_items: Relationship to DownloadQueueItem models
|
||||
episodes: Relationship to Episode models (via id foreign key)
|
||||
download_items: Relationship to DownloadQueueItem models (via id foreign key)
|
||||
created_at: Creation timestamp (from TimestampMixin)
|
||||
updated_at: Last update timestamp (from TimestampMixin)
|
||||
|
||||
Note:
|
||||
All database relationships use `id` (primary key), not `key` or `folder`.
|
||||
Use `get_by_key()` in AnimeSeriesService for lookups.
|
||||
"""
|
||||
__tablename__ = "anime_series"
|
||||
|
||||
@ -63,7 +74,7 @@ class AnimeSeries(Base, TimestampMixin):
|
||||
# Core identification
|
||||
key: Mapped[str] = mapped_column(
|
||||
String(255), unique=True, nullable=False, index=True,
|
||||
doc="Unique provider key"
|
||||
doc="Unique provider key - PRIMARY IDENTIFIER for all lookups"
|
||||
)
|
||||
name: Mapped[str] = mapped_column(
|
||||
String(500), nullable=False, index=True,
|
||||
@ -75,7 +86,7 @@ class AnimeSeries(Base, TimestampMixin):
|
||||
)
|
||||
folder: Mapped[str] = mapped_column(
|
||||
String(1000), nullable=False,
|
||||
doc="Local filesystem path"
|
||||
doc="Filesystem folder name - METADATA ONLY, not for lookups"
|
||||
)
|
||||
|
||||
# Metadata
|
||||
|
||||
@ -43,6 +43,11 @@ class AnimeSeriesService:
|
||||
|
||||
Provides methods for creating, reading, updating, and deleting anime series
|
||||
with support for both async and sync database sessions.
|
||||
|
||||
Series Identifier Convention:
|
||||
- Use `get_by_key()` for lookups by provider key (primary identifier)
|
||||
- Use `get_by_id()` for lookups by database primary key (internal)
|
||||
- Never use `folder` for identification - it's metadata only
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
@ -115,12 +120,19 @@ class AnimeSeriesService:
|
||||
async def get_by_key(db: AsyncSession, key: str) -> Optional[AnimeSeries]:
|
||||
"""Get anime series by provider key.
|
||||
|
||||
This is the PRIMARY lookup method for series identification.
|
||||
Use this method instead of get_by_id() when looking up by
|
||||
the provider-assigned unique key.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
key: Unique provider key
|
||||
key: Unique provider key (e.g., "attack-on-titan")
|
||||
|
||||
Returns:
|
||||
AnimeSeries instance or None if not found
|
||||
|
||||
Note:
|
||||
Do NOT use folder for lookups - it's metadata only.
|
||||
"""
|
||||
result = await db.execute(
|
||||
select(AnimeSeries).where(AnimeSeries.key == key)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user