Технічний пост про свій проект із деталями, а не ще одна реклама (частина 1)
tl;dr Я прошу допомоги спільноти протестувати проєкт нашої соціальної мережі, про яку я вже писав, і взагалі таких тисячі — ця точно не злетить, чого ти паришся, чувак. Тому вважайте це щоденником розробників, де іноді будуть з’являтися різні кумедні штуки.
Вступ
Я вже писав тут про нього. Це Вміст — схожий і на соцмережу, і на звичайний контентний сайт. Тут багато хто розповідав про свої проєкти з приблизно однаковим успіхом, це теж по суті самореклама, але я вирішив спробувати інший підхід.
Моя теорія в тому, що коментатори ДОУ токсичні, бо втомилися від булшиту в різних сенсах. Тому замість явного самовихваляння я спробую розповісти про те, що ми робили, і різні приколи розробки. Скажу відразу: вуха відкриті для будь-якої критики чи порад, адже наша робота — це щось на кшталт поетичних батлів.
Прикол № 1 для затравки
Коли ми тільки починали, у моментах, де я пропонував підтримку Markdown, фронтендери хрестилися і казали, що такого нема в класичних соцмережах, що при 0 користувачах ускладнювати немає сенсу й що мені треба більше відпочивати. Я погодився, тим паче що тоді мав основну роботу і ще одну, де працював за договором кілька годин на тиждень.
Але мені дуже хотілося, щоб посилання підтримувалися нативно: з прев’ю, внутрішнім обліком і всім таким. І ми додали концепт метаданих у код — бекенд, отримуючи новий пост, отримував також масив ідентифікаторів, затегованих у body за допомогою \u200B. Типу так: \u200B{1}. Фронтенд рендеріл текст вибираючи посилання з масиву.
Вийшло класно, ми навіть змогли робити прев’ю. Але виявилося, що:
- Більшість популярних сайтів ненавидять запити з пулів хостерів. У відповідь ти отримаєш у кращому разі 403, у гіршому — класичний фолбек від Nginx на помилку 444.
- Моя регулярка для пошуку посилань у тексті не врахувала, що люди люблять обгортати їх у дужки, а ще й самі посилання іноді містять дужки (привіт, Вікіпедія).
- Посилання на самого себе не працювали, бо бекенд не бачив свій же домен.
Першу проблему ми вирішили кумедним костилем. Увесь сайт уже працював у Kubernetes на DigitalOcean, тож я просто додав проксі як фолбек: якщо запит падав, сервер пробував ще раз через мою власну квартиру. Це виявилося напрочуд ефективним. Для цього я взяв простий TinyProxy з вайтлістом запитів із сервера.
Проблему з дужками я вирішую досі, бо несповідимі шляхи користувачів. Нещодавно ми все-таки додали підтримку маркдауну, що додало головного болю, тому що поведінка рендеру на фронті виявилася непередбачуваною. Довелося піти на хитрість — тепер я спочатку перетворюю посилання з маркдаун на свій формат, а потім проходжуся по тексту як раніше.
Регулярка вийшла такою: (?:^|[\s(\[<\{'"`])(https://[^\s\}>'"`]+)(?:\s*<([^>]+)>)?
Третя проблема виявилася найгіршою. Попри допомогу одного з найталановитіших девопсів, яких я знав (і водночас одного з моїх найкращих друзів), ми так і не змогли змусити поди бачити власний домен. Довелося городити костилі.
На той час у нас уже працював окремий ендпоінт для побудови відповідей з тегами OG і всім, що робить посилання красивими. Я виніс його в окремий мікросервіс, і він став простим ререндером для таких запитів, повертаючи дуже простий HTML тільки з найважливішим. Можна було б заморочитися і зробити краще, але тоді навіщо я пишу цей пост?
Відео
О боже, як тільки з’явилися користувачі — усі захотіли відео. Але на це пішло 4 місяці. Спочатку ми додали обробку в Sidekiq з запуском ffmpeg, мінімум змін. Лімітували розмір файлу до 100 МБ, я потім додав перевірку тривалості й обмежив до 15 хвилин, але при такому розмірі це був уже другий презерватив, а не реально робочий план.
Та варто було відео бути трохи довшим за 5 хвилин або справді якісним — і ми зіткнулися з причиною, чому такі речі треба виносити в окремий інстанс, а не тримати в поді. Навіть за агресивних налаштувань у якийсь момент гувернер дивився на под, що жер 1000% ресурсів, поправляв монокль і підписував вирок. Стартували нові два, які знову брали завалений джоб, потім піднімалася нова нода — і так по колу. Мені вистачило мізків додати raise, інакше цей пост починався б із кредитної картки.
Поки я залишив усе всередині пода з Sidekiq, підняв ліміти, виставив гарантовані ресурси і змінив кодек на H.265 з профілем faster. Для тестових відео все пройшло успішно, викочуємо буквально днями — але я досі нервово заглядаю в k9s.
Росіяни
Ох, навіть не знаю, з чого почати. Ми вирішили, що росіяни, загалом, потрібні (дочитайте!). Вони є, ми не можемо вдавати, що їх не існує. Тому потрібно не ховатись від них, а подивитися в очі та вказати місце. Ну і особисто я проти створення комфортних бульбашок.
Майже відразу додали фільтри «Сховати пости російською мовою», що я вважав популізмом, але навіть у моєму особистому колі всі сказали, що це гарне рішення і я передумав. Зробили приховування на основі запитів в Google Транслейт API, копіюючи 20 відсотків посту рандомом з різних місць, методом точок акцентів, щоб точно отримати правильний результат навіть якщо цитується якийсь пропагандист.
По-перше, ми створили ідеальний ханіпот — трекали їхні сесії, намагалися заглянути за VPN, написали суворі правила й покладалися на користувачів, бо в українців (яких ми завжди вважали головною аудиторією) на них реакція, як у мого кота на апельсини.
У правилах було розписано багато, але коротко: крок вбік — публічний розстріл і похорон у морі. Дивіться самі: vmist.net/static/ref/rules
Та ще коли в нас і 50 користувачів не було, посипалися не просто боти, а реальні люди, які почали писати про кривавий режим і килимові бомбардування алеї ангелів. Довелося діяти швидко.
Наші гості користувалися нідерландським мікрохостером, створюючи там дешеві VPS. Я спершу думав, що це просто VPN, але вони реально логінилися туди і відразу заходили по RDS, бо в User-Agent часто була вінда. Написав купу листів хостеру, навіть нахабно погрозив судом, але отримав запевнення у сприянні та все на цьому. Чісто ООН чи как там.
На той момент у нас уже був бот Душнила, що працював на Gemini Flash 2.5, і я віддав йому на відкуп аналіз постів (згодом це переросло у велику інтеграцію, але про це в іншому пості). Він почав бити на сполох, вбивати акаунти і банити через Rack::Attack підмережі з коротким TTL. Я також заборонив вхід через сервіси миттєвих мейлів і синхронізувався з базами.
На цьому вони не зупинилися і почали штормити dev-оточення, яке я, на жаль, посадив на той самий домен, і знайти його було легко. Ви б бачили: пул пітерських IP 45.135.232.* буквально жив у мене на нетиповому порті SSH 2220. А ще був дев-сайт, відкритий назовні... Одного разу я не зміг через них швидко завантажити апдейт для Astrobot і додав knock, зроблений нашвидкуруч — тепер доступ відкривається тільки після правильної послідовності. Стало набагато легше жити.
Перший підсумок під постом
Мені здається, я достатньо написав для початку. Це проба пера, тому тут швидше забавні випадки, а не технічні подробиці, які будуть у наступних постах, якщо вам сподобається формат.
Історій у нас назбиралося на роки. Крім того, я постійно робив бенчмарки, ми зіштовхнулися з неймовірними проблемами інтегруючи Телеграм через їхній сервер у докері, ми придумали SSR усередині Rails API-only застосунку, я можу розсмішити будь-кого розповідями про проблеми React Native з Kotlin у рендері Webview і багато чого ще.
Крім відгуків, я прошу вас дати нам ще один шанс і подивитися на сам проєкт.
Вміст, vmist.net
З повагою до спільноти та щирою спробою розірвати цикл і почати писати цікаві технічні пости.

9 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів