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`
|
**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
|
## Core Services
|
||||||
|
|
||||||
### SeriesApp (`src/core/SeriesApp.py`)
|
### SeriesApp (`src/core/SeriesApp.py`)
|
||||||
|
|||||||
@ -156,88 +156,12 @@ All API layer tasks completed.
|
|||||||
|
|
||||||
### Phase 5: Frontend ✅ (Completed November 28, 2025)
|
### Phase 5: Frontend ✅ (Completed November 28, 2025)
|
||||||
|
|
||||||
All frontend tasks completed:
|
|
||||||
|
|
||||||
- **Task 5.1: Update Frontend JavaScript** ✅
|
### Phase 6: Database Layer ✅ (Completed November 28, 2025)
|
||||||
- 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** ✅
|
All database layer tasks completed:
|
||||||
- WebSocket service already has proper documentation for `key` usage
|
- Task 6.1: Verified `AnimeSeries.key` is unique and indexed, `folder` is metadata only, updated docstrings
|
||||||
- Updated tests to include `key` and `folder` in broadcast data
|
- Task 6.2: Verified all service methods use `key` for lookups, no folder-based identification
|
||||||
- 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
|
|
||||||
|
|
||||||
#### 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
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -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.2: Update WebSocket Events
|
||||||
- [x] Task 5.3: Update Additional Frontend JavaScript Files
|
- [x] Task 5.3: Update Additional Frontend JavaScript Files
|
||||||
- [x] Task 5.4: Update HTML Templates
|
- [x] Task 5.4: Update HTML Templates
|
||||||
- [ ] Phase 6: Database Layer
|
- [x] Phase 6: Database Layer ✅ **Completed November 28, 2025**
|
||||||
- [ ] Task 6.1: Verify Database Models
|
- [x] Task 6.1: Verify Database Models
|
||||||
- [ ] Task 6.2: Update Database Services
|
- [x] Task 6.2: Update Database Services
|
||||||
- [ ] Phase 7: Testing and Validation
|
- [ ] Phase 7: Testing and Validation
|
||||||
- [ ] Task 7.1: Update Test Fixtures
|
- [ ] Task 7.1: Update Test Fixtures
|
||||||
- [ ] Task 7.2: Add Integration Tests
|
- [ ] Task 7.2: Add Integration Tests
|
||||||
|
|||||||
@ -38,20 +38,31 @@ class AnimeSeries(Base, TimestampMixin):
|
|||||||
Represents an anime series with metadata, provider information,
|
Represents an anime series with metadata, provider information,
|
||||||
and links to episodes. Corresponds to the core Serie class.
|
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:
|
Attributes:
|
||||||
id: Primary key
|
id: Database primary key (internal use for relationships)
|
||||||
key: Unique identifier used by provider
|
key: Unique provider key - PRIMARY IDENTIFIER for all lookups
|
||||||
name: Series name
|
name: Display name of the series
|
||||||
site: Provider site URL
|
site: Provider site URL
|
||||||
folder: Local filesystem path
|
folder: Filesystem folder name (metadata only, not for lookups)
|
||||||
description: Optional series description
|
description: Optional series description
|
||||||
status: Current status (ongoing, completed, etc.)
|
status: Current status (ongoing, completed, etc.)
|
||||||
total_episodes: Total number of episodes
|
total_episodes: Total number of episodes
|
||||||
cover_url: URL to series cover image
|
cover_url: URL to series cover image
|
||||||
episodes: Relationship to Episode models
|
episodes: Relationship to Episode models (via id foreign key)
|
||||||
download_items: Relationship to DownloadQueueItem models
|
download_items: Relationship to DownloadQueueItem models (via id foreign key)
|
||||||
created_at: Creation timestamp (from TimestampMixin)
|
created_at: Creation timestamp (from TimestampMixin)
|
||||||
updated_at: Last update 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"
|
__tablename__ = "anime_series"
|
||||||
|
|
||||||
@ -63,7 +74,7 @@ class AnimeSeries(Base, TimestampMixin):
|
|||||||
# Core identification
|
# Core identification
|
||||||
key: Mapped[str] = mapped_column(
|
key: Mapped[str] = mapped_column(
|
||||||
String(255), unique=True, nullable=False, index=True,
|
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(
|
name: Mapped[str] = mapped_column(
|
||||||
String(500), nullable=False, index=True,
|
String(500), nullable=False, index=True,
|
||||||
@ -75,7 +86,7 @@ class AnimeSeries(Base, TimestampMixin):
|
|||||||
)
|
)
|
||||||
folder: Mapped[str] = mapped_column(
|
folder: Mapped[str] = mapped_column(
|
||||||
String(1000), nullable=False,
|
String(1000), nullable=False,
|
||||||
doc="Local filesystem path"
|
doc="Filesystem folder name - METADATA ONLY, not for lookups"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Metadata
|
# Metadata
|
||||||
|
|||||||
@ -43,6 +43,11 @@ class AnimeSeriesService:
|
|||||||
|
|
||||||
Provides methods for creating, reading, updating, and deleting anime series
|
Provides methods for creating, reading, updating, and deleting anime series
|
||||||
with support for both async and sync database sessions.
|
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
|
@staticmethod
|
||||||
@ -115,12 +120,19 @@ class AnimeSeriesService:
|
|||||||
async def get_by_key(db: AsyncSession, key: str) -> Optional[AnimeSeries]:
|
async def get_by_key(db: AsyncSession, key: str) -> Optional[AnimeSeries]:
|
||||||
"""Get anime series by provider key.
|
"""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:
|
Args:
|
||||||
db: Database session
|
db: Database session
|
||||||
key: Unique provider key
|
key: Unique provider key (e.g., "attack-on-titan")
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
AnimeSeries instance or None if not found
|
AnimeSeries instance or None if not found
|
||||||
|
|
||||||
|
Note:
|
||||||
|
Do NOT use folder for lookups - it's metadata only.
|
||||||
"""
|
"""
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(AnimeSeries).where(AnimeSeries.key == key)
|
select(AnimeSeries).where(AnimeSeries.key == key)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user