refactor(docs): restructure navigation as state machine
Replaced linear flow diagram with explicit state definitions and transition table. Removes MIGRATION_GUIDE.md (merged into main docs).
This commit is contained in:
@@ -1,111 +0,0 @@
|
||||
# Migration Guide: File-Based to Database Storage
|
||||
|
||||
## Overview
|
||||
|
||||
This guide covers the transition from file-based series metadata storage to the new database-backed system introduced in v2.0.
|
||||
|
||||
## What Changed
|
||||
|
||||
**Before v2.0**: Series metadata stored in `key` and `data` files alongside anime folders.
|
||||
|
||||
**After v2.0**: All metadata stored in SQLite database (`aniworld.db`). Files are deprecated but still supported for backward compatibility during migration.
|
||||
|
||||
## Automated Migration
|
||||
|
||||
The application automatically migrates on first startup:
|
||||
|
||||
1. Scans anime directory for `key` and `data` files
|
||||
2. Parses legacy files into `AnimeSeries` and `Episode` records
|
||||
3. Loads series into in-memory cache
|
||||
4. Logs migration results
|
||||
|
||||
**No manual action required.**
|
||||
|
||||
## Manual Verification
|
||||
|
||||
After first startup with the new version:
|
||||
|
||||
1. **Check logs** for: `"Migrated X series from files to DB"`
|
||||
2. **Verify series count**: UI shows same number of series as before
|
||||
3. **Confirm episodes**: Episode counts match expected totals
|
||||
|
||||
```bash
|
||||
# Check migration log
|
||||
grep "Migrated" logs/app.log
|
||||
|
||||
# Verify series via API
|
||||
curl http://localhost:8000/api/anime | jq '.total'
|
||||
```
|
||||
|
||||
## After Migration
|
||||
|
||||
### Safe to Delete
|
||||
|
||||
Once verified, these files can be removed:
|
||||
|
||||
```
|
||||
<anime_folder>/
|
||||
├── Attack on Titan (2013)/
|
||||
│ ├── key # ❌ Can delete
|
||||
│ ├── data # ❌ Can delete
|
||||
│ └── Season 1/
|
||||
│ └── ...
|
||||
```
|
||||
|
||||
**Deleting these files does not affect the database.** The metadata now lives in `aniworld.db`.
|
||||
|
||||
### Backup (Recommended)
|
||||
|
||||
Before deleting, backup the files:
|
||||
|
||||
```bash
|
||||
# Create backup directory
|
||||
mkdir -p backup/legacy_series_files
|
||||
|
||||
# Copy all key and data files
|
||||
find /path/to/anime -name "key" -o -name "data" | while read f; do
|
||||
cp "$f" "backup/legacy_series_files/"
|
||||
done
|
||||
```
|
||||
|
||||
## Reverting (Not Recommended)
|
||||
|
||||
If you must revert to file-based storage:
|
||||
|
||||
1. **Restore from database backup** (if available)
|
||||
2. **Export manually** (no export script exists)
|
||||
|
||||
**Warning**: File-based storage is deprecated and will be removed in v3.0.0.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Series Not Appearing After Migration
|
||||
|
||||
1. Check logs for migration errors: `grep -i error logs/app.log`
|
||||
2. Verify `key` and `data` files exist and are readable
|
||||
3. Manually trigger rescan: `POST /api/scheduler/trigger-rescan`
|
||||
|
||||
### Duplicate Series
|
||||
|
||||
1. Check for duplicate `key` files (same series in multiple folders)
|
||||
2. Verify series key uniqueness in database:
|
||||
|
||||
```bash
|
||||
sqlite3 aniworld.db "SELECT key, COUNT(*) FROM anime_series GROUP BY key HAVING COUNT(*) > 1;"
|
||||
```
|
||||
|
||||
### Missing Episodes
|
||||
|
||||
1. Trigger targeted scan for affected series
|
||||
2. Check episode sync logs
|
||||
3. Verify file permissions on anime directory
|
||||
|
||||
## Deprecation Timeline
|
||||
|
||||
| Version | Status |
|
||||
|---------|--------|
|
||||
| v2.0.x | Legacy files supported, migration automated |
|
||||
| v2.1.x | Legacy files still supported, warnings in logs |
|
||||
| v3.0.0 | **Legacy files removed** - database only |
|
||||
|
||||
Upgrade to v3.0.0 before legacy file support ends.
|
||||
@@ -4,54 +4,56 @@ This document describes the setup flow navigation, covering how users progress f
|
||||
|
||||
## Overview
|
||||
|
||||
The application uses a middleware-based redirect system to ensure users complete setup before accessing the main app. The flow involves multiple pages handling setup completion, unresolved folder detection, and initialization.
|
||||
The application uses a middleware-based redirect system to enforce a strict state machine. Users must complete each phase before accessing the next. Attempting to bypass the current phase redirects to the appropriate page.
|
||||
|
||||
## Setup Flow
|
||||
## State Machine
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ SETUP FLOW │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ NAVIGATION STATES │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ /setup ──► /loading ──► /setup/unresolved ──► /loading ──► /login │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ ▼ ▼ ▼ ▼ │
|
||||
│ (first (Series Scan + (has folders) (all resolved) │
|
||||
│ time) NFO Scan) │ │
|
||||
│ │ │ │
|
||||
│ │ │ │
|
||||
│ │ ▼ │
|
||||
│ │ [Done button] ──► marks complete │
|
||||
│ │ │ │
|
||||
│ │ ▼ │
|
||||
│ │ /loading (NFO phase runs again) │
|
||||
│ │ │ │
|
||||
│ └────────┴─────────────────────────────────────┘
|
||||
│ NO_SETUP ──────────► SETUP_COMPLETE ──────────► UNRESOLVED_PENDING │
|
||||
│ │ │ │ │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ /setup /loading /setup/unresolved │
|
||||
│ (series scan) (resolve folders) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
│ UNRESOLVED_DONE ───────┐
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ NFO_SCAN_PENDING │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ /loading │
|
||||
│ (NFO scan) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ COMPLETE │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ /login │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**New Navigation Order:**
|
||||
1. `/setup` → Initial configuration
|
||||
2. `/loading` → Series scan + NFO scan
|
||||
3. `/setup/unresolved` → Resolve folders (if any)
|
||||
4. `/loading` → NFO scan runs again
|
||||
5. `/login` → Authentication
|
||||
## State Definitions
|
||||
|
||||
**Key Changes:**
|
||||
- After `/setup/unresolved`, the "Done" button marks the phase as complete
|
||||
- Revisiting `/setup/unresolved` after completion → redirects to `/loading`
|
||||
- `/loading` always goes to `/setup/unresolved` if unresolved folders exist
|
||||
- NFO scan runs as a separate phase after series sync during initialization
|
||||
| State | Condition | Target Page |
|
||||
|-------|-----------|-------------|
|
||||
| `NO_SETUP` | No master password configured | `/setup` |
|
||||
| `SETUP_COMPLETE` | Initial config passed, loading not started | `/loading` |
|
||||
| `UNRESOLVED_PENDING` | Setup done, unresolved exist, not marked done | `/setup/unresolved` |
|
||||
| `UNRESOLVED_DONE` | Unresolved phase marked complete, NFO scan pending | `/loading` |
|
||||
| `NFO_SCAN_PENDING` | Unresolved done, NFO scan incomplete | `/loading` |
|
||||
| `COMPLETE` | All phases finished | `/login` |
|
||||
|
||||
## Middleware: SetupRedirectMiddleware
|
||||
|
||||
**File:** `src/server/middleware/setup_redirect.py`
|
||||
|
||||
The middleware intercepts all requests and redirects to `/setup` if:
|
||||
- No master password is configured
|
||||
- Configuration file is missing or invalid
|
||||
The middleware intercepts all requests and enforces the state machine.
|
||||
|
||||
### Exempt Paths (always accessible)
|
||||
|
||||
@@ -68,13 +70,47 @@ The middleware intercepts all requests and redirects to `/setup` if:
|
||||
|
||||
### Middleware Logic
|
||||
|
||||
1. **Setup incomplete** → Redirect to `/setup`
|
||||
2. **Setup complete, accessing `/setup`** → Redirect to `/login`
|
||||
3. **Setup complete, accessing `/loading`** → Allow access (page handles its own redirect)
|
||||
4. **Setup complete, accessing `/setup/unresolved`**:
|
||||
- If `unresolved_completed` flag is set → Redirect to `/loading`
|
||||
- Otherwise → Allow access
|
||||
5. **API requests during setup** → Return 503 with `setup_url`
|
||||
The middleware checks the current state and redirects accordingly:
|
||||
|
||||
```
|
||||
1. NO_SETUP state:
|
||||
→ Redirect ALL requests to /setup
|
||||
→ Exception: /setup itself is accessible
|
||||
|
||||
2. SETUP_COMPLETE state:
|
||||
→ Redirect /setup to /loading
|
||||
→ Redirect any other page to /loading
|
||||
|
||||
3. UNRESOLVED_PENDING state (unresolved folders exist, not marked done):
|
||||
→ Redirect /setup to /setup/unresolved
|
||||
→ Redirect /loading to /setup/unresolved
|
||||
→ Allow access to /setup/unresolved
|
||||
→ Redirect any other page to /setup/unresolved
|
||||
|
||||
4. UNRESOLVED_DONE state (unresolved marked done, NFO scan pending):
|
||||
→ Redirect /setup to /loading
|
||||
→ Redirect /setup/unresolved to /loading
|
||||
→ Redirect any other page to /loading
|
||||
|
||||
5. NFO_SCAN_PENDING state:
|
||||
→ Redirect /setup to /loading
|
||||
→ Redirect /setup/unresolved to /loading
|
||||
→ Allow access to /loading (NFO phase runs)
|
||||
→ Redirect any other page to /loading
|
||||
|
||||
6. COMPLETE state (loading finished):
|
||||
→ Redirect /setup, /loading, /setup/unresolved to /login
|
||||
→ Allow access to /login and main app
|
||||
```
|
||||
|
||||
### Phase Tracking Flags
|
||||
|
||||
| Flag | Purpose |
|
||||
|------|---------|
|
||||
| `setup_complete` | Initial configuration was saved |
|
||||
| `unresolved_completed` | User clicked "Done" on unresolved page |
|
||||
| `loading_complete` | Series scan + initial loading finished |
|
||||
| `nfo_scan_complete` | Final NFO scan finished |
|
||||
|
||||
## Pages
|
||||
|
||||
@@ -87,8 +123,11 @@ Handles initial configuration:
|
||||
- Anime directory selection
|
||||
- Database initialization
|
||||
|
||||
**Post-completion flow:**
|
||||
- Redirects to `/loading` to begin initialization
|
||||
**Allowed in states:** `NO_SETUP`
|
||||
|
||||
**Post-completion:**
|
||||
- Sets `setup_complete` flag
|
||||
- Redirects to `/loading`
|
||||
|
||||
### 2. Loading Page (`/loading`)
|
||||
|
||||
@@ -99,25 +138,28 @@ Shows initialization progress via WebSocket:
|
||||
- Database population
|
||||
- Logo/image loading
|
||||
|
||||
**Post-initialization flow:**
|
||||
**Allowed in states:** `SETUP_COMPLETE`, `UNRESOLVED_DONE`, `NFO_SCAN_PENDING`
|
||||
|
||||
**Post-initialization (series scan complete):**
|
||||
```javascript
|
||||
async function checkUnresolvedAndProceed() {
|
||||
// Fetch unresolved folders via API
|
||||
const res = await fetch('/api/setup/unresolved', {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
});
|
||||
const folders = await res.json();
|
||||
|
||||
if (folders.length > 0) {
|
||||
// Has unresolved folders → go to resolution page
|
||||
window.location.href = '/setup/unresolved';
|
||||
} else {
|
||||
// No unresolved folders → go to login
|
||||
window.location.href = '/login';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Post-NFO scan:**
|
||||
- Sets `nfo_scan_complete` flag
|
||||
- Redirects to `/login`
|
||||
|
||||
### 3. Unresolved Folders Page (`/setup/unresolved`)
|
||||
|
||||
**File:** `src/server/web/templates/unresolved.html`
|
||||
@@ -127,24 +169,16 @@ Allows manual resolution of folders that couldn't be auto-matched:
|
||||
- Provides search suggestions
|
||||
- Input field for entering provider key
|
||||
- Resolve/delete actions
|
||||
- **Done button** at top to complete the phase without resolving all folders
|
||||
- **Done button** to complete the phase without resolving all folders
|
||||
|
||||
**Post-resolution flow:**
|
||||
```javascript
|
||||
// After clicking "Done" button
|
||||
async function handleDone() {
|
||||
// Call API to mark phase as complete
|
||||
await fetch('/api/setup/unresolved/done', { method: 'POST' });
|
||||
// Redirect to loading for final NFO scan
|
||||
window.location.href = '/loading';
|
||||
}
|
||||
```
|
||||
**Allowed in states:** `UNRESOLVED_PENDING`
|
||||
|
||||
**Done button behavior:**
|
||||
- Marks all remaining folders as handled
|
||||
- Sets `unresolved_completed` flag in config
|
||||
- Redirects to `/loading` to run final NFO scan
|
||||
- After completion, `/setup/unresolved` becomes inaccessible (redirects to `/loading`)
|
||||
- Sets `unresolved_completed` flag
|
||||
- Redirects to `/loading` for final NFO scan
|
||||
|
||||
**After completion:**
|
||||
- Any access redirects to `/loading`
|
||||
|
||||
### 4. Login Page (`/login`)
|
||||
|
||||
@@ -152,6 +186,8 @@ async function handleDone() {
|
||||
|
||||
Authentication page. After successful login → redirect to `/` (main app).
|
||||
|
||||
**Allowed in states:** `COMPLETE`
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Unresolved Folders API
|
||||
@@ -177,7 +213,7 @@ Authentication page. After successful login → redirect to `/` (main app).
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `src/server/middleware/setup_redirect.py` | Redirect middleware |
|
||||
| `src/server/middleware/setup_redirect.py` | Redirect middleware (state machine) |
|
||||
| `src/server/controllers/page_controller.py` | Page route handlers |
|
||||
| `src/server/web/templates/setup.html` | Setup template |
|
||||
| `src/server/web/templates/loading.html` | Loading template |
|
||||
@@ -185,22 +221,13 @@ Authentication page. After successful login → redirect to `/` (main app).
|
||||
| `src/server/api/setup_endpoints.py` | Unresolved folders API |
|
||||
| `src/server/database/service.py` | UnresolvedFolderService |
|
||||
|
||||
## Common Issues
|
||||
## Navigation Summary
|
||||
|
||||
### Redirect Loop
|
||||
|
||||
**Symptom:** Browser keeps redirecting between pages.
|
||||
|
||||
**Causes:**
|
||||
1. `loading.html` always redirected to `/setup/unresolved` without checking if any exist
|
||||
2. `unresolved.html` redirected to `/` which middleware redirected back to `/login`
|
||||
|
||||
**Fix:** See the navigation logic updates in loading.html and unresolved.html.
|
||||
|
||||
### Can't Access Unresolved Page After Setup
|
||||
|
||||
**Symptom:** Middleware redirects to `/login` instead of allowing access to `/setup/unresolved`.
|
||||
|
||||
**Cause:** `/setup/unresolved` is in the exempt paths but the request may not be reaching it due to completion check timing.
|
||||
|
||||
**Fix:** The middleware allows access to `/loading` which handles the redirect to `/setup/unresolved` after initialization.
|
||||
| Current State | Access `/setup` | Access `/loading` | Access `/setup/unresolved` |
|
||||
|--------------|-----------------|-------------------|---------------------------|
|
||||
| NO_SETUP | ✅ Allowed | ❌ → `/setup` | ❌ → `/setup` |
|
||||
| SETUP_COMPLETE | ❌ → `/loading` | ✅ Allowed | ❌ → `/loading` |
|
||||
| UNRESOLVED_PENDING | ❌ → `/setup/unresolved` | ❌ → `/setup/unresolved` | ✅ Allowed |
|
||||
| UNRESOLVED_DONE | ❌ → `/loading` | ✅ Allowed (NFO phase) | ❌ → `/loading` |
|
||||
| NFO_SCAN_PENDING | ❌ → `/loading` | ✅ Allowed (NFO phase) | ❌ → `/loading` |
|
||||
| COMPLETE | ❌ → `/login` | ❌ → `/login` | ❌ → `/login` |
|
||||
Reference in New Issue
Block a user