Спасибо за разбор — полезно. Прошлась по всем трём пунктам.
1. Tesseract.js Замечание частично справедливо, но с оговоркой: Tesseract уже работает через createWorker() — распознавание идёт в Web Worker, главный поток не блокируется. WASM и модели кэшируются в IndexedDB. Так что «блокирует главный поток» — не про мой случай. Но задержки были, и я их закрыла: OCR запускался после 3-секундной анимации впитывания → теперь параллельно с ней. Воркер создавался при первом вводе → теперь ленивая предзагрузка при первом pointerdown + прогрев. Добавила таймаут на recognize() (15 сек). Результат: первый ввод вдвое быстрее, повторные — OCR прячется за анимацией. TextDetector не подходит: только Chrome/Android и только печатный текст. Ключевая механика — рукописный ввод.
2. Avada Kedavra Замечание справедливо, это был баг. while(true) {} без await вешал вкладку. Задумка была «честный эффект», реализация — DoS на свой же браузер. Исправлено: busy-loop заменён на бесконечный requestAnimationFrame-цикл. Главный поток свободен, вкладка отвечает, CPU в простое ≈ 0%. Визуально то же самое — «мёртвая пустота», ввод заблокирован.
3. Rate limiting на фронте Справедливо. Фронтовый лимитер — UX, не безопасность. Обходится через DevTools или curl. Исправлено в Worker'е: Origin-проверка → 403 для чужих доменов. Per-IP лимит: 10/мин, бан 3 часа (как в исходном RateLimiterService). Глобальный дневной лимит: 5000 запросов — защита бюджета DeepSeek. Retry-After в заголовках 429. НЕ делаю: Durable Objects (недоступны на бесплатном тарифе), Turnstile/WAF (избыточно для пет-проекта). Если пойдёт вирусный трафик — добавлю Turnstile. Ограничение: in-memory счётчики сбрасываются при redeploy. Для текущего масштаба приемлемо.
Спасибо за разбор — полезно. Прошлась по всем трём пунктам.
1. Tesseract.js
Замечание частично справедливо, но с оговоркой: Tesseract уже работает через createWorker() — распознавание идёт в Web Worker, главный поток не блокируется. WASM и модели кэшируются в IndexedDB. Так что «блокирует главный поток» — не про мой случай.
Но задержки были, и я их закрыла:
OCR запускался после 3-секундной анимации впитывания → теперь параллельно с ней.
Воркер создавался при первом вводе → теперь ленивая предзагрузка при первом pointerdown + прогрев.
Добавила таймаут на recognize() (15 сек).
Результат: первый ввод вдвое быстрее, повторные — OCR прячется за анимацией.
TextDetector не подходит: только Chrome/Android и только печатный текст. Ключевая механика — рукописный ввод.
2. Avada Kedavra
Замечание справедливо, это был баг. while(true) {} без await вешал вкладку. Задумка была «честный эффект», реализация — DoS на свой же браузер.
Исправлено: busy-loop заменён на бесконечный requestAnimationFrame-цикл. Главный поток свободен, вкладка отвечает, CPU в простое ≈ 0%. Визуально то же самое — «мёртвая пустота», ввод заблокирован.
3. Rate limiting на фронте
Справедливо. Фронтовый лимитер — UX, не безопасность. Обходится через DevTools или curl.
Исправлено в Worker'е:
Origin-проверка → 403 для чужих доменов.
Per-IP лимит: 10/мин, бан 3 часа (как в исходном RateLimiterService).
Глобальный дневной лимит: 5000 запросов — защита бюджета DeepSeek.
Retry-After в заголовках 429.
НЕ делаю: Durable Objects (недоступны на бесплатном тарифе), Turnstile/WAF (избыточно для пет-проекта). Если пойдёт вирусный трафик — добавлю Turnstile.
Ограничение: in-memory счётчики сбрасываются при redeploy. Для текущего масштаба приемлемо.