Всем приветик!
Настало время понемногу рассказывать о том, с чем мы столкнулись в разработке — и что, как мне кажется, будет вам интересно.
(Иронично, конечно, что пост выходит в момент, когда я снова дико занят, потому что кое-кто опять занят юридическими делами. Но ладно, не будем о грустном.)
Помните, в одном из прошлых постов я говорил, что хочу попробовать поработать с ещё более жёстким хайлоадом?
Ну… накаркал.
Как вы знаете, в Стражнике мы модерируем стикеры (и морально готовимся к фото и гифкам). И вот, буквально на днях, нас накрыл такой вал нагрузки, что за короткое время мы обработали 30+ миллионов записей и 8 миллионов файлов.
И где-то между «всё хорошо» и «This is fine» всплыла очень любопытная проблема.
Как у нас устроен флоу обработки:
запись задачи → процессор обрабатывает задачу → сохраняет результаты как файлы → нейронка обрабатывает эти файлы.
Красиво? Да.
Работает? Обычно — да.
Но в тот день нейронка… простаивала. Почти полностью пустая.
А очередь задач — Токио ещё далеко до такого количества записей.
Мы начали разбираться, и выяснилось: у нас дико тормозит удаление строк из таблицы. Самый обычный, самый банальный запрос:
То есть не нейронка, не процессинг файлов, не очереди — а DELETE.
И в этот момент у меня в голове всплыло то самое вечное высказывание, которое я слышу когда Telegram в очередной раз показывает удалённое сообщение:
«Мессенджеры не удаляют сообщения — они помечают их как удалённые».
И я подумал: окей, если у нас DELETE начинает душить пайплайн, давайте разберёмся почему так происходит и как жить.
Поэтому встречайте: новый мини-цикл постов!
Мы поговорим о:
- soft delete и hard delete
- о том, почему PostgreSQL на самом деле не удаляет строки сразу
- как устроена под капотом MVCC
- почему UPDATE с флагом бывает дешевле DELETE
- как мессенджеры управляют массивами данных
- что вам лично с этим делать, если у вас миллионы строк и нагрузка растёт
Готовьте свои СУБД, миллионы записей и немного кофе.
Мы начинаем уже завтра.
Настало время понемногу рассказывать о том, с чем мы столкнулись в разработке — и что, как мне кажется, будет вам интересно.
(Иронично, конечно, что пост выходит в момент, когда я снова дико занят, потому что кое-кто опять занят юридическими делами. Но ладно, не будем о грустном.)
Помните, в одном из прошлых постов я говорил, что хочу попробовать поработать с ещё более жёстким хайлоадом?
Ну… накаркал.
Как вы знаете, в Стражнике мы модерируем стикеры (и морально готовимся к фото и гифкам). И вот, буквально на днях, нас накрыл такой вал нагрузки, что за короткое время мы обработали 30+ миллионов записей и 8 миллионов файлов.
И где-то между «всё хорошо» и «This is fine» всплыла очень любопытная проблема.
Как у нас устроен флоу обработки:
запись задачи → процессор обрабатывает задачу → сохраняет результаты как файлы → нейронка обрабатывает эти файлы.
Красиво? Да.
Работает? Обычно — да.
Но в тот день нейронка… простаивала. Почти полностью пустая.
А очередь задач — Токио ещё далеко до такого количества записей.
Мы начали разбираться, и выяснилось: у нас дико тормозит удаление строк из таблицы. Самый обычный, самый банальный запрос:
DELETE FROM jobs WHERE id = $1;
То есть не нейронка, не процессинг файлов, не очереди — а DELETE.
И в этот момент у меня в голове всплыло то самое вечное высказывание, которое я слышу когда Telegram в очередной раз показывает удалённое сообщение:
«Мессенджеры не удаляют сообщения — они помечают их как удалённые».
И я подумал: окей, если у нас DELETE начинает душить пайплайн, давайте разберёмся почему так происходит и как жить.
Поэтому встречайте: новый мини-цикл постов!
Мы поговорим о:
- soft delete и hard delete
- о том, почему PostgreSQL на самом деле не удаляет строки сразу
- как устроена под капотом MVCC
- почему UPDATE с флагом бывает дешевле DELETE
- как мессенджеры управляют массивами данных
- что вам лично с этим делать, если у вас миллионы строк и нагрузка растёт
Готовьте свои СУБД, миллионы записей и немного кофе.
Мы начинаем уже завтра.
🔥39❤8❤🔥3😎3🍓2👻1
Итак, открываем наш цикл о сложности, о которой почти никто не думает — до тех пор, пока не становится слишком поздно.
Начнём с самого простого. Вот наш запрос:
Разбираем по частям:
Выглядит… ну, вообще не страшно. Обычнейшая операция.
Но давайте посмотрим, что на самом деле происходит в тот момент, когда вы это делаете.
1) Поиск строки
PostgreSQL должен найти нужную запись.
В больших таблицах это почти всегда будет по индексу, так что шаг ещё относительно быстрый.
Но это — только разогрев.
2) Установка блокировки строки
DELETE ставит блокировку на саму строку.
Если таблица — архив, не страшно.
Если таблица активно читается/пишется, или если DELETE прилетают потоком — вы получите: задержки, очереди ожидания, эффект "узкого горлышка", который начинает душить весь поток.
Неприятно, но терпимо. Пока.
3) Удаление строки (ну… почти)
PostgreSQL помечает строку как удалённую.
Физически она никуда не девается (про это поговорим в следующем посте).
Сам шаг быстрый, тут ещё нет боли.
4) Обновление индексов — и вот здесь начинается настоящий урон
База вынуждена удалить все ссылки на эту строку из:
- первичного ключа,
- каждого индекса таблицы,
- всех составных индексов, если они есть (а они почти всегда есть).
Это самая дорогая часть операции:
Postgres модифицирует страницы индексов, перелопачивает их структуру, записывает изменения — это всё время, CPU и дисковые операции.
DELETE на таблице с 5 индексами — это в 5+ раз больше работы, чем DELETE на таблице без индексов.
5) Запись изменений в WAL — финальный босс
Всё, что произошло:
- блокировки,
- изменения строк,
- изменения индексов,
- факт удаления
всё это теперь нужно записать в WAL (Write-Ahead Log).
И если у вас:
- высокая нагрузка,
- репликация,
- много DELETE подряд
WAL становится бутылочным горлышком, начинаются задержки, и производительность всей системы падает.
И что мы получаем
Одна строка. Один DELETE.
А работы... Много, если цензурно выражаться.
А теперь представьте, что это не один DELETE, а тысяча.
А теперь — что это тысячи DELETE каждую минуту.
Если вы мессенджер, DELETE будет прилетать потоком.
Если вы контроллер задач с большой нагрузкой — тоже.
И вот тут DELETE превращается в довольно дорогую операцию, которая может тормозить весь ваш пайплайн… как это, собственно, и произошло у нас.
Начнём с самого простого. Вот наш запрос:
DELETE FROM jobs WHERE id = 123;
Разбираем по частям:
DELETE — говорим серверу: «пора удалять».FROM jobs — удалять будем в таблице jobs.WHERE id = 123 — удаляем только те строки, где id равен 123.Выглядит… ну, вообще не страшно. Обычнейшая операция.
Но давайте посмотрим, что на самом деле происходит в тот момент, когда вы это делаете.
1) Поиск строки
PostgreSQL должен найти нужную запись.
В больших таблицах это почти всегда будет по индексу, так что шаг ещё относительно быстрый.
Но это — только разогрев.
2) Установка блокировки строки
DELETE ставит блокировку на саму строку.
Если таблица — архив, не страшно.
Если таблица активно читается/пишется, или если DELETE прилетают потоком — вы получите: задержки, очереди ожидания, эффект "узкого горлышка", который начинает душить весь поток.
Неприятно, но терпимо. Пока.
3) Удаление строки (ну… почти)
PostgreSQL помечает строку как удалённую.
Физически она никуда не девается (про это поговорим в следующем посте).
Сам шаг быстрый, тут ещё нет боли.
4) Обновление индексов — и вот здесь начинается настоящий урон
База вынуждена удалить все ссылки на эту строку из:
- первичного ключа,
- каждого индекса таблицы,
- всех составных индексов, если они есть (а они почти всегда есть).
Это самая дорогая часть операции:
Postgres модифицирует страницы индексов, перелопачивает их структуру, записывает изменения — это всё время, CPU и дисковые операции.
DELETE на таблице с 5 индексами — это в 5+ раз больше работы, чем DELETE на таблице без индексов.
5) Запись изменений в WAL — финальный босс
Всё, что произошло:
- блокировки,
- изменения строк,
- изменения индексов,
- факт удаления
всё это теперь нужно записать в WAL (Write-Ahead Log).
И если у вас:
- высокая нагрузка,
- репликация,
- много DELETE подряд
WAL становится бутылочным горлышком, начинаются задержки, и производительность всей системы падает.
И что мы получаем
Одна строка. Один DELETE.
А работы... Много, если цензурно выражаться.
А теперь представьте, что это не один DELETE, а тысяча.
А теперь — что это тысячи DELETE каждую минуту.
Если вы мессенджер, DELETE будет прилетать потоком.
Если вы контроллер задач с большой нагрузкой — тоже.
И вот тут DELETE превращается в довольно дорогую операцию, которая может тормозить весь ваш пайплайн… как это, собственно, и произошло у нас.
❤50🔥8❤🔥5🍓2🤝2
Чё мы такие серьёзные, учитывая посты в канале, ко мне уже люди боятся обращаться, думая что я задушню. Обращение "дядя Бессонный" — легендарно.
Давайте разбавлять напряжение и страх меня в канале.
Тем более, It's wednesday my dudes. Теперь по средам мы не напрягаемся, я не пугаю вас лонгридами и мы смотрим мемчики. Не только же работать)
Давайте разбавлять напряжение и страх меня в канале.
Тем более, It's wednesday my dudes. Теперь по средам мы не напрягаемся, я не пугаю вас лонгридами и мы смотрим мемчики. Не только же работать)
🕊63❤12☃5✍3❤🔥2🔥2💋2🎉1
Продолжая разговор о таблицах и строках.
Мы уже поняли, что
Давайте разберёмся, как
Когда PostgreSQL «удаляет» строку, он не вырезает её из таблицы. Он помечает её как неактуальную. Такая строка называется dead tuple — мёртвая версия строки.
Она:
- продолжает лежать в таблице
- занимает место на странице и на диске
- участвует в механизме чтения (они не возвращаются, так как отфильтровываются по visibility map, но увеличивают стоимость скана)
- не удаляется без VACUUM
То есть
Почему так происходит
Причина — MVCC (многоверсионность).
PostgreSQL обязан:
- позволять другим транзакциям дочитать старые данные
- сохранять консистентность
- не блокировать чтение
Цена за это — версии строк. А при
А проблема ли это вообще?
Пока dead tuples мало — нет.
Но при массовых операциях начинается цепная реакция.
- Вы удаляете строки, но место на диске не освобождается, а иногда даже продолжает расти.
- Чтение становится дороже: база проверяет видимость строк, даже если актуальных данных мало.
- VACUUM начинает работать дольше и чаще.
Самое неприятное
PostgreSQL не уменьшает размер таблицы автоматически.
Даже если VACUUM убрал большенство dead tuples — файл таблицы на диске останется прежнего размера.
Чтобы реально вернуть место, нужны тяжёлые меры:
- VACUUM FULL
- перенос данных
- партиционирование
А это уже операции, которые очень не хочется выполнять на живой системе под нагрузкой. А как жить в таком жестоком мире мы поговорим в следующем посте.
Мы уже поняли, что
DELETE — операция тяжеловатая. Но внимательные могли заметить: я писал не «удаляет строку», а «помечает строку». И это важно.Давайте разберёмся, как
DELETE работает на самом деле.Когда PostgreSQL «удаляет» строку, он не вырезает её из таблицы. Он помечает её как неактуальную. Такая строка называется dead tuple — мёртвая версия строки.
Она:
- продолжает лежать в таблице
- занимает место на странице и на диске
- участвует в механизме чтения (они не возвращаются, так как отфильтровываются по visibility map, но увеличивают стоимость скана)
- не удаляется без VACUUM
То есть
DELETE — это не «убрали», а «оставили, но пометили как мусор».Почему так происходит
Причина — MVCC (многоверсионность).
PostgreSQL обязан:
- позволять другим транзакциям дочитать старые данные
- сохранять консистентность
- не блокировать чтение
Цена за это — версии строк. А при
DELETE появляется ещё и мёртвая версия, которая никуда не исчезает сразу.А проблема ли это вообще?
Пока dead tuples мало — нет.
Но при массовых операциях начинается цепная реакция.
- Вы удаляете строки, но место на диске не освобождается, а иногда даже продолжает расти.
- Чтение становится дороже: база проверяет видимость строк, даже если актуальных данных мало.
- VACUUM начинает работать дольше и чаще.
Самое неприятное
PostgreSQL не уменьшает размер таблицы автоматически.
Даже если VACUUM убрал большенство dead tuples — файл таблицы на диске останется прежнего размера.
Чтобы реально вернуть место, нужны тяжёлые меры:
- VACUUM FULL
- перенос данных
- партиционирование
А это уже операции, которые очень не хочется выполнять на живой системе под нагрузкой. А как жить в таком жестоком мире мы поговорим в следующем посте.
❤42🔥12⚡5🫡3🥰2👍1🆒1
И снова привет! Продолжаем наши похождения по удалениям.
Мы уже обсудили две важные вещи:
-
- после
Возникает логичный вопрос: а как тогда удалять?
И ответ на него одновременно простой и нет — soft delete.
Что такое soft delete
В этой методике мы не удаляем строку, а просто помечаем её как удалённую.
То есть вместо:
мы делаем:
Для приложения запись сразу считается удалённой,
но физически она остаётся в таблице.
Почему это дешевле
1. Мы почти не трогаем индексы
Поле
а значит — меньше модификаций страниц и меньше дисковых операций.
2. Меньше WAL
UPDATE одного поля пишет меньше данных в WAL,
что снижает нагрузку на диск и упрощает репликацию.
3. Меньше блокировок и побочных эффектов
Нет постоянного потока тяжёлых DELETE,
система ведёт себя стабильнее под нагрузкой.
Почему deleted_at, а не is_deleted
Чаще всего используют именно
- известно, когда запись была удалена
- можно откатить удаление по дате
- удобно строить TTL-чистку на основе времени удаления.
«Но ведь строки остаются в таблице»
Да. И в этом весь смысл.
Мы разделяем удаление на два этапа:
1. Быстро и дёшево убираем данные из пользовательского флоу в любой момент времени.
2. Медленно и аккуратно удаляем их физически позже —
например, ночью, когда система нагружена меньше.
И небольшой приятный бонус
Когда пользователь пишет: «Я СЛУЧАЙНО НАЖАЛ УДАЛИТЬ, ВЕРНИТЕ» — у вас уже есть TTL-окно, в которое это можно спокойно сделать 😉
Мы уже обсудили две важные вещи:
-
DELETE — тяжёлая операция;- после
DELETE в базе остаётся мусор.Возникает логичный вопрос: а как тогда удалять?
И ответ на него одновременно простой и нет — soft delete.
Что такое soft delete
В этой методике мы не удаляем строку, а просто помечаем её как удалённую.
То есть вместо:
DELETE FROM messages WHERE id = 993;
мы делаем:
UPDATE messages
SET deleted_at = now()
WHERE id = 993;
Для приложения запись сразу считается удалённой,
но физически она остаётся в таблице.
Почему это дешевле
1. Мы почти не трогаем индексы
Поле
deleted_at обычно не входит в основные индексы,а значит — меньше модификаций страниц и меньше дисковых операций.
2. Меньше WAL
UPDATE одного поля пишет меньше данных в WAL,
что снижает нагрузку на диск и упрощает репликацию.
3. Меньше блокировок и побочных эффектов
Нет постоянного потока тяжёлых DELETE,
система ведёт себя стабильнее под нагрузкой.
Почему deleted_at, а не is_deleted
Чаще всего используют именно
deleted_at timestamptz, потому что:- известно, когда запись была удалена
- можно откатить удаление по дате
- удобно строить TTL-чистку на основе времени удаления.
«Но ведь строки остаются в таблице»
Да. И в этом весь смысл.
Мы разделяем удаление на два этапа:
1. Быстро и дёшево убираем данные из пользовательского флоу в любой момент времени.
2. Медленно и аккуратно удаляем их физически позже —
например, ночью, когда система нагружена меньше.
И небольшой приятный бонус
Когда пользователь пишет: «Я СЛУЧАЙНО НАЖАЛ УДАЛИТЬ, ВЕРНИТЕ» — у вас уже есть TTL-окно, в которое это можно спокойно сделать 😉
👍37❤14🙏3🎃1🦄1
This media is not supported in your browser
VIEW IN TELEGRAM
🤣51😁8💯7🔥4🥰1👏1😢1🏆1😭1
Мы пережили среду. Не сказать, что это было сложно, но — пережили.
А значит, идём дальше в нашем приключении по столбцам.
Мы уже научились дёшево “удалять” данные, используя методику soft delete. Но, как это обычно бывает, тут нас ждёт новый подводный камень.
Если просто начать добавлять
Почему?
Потому что мы поменяли паттерн чтения, и внезапно перестали эффективно попадать в индекс.
Звучит не очень понятно — давайте разберёмся на примере.
Пример: таблица сообщений
Допустим, у нас есть таблица сообщений, и задача простая: прочитать сообщения конкретного чата, отсортированные по дате создания.
Запрос выглядит просто:
Под него идеально подходит индекс:
Быстро, красиво, эффективно.
А теперь добавляем soft delete
Как только появляется условие:
На больших таблицах это означает лишнюю работу, а иногда — почти последовательное сканирование.
И вот вы уже вроде как оптимизировали удаление, и сломали чтение.
Но и тут есть решение — partial index (частичный индекс)
Мы можем создать индекс только по живым строкам:
Что это нам даёт:
- индекс становится меньше по размеру
- в нём лежат только актуальные данные
- чтение сообщений происходит быстро и стабильно
- планировщику проще выбрать правильный план.
Важный момент
Partial index — это не опциональная оптимизация, а обязательная часть архитектуры soft delete.
Очень частая ошибка выглядит так: «Мы внедрили soft delete, но база всё равно тормозит».
А потом выясняется, что:
- SELECT сканирует кучу удалённых строк;
- индекс есть, но он не помогает
Если коротко
И только вместе они дают тот эффект, ради которого всё это и затевалось.
А значит, идём дальше в нашем приключении по столбцам.
Мы уже научились дёшево “удалять” данные, используя методику soft delete. Но, как это обычно бывает, тут нас ждёт новый подводный камень.
Если просто начать добавлять
deleted_at IS NULL в запросы, то на больших объёмах данных мы можем не ускориться, а вполне себе замедлиться.Почему?
Потому что мы поменяли паттерн чтения, и внезапно перестали эффективно попадать в индекс.
Звучит не очень понятно — давайте разберёмся на примере.
Пример: таблица сообщений
Допустим, у нас есть таблица сообщений, и задача простая: прочитать сообщения конкретного чата, отсортированные по дате создания.
Запрос выглядит просто:
SELECT *
FROM messages
WHERE chat_id = 42
ORDER BY created_at;
Под него идеально подходит индекс:
(chat_id, created_at)Быстро, красиво, эффективно.
А теперь добавляем soft delete
Как только появляется условие:
AND deleted_at IS NULL всё начинает меняться. PostgreSQL сначала находит строки по индексу, а потом вынужден проверять deleted_at IS NULL отдельноНа больших таблицах это означает лишнюю работу, а иногда — почти последовательное сканирование.
И вот вы уже вроде как оптимизировали удаление, и сломали чтение.
Но и тут есть решение — partial index (частичный индекс)
Мы можем создать индекс только по живым строкам:
CREATE INDEX idx_messages_live
ON messages (chat_id, created_at)
WHERE deleted_at IS NULL;
Что это нам даёт:
- индекс становится меньше по размеру
- в нём лежат только актуальные данные
- чтение сообщений происходит быстро и стабильно
- планировщику проще выбрать правильный план.
Важный момент
Partial index — это не опциональная оптимизация, а обязательная часть архитектуры soft delete.
Очень частая ошибка выглядит так: «Мы внедрили soft delete, но база всё равно тормозит».
А потом выясняется, что:
- SELECT сканирует кучу удалённых строк;
- индекс есть, но он не помогает
Если коротко
Soft delete отвечает за дешёвую запись.
Partial index — за быструю выборку.
И только вместе они дают тот эффект, ради которого всё это и затевалось.
❤47😁4❤🔥1👍1🔥1🌭1🙈1
Итак, мы уже почти полностью прошли путь внедрения soft delete: от замены DELETE-операций до выстраивания индексов.
Но остаётся главный вопрос:
Ведь строки остаются.
И если их не убирать — таблица рано или поздно превратится в свалку.
На первый взгляд всё кажется простым.
Ну правда, что может пойти не так?
Но как бы мило и аккуратно ни выглядел этот запрос,
на больших объёмах он может сделать очень больно:
- огромный DELETE → всплеск WAL
- долгий и тяжёлый ближайший VACUUM
- просадки по latency
- неожиданные тормоза в живом трафике.
Если у вас ночью почти нет нагрузки — да, такой вариант иногда можно себе позволить.
Но что делать, если у вас постоянный поток операций и «тихого времени» просто не существует?
Постепенный вынос мусора
В этом случае мусор выносят маленькими порциями.
Типичный подход выглядит так:
- раз в 5 минут
- удаляем 1–5 тысяч строк
- без спешки
- без пиков нагрузки
Пример запроса:
Что это даёт:
- Ограниченный WAL — без резких всплесков.
- Короткие транзакции — меньше блокировок.
- Предсказуемую нагрузку — без сюрпризов для продакшена.
- Возможность спокойно жить даже под постоянным трафиком.
И главное, что стоит запомнить
Но остаётся главный вопрос:
а как вообще выносят мусор?
Ведь строки остаются.
И если их не убирать — таблица рано или поздно превратится в свалку.
На первый взгляд всё кажется простым.
Ну правда, что может пойти не так?
DELETE FROM messages
WHERE deleted_at < now() - interval '30 days';
Но как бы мило и аккуратно ни выглядел этот запрос,
на больших объёмах он может сделать очень больно:
- огромный DELETE → всплеск WAL
- долгий и тяжёлый ближайший VACUUM
- просадки по latency
- неожиданные тормоза в живом трафике.
Если у вас ночью почти нет нагрузки — да, такой вариант иногда можно себе позволить.
Но что делать, если у вас постоянный поток операций и «тихого времени» просто не существует?
Постепенный вынос мусора
В этом случае мусор выносят маленькими порциями.
Типичный подход выглядит так:
- раз в 5 минут
- удаляем 1–5 тысяч строк
- без спешки
- без пиков нагрузки
Пример запроса:
DELETE FROM messages
WHERE id IN (
SELECT id
FROM messages
WHERE deleted_at < now() - interval '30 days'
ORDER BY deleted_at
LIMIT 5000
);
Что это даёт:
- Ограниченный WAL — без резких всплесков.
- Короткие транзакции — меньше блокировок.
- Предсказуемую нагрузку — без сюрпризов для продакшена.
- Возможность спокойно жить даже под постоянным трафиком.
И главное, что стоит запомнить
Soft delete — это не “никогда не удалять”.
Это “удалять тогда, когда системе удобно”.
Он не является панацеей от всех проблем,
но его разумное использование может сократить их.
❤21🔥4❤🔥3👍1😁1🤗1
Сегодня конечно не среда, но держите прекрасную ситуацию, которая у нас возникла из-за ttl токена, о котором все забыли 😱
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥73😍5💯4❤2👏2
Ух, наконец тот самый момент — конец года уже совсем близко. В честь такого можно взять заслуженный отпуск, хотя бы на пару часов и просто выдохнуть.
Год, если честно, был непростой. Очень непростой. АЛО, КТО ВКЛЮЧИЛ ХАРДКОР?
Но при всём этом — хорошего в нём тоже было немало.
Давайте начнём с моего большого личного проектика. Имперский Стражник, твой выход.
Мы сделали много разных обновлений. Хотелось, конечно, больше — но не всё успели, хотя впереди ещё огого сколько всего.
Активно поработали над модерацией медиа и уже уверенно движемся к модерации текста.
Расширили команду — с одного меня до нескольких человек. И это, честно, очень сильно помогло.
Что ещё? Я начал чуть активнее работать над каналом, особенно весной. Вы получили прям гору контента — и это далеко не всё. В работе ещё много интересных циклов и отдельных постов, и я правда верю, что смогу их довести до конца.
Давайте вспомним, что канал всё-таки немного авторский. А значит — и обо мне тоже.
Что там по мне? Я живой. Это уже достижение, D:
Во-первых, я закрыл огромную главу жизни и наконец выпустился. Два десятка лет обучения — всё, конец. Свобода)
Во-вторых… я очень долго бился, но всё-таки смог победить. Я ещё ни разу не говорил об этом здесь, но, пожалуй, время пришло.
Я человек с таким «позитивным» здоровьем, что меня уже знают в поликлиниках в лицо. А мои любимки из объединённого военкомата города Москвы решили закрыть глаза и на болячки, и на законы — и выдали мне повестку на отправку к месту службы.
Шесть месяцев шло разбирательство. И вот совсем недавно я наконец смог отстоять законное признание своего состояния и получил категорию «В».
Это было сложно. Долго. Нервно. Без взяток (но и не бесплатно — суды деньги жрут знатно).
Вот как-то так.
А что у нас по ST? Любимок, конечно, забывать нельзя. Но да — в этом году я с ними немного охладил интеракцию.
Когда твой год выглядит как цепочка
зимняя сессия → практика → дипломная → суд с государством,
времени становится катастрофически мало.
Это, думаю, было заметно: я просел и по количеству контента для вас, и по объёму вклада в ST.
Но даже так — сделал немало полезного и важного.
В целом этот год можно смело назвать годом внутрянки и удобства сотрудников. Из-за множества событий в стране пришлось многое менять и перестраивать — и эти процессы до сих пор продолжаются. Про это я, скорее всего, напишу отдельный пост, как только согласую формулировки с NDA.
Вот такой немного безумный год получился.
Через пару часов (или уже завтра) я выпущу отдельный пост о том, как этот год выглядел в цифрах.
А сейчас — хочу просто пожелать вам счастливого Нового года и удачи. Спасибо, что вы здесь.
Год, если честно, был непростой. Очень непростой. АЛО, КТО ВКЛЮЧИЛ ХАРДКОР?
Но при всём этом — хорошего в нём тоже было немало.
Давайте начнём с моего большого личного проектика. Имперский Стражник, твой выход.
Мы сделали много разных обновлений. Хотелось, конечно, больше — но не всё успели, хотя впереди ещё огого сколько всего.
Активно поработали над модерацией медиа и уже уверенно движемся к модерации текста.
Расширили команду — с одного меня до нескольких человек. И это, честно, очень сильно помогло.
Что ещё? Я начал чуть активнее работать над каналом, особенно весной. Вы получили прям гору контента — и это далеко не всё. В работе ещё много интересных циклов и отдельных постов, и я правда верю, что смогу их довести до конца.
Давайте вспомним, что канал всё-таки немного авторский. А значит — и обо мне тоже.
Что там по мне? Я живой. Это уже достижение, D:
Во-первых, я закрыл огромную главу жизни и наконец выпустился. Два десятка лет обучения — всё, конец. Свобода)
Во-вторых… я очень долго бился, но всё-таки смог победить. Я ещё ни разу не говорил об этом здесь, но, пожалуй, время пришло.
Я человек с таким «позитивным» здоровьем, что меня уже знают в поликлиниках в лицо. А мои любимки из объединённого военкомата города Москвы решили закрыть глаза и на болячки, и на законы — и выдали мне повестку на отправку к месту службы.
Шесть месяцев шло разбирательство. И вот совсем недавно я наконец смог отстоять законное признание своего состояния и получил категорию «В».
Это было сложно. Долго. Нервно. Без взяток (но и не бесплатно — суды деньги жрут знатно).
Вот как-то так.
А что у нас по ST? Любимок, конечно, забывать нельзя. Но да — в этом году я с ними немного охладил интеракцию.
Когда твой год выглядит как цепочка
зимняя сессия → практика → дипломная → суд с государством,
времени становится катастрофически мало.
Это, думаю, было заметно: я просел и по количеству контента для вас, и по объёму вклада в ST.
Но даже так — сделал немало полезного и важного.
В целом этот год можно смело назвать годом внутрянки и удобства сотрудников. Из-за множества событий в стране пришлось многое менять и перестраивать — и эти процессы до сих пор продолжаются. Про это я, скорее всего, напишу отдельный пост, как только согласую формулировки с NDA.
Вот такой немного безумный год получился.
Через пару часов (или уже завтра) я выпущу отдельный пост о том, как этот год выглядел в цифрах.
А сейчас — хочу просто пожелать вам счастливого Нового года и удачи. Спасибо, что вы здесь.
❤37🍾4❤🔥3💊2🙊1😎1
This media is not supported in your browser
VIEW IN TELEGRAM
❤35🔥6🤝3⚡2❤🔥1👍1🤯1💊1
Никто этого не ждал (5 сбоев Bot Api за 2 дня не считаются), но Telegram наконец выпустил обновление Bot Api которое ещё давно нам обещал!
Как говорится, праздник? Не, не слышали, идём под куранты обновлять ботов и либы.
Возможности для AI (топики и стриминг).
- Теперь в приватных чатах (лички) можно включить разделение на топики. Боты могут соответственно отправлять сообщения и медиа в конкретные топики.
- Добавлен стриминг сообщений по мере генерации текста (через sendMessageDraft)
Подарки и звёзды
- Добавлена возможность получать подарки пользователя и чата через Bot API
- Гибкая фильтрация лимитированных, апгрейд-подарков и подарков из TON.
- Добавлена полная информация о подарках в Bot API включая уникальные цвета, фоны и стили, влияющие на имя пользователя, ответы и превью ссылок.
- Максимальная цена платного медиа увеличена до 25 000 Stars.
Прочее
- Боты могут отключать основной username, если есть дополнительные.
- Можно отключать can_restrict_members в каналах.
- Добавлен репост сторис между бизнес-аккаунтами.
- Появился рейтинг пользователей и дополнительные поля в информации о чатах.
- Новые параметры эффектов сообщений и чеклистов.
Как говорится, праздник? Не, не слышали, идём под куранты обновлять ботов и либы.
Возможности для AI (топики и стриминг).
- Теперь в приватных чатах (лички) можно включить разделение на топики. Боты могут соответственно отправлять сообщения и медиа в конкретные топики.
- Добавлен стриминг сообщений по мере генерации текста (через sendMessageDraft)
Подарки и звёзды
- Добавлена возможность получать подарки пользователя и чата через Bot API
- Гибкая фильтрация лимитированных, апгрейд-подарков и подарков из TON.
- Добавлена полная информация о подарках в Bot API включая уникальные цвета, фоны и стили, влияющие на имя пользователя, ответы и превью ссылок.
- Максимальная цена платного медиа увеличена до 25 000 Stars.
Прочее
- Боты могут отключать основной username, если есть дополнительные.
- Можно отключать can_restrict_members в каналах.
- Добавлен репост сторис между бизнес-аккаунтами.
- Появился рейтинг пользователей и дополнительные поля в информации о чатах.
- Новые параметры эффектов сообщений и чеклистов.
❤27🔥7💊3❤🔥1👍1🎉1🙏1🐳1👾1