28 июня 2026 г.

Выжимка из обсуждения с Claude от 28.06.2026

#multer#http#tls#криптография#mod#bloom filter#hyperloglog#идемпотентность#AI#TIL

HTTP

Multer — middleware для парсинга multipart/form-data. Использует busboy для разбора входящего стрима req. Storage engine определяет куда идут данные: DiskStorage → диск, MemoryStorage → буфер в RAM, кастомный → можно стримить напрямую в S3 через file.stream.

HTTP-запрос — это стрим. req реализует Readable, данные приходят чанками по TCP. Браузер тоже отдаёт файл по частям — TCP делит на сегменты ~1460 байт, congestion control регулирует скорость.

Видео в браузере — два механизма: progressive download через Range-запросы (206 Partial Content) и адаптивный стриминг (HLS/DASH) — нарезка на сегменты по 2-10 сек в нескольких качествах, много маленьких HTTP-запросов, CDN-friendly.

Редкие HTTP-коды:

WebDAV — расширение HTTP для работы с файлами как с файловой системой. Добавляет методы PROPFIND, MKCOL, COPY, MOVE, LOCK. Использует 207 Multi-Status для ответов с несколькими ресурсами. Не взлетел широко из-за XML, пессимистичных блокировок и отсутствия merge. Используется в Яндекс.Диске, Nextcloud, SharePoint.


TLS и криптография

TLS — три гарантии: конфиденциальность, целостность, аутентификация. Handshake — переговоры об алгоритме, выработка ключа, проверка сертификата. После — симметричное шифрование (AES-GCM) каждого пакета.

Зашифрованный туннель — метафора. Физически: трансформация данных перед отправкой в TCP. Промежуточные узлы видят пакеты, но не содержимое. Снаружи видны IP и SNI (hostname). ECH в TLS 1.3 шифрует и SNI.

TLS 1.3 — 1 round-trip вместо 2, убраны слабые алгоритмы, Forward Secrecy обязателен, 0-RTT (early data) для повторных соединений.

Diffie-Hellman — выработка общего секрета через открытый канал. Основан на задаче дискретного логарифма: g^x mod p = A — зная g, p, A найти x вычислительно невозможно при больших числах. ECDH — то же самое на эллиптических кривых, ключи в 8x меньше при той же стойкости.

Дискретный логарифмg^x ≡ A (mod p). Тройное равно (≡) — конгруэнтность, не обычное равенство. mod необратима — теряет информацию, поэтому нет обратной формулы. Лучший алгоритм — Index Calculus, субэкспоненциальный, поэтому классический DH требует 2048+ бит.

Квантовая угроза — алгоритм Шора решает дискретный логарифм за полиномиальное время. NIST стандартизирует пост-квантовую криптографию: CRYSTALS-Kyber, CRYSTALS-Dilithium (решётчатая математика).


Модульная арифметика

mod в backend: хэш-таблицы (index = hash % size, простой размер → равномерное распределение), round-robin (i % n), шардирование (user_id % shard_count), consistent hashing (кольцо [0, 2^32)), Bloom filter (h(x) % m), переполнение integer (wrapping_add в Rust = арифметика mod 2^32).

Кольцо вычетов Z/pZ — для простого p каждый ненулевой элемент имеет обратный по умножению. Малая теорема Ферма: a^(p-1) ≡ 1 (mod p) — используется в RSA для оптимизации. CRT (Chinese Remainder Theorem) ускоряет RSA-операции в ~4 раза.


Вероятностные структуры данных

Bloom Filter — битовый массив + k хэш-функций. “Точно нет” или “возможно да”. Ложные отрицания невозможны. Оптимальная заполненность ~50% (математически доказано). При переполнении вероятность ошибки растёт к 100%.

Формулы: m = -n * ln(p) / (ln(2))², k = (m/n) * ln(2). Практически: ~10 бит/элемент при 1% ошибки. Реализация через double hashing: h_i(x) = (h1(x) + i * h2(x)) % m — две базовые хэш-функции симулируют k независимых. MurmurHash/xxHash вместо криптографических — быстрее в десятки раз.

Применение: кэш промахи, защита от несуществующих ключей, дедупликация событий, SSTable в LSM-деревьях (RocksDB, Cassandra), Safe Browsing в Chrome.

Для идемпотентности не подходит — нужна гарантия “точно да”. Правильные инструменты: INSERT ... ON CONFLICT (уникальный индекс в БД) или Redis SET NX. Bloom filter — только оптимизация перед основной защитой, не замена.

Гонки в Bloom Filter — фильтр не потокобезопасен сам по себе. Гонка между проверкой и добавлением есть всегда. Distributed lock или mutex защищают сам фильтр, но не убирают гонку между фильтром и БД. Единственная надёжная защита — атомарные операции хранилища (SET NX, INSERT ... ON CONFLICT).

Saturation — при переполнении все биты становятся 1, фильтр бесполезен. Решения: заранее рассчитать размер, мониторить fill rate, Scalable Bloom Filter (цепочка фильтров), rotating фильтры (для временных окон).

HyperLogLog — оценка количества уникальных элементов. Фиксированные ~12 KB независимо от размера потока, погрешность ~0.8-2%. Основан на максимальной длине серии ведущих нулей в хэшах. Гармоническое среднее подавляет выбросы. PFMERGE в Redis позволяет объединять HLL за O(m) — константа. Для идемпотентности не подходит — не отвечает на вопрос “был ли конкретный элемент”.

Другие структуры:


PostgreSQL LISTEN/NOTIFY

Встроенный механизм, расширений не нужно. Убирает polling при ожидании результата.

Паттерн для идемпотентности с LISTEN/NOTIFY:

  1. CREATE записи со статусом processing (unique constraint ловит дубликаты)
  2. Дубликат → LISTEN payment_done → ждём уведомления
  3. После обработки → UPDATE статуса + NOTIFY payment_done, requestId

Порядок критичен: сначала LISTEN, потом проверка статуса — иначе гонка. Один глобальный listener на процесс (не на запрос) — иначе исчерпаешь пул соединений. NOTIFY не гарантирует доставку при обрыве — timeout + fallback на чтение из БД обязателен. Payload ограничен 8000 байт.


MikroORM v7 и Kysely

Почему убрали knex: фактически заброшен (редкие фиксы), накопились workaround’ы, слабая типобезопасность. Заменили на Kysely + цель zero runtime dependencies в @mikro-orm/core.

Как делать raw-запросы в v7:

Kysely + entity names: через em.getKysely({ tableNamingStrategy: 'entity', columnNamingStrategy: 'property' }) можно использовать имена entity/property вместо таблиц/колонок. Требует [EntityName]?: 'ClassName' символ в entity.

Kysely vs MikroORM QB: разные API, FilterQuery объект в Kysely не передать. Kysely нужен только для того что MikroORM QB не умеет. eb (expression builder) — типизированный объект для сложных выражений (window functions, CASE WHEN, subquery).

← ко всем статьям