docs(todo): add task 3 for word deduplication and duplicate prevention
This commit is contained in:
1 parent
2ba78191df
commit
f52820fff6
1 file changed
+23
-12
@@ -47,7 +47,22 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3. 🔌 Пул соединений HTTP (`httpx.AsyncClient` с Keep-Alive)
|
### 3. 🛡️ Дедупликация слов и защита от повторного добавления (Reader + API)
|
||||||
|
- [ ] **Проверка дубликатов на бэкенде (`POST /api/cards`)**:
|
||||||
|
- Проверять наличие слова для пользователя без учёта регистра: `lower(trim(term))`.
|
||||||
|
- При попытке повторного добавления: не создавать дубликат-клон, а дополнять контекстное предложение (если в новой цитате другой контекст) и объединять теги книги (`tags`), возвращая существующую карточку со статусом `already_exists`.
|
||||||
|
- [ ] **Индикация в читалке (Reader Popup)**:
|
||||||
|
- При клике на слово проверять, есть ли уже `cleanTerm` в словаре пользователя.
|
||||||
|
- Если слово уже сохранено: показывать зелёный бейдж `✓ В словаре` вместо активной кнопки `+ В словарь` (предотвращая случайные повторные клики).
|
||||||
|
- Предоставить кнопку «Добавить контекст» для привязки новой цитаты к существующей карточке.
|
||||||
|
- [ ] **Индекс целостности в SQLite**:
|
||||||
|
- Добавить `CREATE INDEX IF NOT EXISTS idx_vocab_user_term_nocase ON vocabulary_cards(user_id, term COLLATE NOCASE);` для мгновенного поиска за $O(\log N)$.
|
||||||
|
- [ ] **Слияние существующих дубликатов в базе**:
|
||||||
|
- Написать безопасную миграцию/скрипт, объединяющий накопившиеся дубликаты (например, `admired`, `suddenly`/`Suddenly` у пользователя `kopri`), объединяя контексты предложений и сохраняя историю повторений SRS.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. 🔌 Пул соединений HTTP (`httpx.AsyncClient` с Keep-Alive)
|
||||||
- [ ] В [`app/dictionary.py`](file:///home/ai-projects/services/study.qpid.pro/app/dictionary.py) создать синглтон-клиент `get_http_client()` с пулом соединений:
|
- [ ] В [`app/dictionary.py`](file:///home/ai-projects/services/study.qpid.pro/app/dictionary.py) создать синглтон-клиент `get_http_client()` с пулом соединений:
|
||||||
```python
|
```python
|
||||||
limits = httpx.Limits(max_keepalive_connections=10, max_connections=20)
|
limits = httpx.Limits(max_keepalive_connections=10, max_connections=20)
|
||||||
@@ -57,7 +72,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 4. 🗄️ Тюнинг SQLite PRAGMA и составных индексов
|
### 5. 🗄️ Тюнинг SQLite PRAGMA и составных индексов
|
||||||
- [ ] В [`app/database.py`](file:///home/ai-projects/services/study.qpid.pro/app/database.py):
|
- [ ] В [`app/database.py`](file:///home/ai-projects/services/study.qpid.pro/app/database.py):
|
||||||
- Вынести `PRAGMA journal_mode=WAL;` в `init_db()` (убрать избыточный вызов при каждом запросе).
|
- Вынести `PRAGMA journal_mode=WAL;` в `init_db()` (убрать избыточный вызов при каждом запросе).
|
||||||
- Включить параметры производительности памяти Linux:
|
- Включить параметры производительности памяти Linux:
|
||||||
@@ -66,22 +81,17 @@
|
|||||||
conn.execute("PRAGMA mmap_size = 268435456;") # 256MB mmap
|
conn.execute("PRAGMA mmap_size = 268435456;") # 256MB mmap
|
||||||
conn.execute("PRAGMA cache_size = -32000;") # 32MB cache
|
conn.execute("PRAGMA cache_size = -32000;") # 32MB cache
|
||||||
```
|
```
|
||||||
- Добавить составной индекс:
|
- [ ] Обеспечить Zero-copy чтение страниц БД ядром Linux.
|
||||||
```sql
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_vocab_user_term_nocase
|
|
||||||
ON vocabulary_cards(user_id, term COLLATE NOCASE);
|
|
||||||
```
|
|
||||||
- [ ] Обеспечить Zero-copy чтение страниц БД ядром Linux и мгновенный поиск дубликатов по пользователю за $O(\log N)$.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5. ✂️ Де-блоатинг внешних парсеров (YAGNI)
|
### 6. ✂️ Де-блоатинг внешних парсеров (YAGNI)
|
||||||
- [ ] Удалить лишний сетевой опрос Datamuse (`fetch_datamuse`) — он дублирует определения и перегружает ответ нерелевантными рифмами.
|
- [ ] Удалить лишний сетевой опрос Datamuse (`fetch_datamuse`) — он дублирует определения и перегружает ответ нерелевантными рифмами.
|
||||||
- [ ] Упростить хрупкий regex-парсинг разметки Wikitext, опираясь на стабильные REST JSON эндпоинты.
|
- [ ] Упростить хрупкий regex-парсинг разметки Wikitext, опираясь на стабильные REST JSON эндпоинты.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6. 📚 Локальный оффлайн-словарь (99%+ покрытия со словоформами, SQLite 10–20 МБ)
|
### 7. 📚 Локальный оффлайн-словарь (99%+ покрытия со словоформами, SQLite 10–20 МБ)
|
||||||
- [ ] Создать в SQLite таблицу:
|
- [ ] Создать в SQLite таблицу:
|
||||||
```sql
|
```sql
|
||||||
CREATE TABLE IF NOT EXISTS offline_dictionary (
|
CREATE TABLE IF NOT EXISTS offline_dictionary (
|
||||||
@@ -103,7 +113,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 7. 🧩 Модульность фронтенда на нативных ES-модулях (без Webpack/Vite)
|
### 8. 🧩 Модульность фронтенда на нативных ES-модулях (без Webpack/Vite)
|
||||||
- [ ] Перевести [`app/static/js/app.js`](file:///home/ai-projects/services/study.qpid.pro/app/static/js/app.js) на нативный браузерный синтаксис `<script type="module">`.
|
- [ ] Перевести [`app/static/js/app.js`](file:///home/ai-projects/services/study.qpid.pro/app/static/js/app.js) на нативный браузерный синтаксис `<script type="module">`.
|
||||||
- [ ] Выделить модули с нативным `import/export`:
|
- [ ] Выделить модули с нативным `import/export`:
|
||||||
- `modules/reader.js` — читалку, блок-парсер и навигацию по главам.
|
- `modules/reader.js` — читалку, блок-парсер и навигацию по главам.
|
||||||
@@ -114,9 +124,10 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 8. 🌐 Быстрый захват из браузера (Bookmarklet)
|
### 9. 🌐 Быстрый захват из браузера (Bookmarklet)
|
||||||
- [ ] Создать JavaScript-букмарклет для добавления слова/фразы из любого окна браузера в личный словарь [`study.qpid.pro`](https://study.qpid.pro).
|
- [ ] Создать JavaScript-букмарклет для добавления слова/фразы из любого окна браузера в личный словарь [`study.qpid.pro`](https://study.qpid.pro).
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⏳ Coming Soon
|
## ⏳ Coming Soon
|
||||||
|
|||||||
Reference in new issue
Block a user