mirror of
https://gitverse.ru/kpa39l/email-assistant.git
synced 2026-09-29 09:15:09 +00:00
docs: анализ формата хранения ФС vs Maildir (задача 4)
- STORAGE_ANALYSIS.md: сравнение email.md / Maildir / MBOX / notmuch по 7 критериям; рекомендация — остаться на email.md + добавить tags в frontmatter + опциональный экспорт в Maildir - README.md: ссылка на анализ в разделе «Оценка альтернатив» - Данные не изменены (4884 email.md до и после)
This commit is contained in:
@@ -11,3 +11,4 @@
|
|||||||
## Оценка альтернатив
|
## Оценка альтернатив
|
||||||
|
|
||||||
- [Анализ Nylas CLI](NYLAS_ANALYSIS.md) — почему Nylas **не подходит** для локального архива (2026-09-11)
|
- [Анализ Nylas CLI](NYLAS_ANALYSIS.md) — почему Nylas **не подходит** для локального архива (2026-09-11)
|
||||||
|
- [Анализ формата хранения: ФС vs Maildir](STORAGE_ANALYSIS.md) — почему текущий формат удобнее Maildir для локальной LLM (2026-09-11)
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
# Анализ хранения писем: Файловая система vs Maildir
|
||||||
|
|
||||||
|
**Дата:** 2026-09-11
|
||||||
|
**Статус:** Анализ (не миграция). Данные не изменены.
|
||||||
|
**Мотивация:** использовать локальную нейросеть (Qwen3:8b, Ollama) как
|
||||||
|
инструмент в обычных скриптах — без облака и трат.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## TL;DR / Рекомендация
|
||||||
|
|
||||||
|
**Остаться на текущем формате** (`email.md` + YAML-frontmatter + SQLite FTS5).
|
||||||
|
Он полностью закрывает сценарий «локальная LLM из скриптов», которым мотивирован
|
||||||
|
выбор файлового хранения. Maildir даёт стандартность, но для LLM-анализа хуже
|
||||||
|
(нужен разбор MIME) и не поддерживает произвольные тэги.
|
||||||
|
|
||||||
|
**Эволюция вместо миграции:**
|
||||||
|
1. Добавить `tags: []` в frontmatter (для веб-UI «назначенные тэги»)
|
||||||
|
2. Держать Maildir-совместимость как **опцию экспорта** (не как базовое хранение)
|
||||||
|
3. `notmuch` — опция позже, если FTS5 станет тесным
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Факты по текущему архиву (замер 2026-09-11)
|
||||||
|
|
||||||
|
| Метрика | Значение |
|
||||||
|
|---------|----------|
|
||||||
|
| Всего email.md | **4884** |
|
||||||
|
| Объём | **76 МБ** |
|
||||||
|
| INBOX (вкл. подпапки) | 2674 |
|
||||||
|
| Archive | 876 |
|
||||||
|
| Отправленные | 790 |
|
||||||
|
| Sent | 544 |
|
||||||
|
| Размер mail_index.db (FTS5) | 5.4 MB |
|
||||||
|
| Структура | `/<folder>/YYYY/MM/UID/email.md` |
|
||||||
|
|
||||||
|
Frontmatter (пример):
|
||||||
|
```yaml
|
||||||
|
id: 4
|
||||||
|
folder: INBOX/!Отчеты
|
||||||
|
subject: "FW: Справка о статусах..."
|
||||||
|
from: "Головлев Алексей Вячеславович <a.golovlev@vinogorod.ru>"
|
||||||
|
to: "Рыбкин Валентин Станиславович <v.rybkin@vinogorod.ru>"
|
||||||
|
date: "2025-08-22 21:50+03:00"
|
||||||
|
flags: ["Seen"]
|
||||||
|
```
|
||||||
|
Плюс в части файлов: Message-ID, References, In-Reply-To, Content-Type.
|
||||||
|
Тело — в том же файле после `---`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Сравнение форматов
|
||||||
|
|
||||||
|
| Критерий | Текущий (email.md + FTS5) | Maildir | MBOX | notmuch |
|
||||||
|
|----------|---------------------------|---------|------|---------|
|
||||||
|
| **Пригодность для LLM-скриптов** | ★★★★★ — `cat email.md \| ollama` напрямую: frontmatter + тело | ★★☆ — raw-MIME, нужен парсер (`mail`/`munpack`) | ★★☆ — mbox, нужен разбор | ★★★★ — поиск готов, но тело в Maildir |
|
||||||
|
| **Человекочитаемость** | ★★★★★ — YAML + Markdown, grep/obsidian | ★★☆ — имена файлов нечитаемы, MIME | ★★☆ | ★★★ |
|
||||||
|
| **Производительность инкр. чтения** | ★★★★ — скан случайных UID-папок | ★★★★★ — число файлов в `new/` = новых писем | ★★☆ — весь файл на перезапись | ★★★★★ |
|
||||||
|
| **Атомарность / устойчивость** | ★★★★ — новая папка на письмо (но без fsync) | ★★★★★ — tmp→new→cur, эталон | ★★☆ — блокировки, частичная запись | ★★★★ |
|
||||||
|
| **Флаги (Seen/Answered)** | ★★★ — в frontmatter | ★★★★★ — в имени файла `:2,RS` | ★★★ | ★★★★ |
|
||||||
|
| **Произвольные тэги (для UI)** | ★★★★★ — добавить `tags: []` | ★★☆ — только флаги, тэгов нет | ★★☆ | ★★★★★ — core-фича |
|
||||||
|
| **Стандарт / совместимость с MUA** | ★★☆ — свой, MUA не читают | ★★★★★ — mutt/neomutt/thunderbird/dovecot | ★★★★★ — legacy | ★★★★ (поверх Maildir) |
|
||||||
|
| **Масштабируемость (10k–100k)** | ★★★★ — но много маленьких файлов | ★★★★★ | ★★☆ | ★★★★★ |
|
||||||
|
| **Бэкапы (Yandex Disk / git)** | ★★★★★ — простой копией/grep | ★★★★ — тысячи файлов | ★★★★ | ★★★ (нужен индекс) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Детали по каждому подходу
|
||||||
|
|
||||||
|
### Текущий формат `email.md` (выбран)
|
||||||
|
**Плюсы:**
|
||||||
|
- Идеален для локальной LLM: `cat email.md | ollama run qwen3:8b "резюмируй"` —
|
||||||
|
тело уже очищено от MIME, frontmatter даёт атрибуты для фильтрации в скрипте
|
||||||
|
- Прозрачность: `grep`, `find`, `jq`, Obsidian, VS Code
|
||||||
|
- Атомарность записи: `mail_archive.py` создаёт новую папку `UID/`, не трогая
|
||||||
|
существующие письма → устойчиво к сбою в любой момент
|
||||||
|
- Бэкап = копирование директории (Yandex Disk FUSE)
|
||||||
|
|
||||||
|
**Минусы:**
|
||||||
|
- Нестандартный: ни один MUA (mutt/thunderbird) не читает напрямую
|
||||||
|
- Флаги в frontmatter, не в ФС-атрибутах → медленнее для MUA
|
||||||
|
- Нет встроенной семантики целостности Maildir (fsync) — но для архива это ок
|
||||||
|
- Дублирование с FTS5-индексом (mail_index.db) — два источника правды
|
||||||
|
- 4884 файла = 4884 маленьких файла → фирменных лимитов на inode нет, но
|
||||||
|
на сотнях тысяч лучше Maildir
|
||||||
|
|
||||||
|
### Maildir
|
||||||
|
**Плюсы:**
|
||||||
|
- **Стандарт де-факто**: mutt, neomutt, thunderbird, dovecot читают
|
||||||
|
- **Эталон атомарности**: `tmp/` → `new/` → `cur/`, флаги в имени файла
|
||||||
|
- Новые письма = файлы в `new/` → быстрый инкрементальный скан (нет SQL)
|
||||||
|
- Надёжность при сбое: никогда не частичного файла
|
||||||
|
|
||||||
|
**Минусы (критично для нас):**
|
||||||
|
- Тело в **raw-MIME**: для LLM-анализа нужен парсер (email.message, munpack).
|
||||||
|
У нас аналогично 2674 письма, но LLM должен читать frontmatter за `cat`
|
||||||
|
- Имена файлов нечитаемы (`1700000000.12345.host:2,S`) — grep по теме невозможен
|
||||||
|
- **Нет произвольных тэгов** — только Seen/Answered/Flagged/Deleted. Для
|
||||||
|
«назначенных тэгов» в веб-UI пришлось бы вести отдельный индекс (notmuch/SQLite)
|
||||||
|
- Не человекочитаем в Obsidian
|
||||||
|
|
||||||
|
### MBOX
|
||||||
|
Исключается сразу: один большой файл на папку, перезапись при любом изменении,
|
||||||
|
блокировки, плохо для инкрементального чтения и бэкапов по частям. Для LLM
|
||||||
|
и бэкапов на Yandex Disk — худший выбор.
|
||||||
|
|
||||||
|
### notmuch (поверх Maildir или email.md)
|
||||||
|
**Плюсы:** полнотекстовый поиск с тэгами — идеален для UI-тэгов.
|
||||||
|
**Минусы:** это **индексный слой**, не хранилище. Требует демона/индекса,
|
||||||
|
дублирует то, что уже делает FTS5. Дисквалифицирует простоту `grep`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Гибридный путь (рекомендация)
|
||||||
|
|
||||||
|
Сохранить текущий `email.md` как **каноническое хранилище** (источник правды),
|
||||||
|
но:
|
||||||
|
1. **Добавить `tags: []`** в frontmatter при записи (для UI) — тривиально в
|
||||||
|
`mail_archive.py`
|
||||||
|
2. **Экспорт в Maildir** как **опция** (для чтения в mutt/thunderbird при
|
||||||
|
желании), не зеркало в реальном времени — по запросу
|
||||||
|
3. **FTS5 остаётся** поисковым индексом; при росте >50k писем — оценить notmuch
|
||||||
|
|
||||||
|
Это даёт: LLM-удобство (текущий), стандартную совместимость (опция экспорта),
|
||||||
|
UI-тэги (frontmatter), поиск (FTS5). Без потери данных и без миграции.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Влияние на веб-интерфейс (задача 1)
|
||||||
|
|
||||||
|
Текущий формат уже содержит всё для UI-списка:
|
||||||
|
- `date` → дата письма
|
||||||
|
- `from` → адресант
|
||||||
|
- `subject` → тема
|
||||||
|
- (новое) `tags` → назначенные тэги
|
||||||
|
- `folder` → текущая папка (для перемещения: `mail_archive.py` или прямой
|
||||||
|
`mv` + обновить frontmatter + FTS5)
|
||||||
|
|
||||||
|
Maildir не дал бы тэгов без отдельного индекса. Текущий формат — оптимален.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Вывод
|
||||||
|
|
||||||
|
Текущий подход (`email.md` + FTS5) **удобнее** Maildir для заявленной цели
|
||||||
|
(локальная LLM из скриптов без облака). Maildir выигрывает только в
|
||||||
|
«стандартной совместимости с MUA» и «инкрементном скане без БД» — что не
|
||||||
|
критично для нашего сценария. **Рекомендуется остаться на текущем + добавить
|
||||||
|
`tags` в frontmatter + опциональный экспорт в Maildir.**
|
||||||
|
|
||||||
|
Ссылки: [README](README.md) · [STATUS](STATUS.md)
|
||||||
Reference in New Issue
Block a user