惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
V
V2EX
C
Check Point Blog
GbyAI
GbyAI
D
Docker
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog RSS Feed
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
Netflix TechBlog - Medium
T
Troy Hunt's Blog
博客园 - Franky
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Security Blog
Microsoft Security Blog
P
Privacy & Cybersecurity Law Blog
WordPress大学
WordPress大学
The Cloudflare Blog
S
SegmentFault 最新的问题
Latest news
Latest news
Microsoft Azure Blog
Microsoft Azure Blog
P
Proofpoint News Feed
I
InfoQ
博客园 - 【当耐特】
NISL@THU
NISL@THU
A
About on SuperTechFans
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
The Hacker News
The Hacker News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Scott Helme
Scott Helme
雷峰网
雷峰网
C
CXSECURITY Database RSS Feed - CXSecurity.com
Security Latest
Security Latest
V
Vulnerabilities – Threatpost
Security Archives - TechRepublic
Security Archives - TechRepublic
A
Arctic Wolf
Hacker News: Ask HN
Hacker News: Ask HN
N
News and Events Feed by Topic
IT之家
IT之家
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
aimingoo的专栏
aimingoo的专栏
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
SecWiki News
SecWiki News
大猫的无限游戏
大猫的无限游戏
S
Security Affairs
The Register - Security
The Register - Security
www.infosecurity-magazine.com
www.infosecurity-magazine.com
L
LINUX DO - 热门话题
T
Tor Project blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Mountain| Первый финал, первая победа и новый старт
Cayo · 2026-05-01 · via Все публикации подряд на Хабре

Уровень сложностиПростой

Время на прочтение6 мин

Охват и читатели469

Обзор

За 25 дней нам удалось добиться довольно больших изменений в нашем проекте.

Мы провели:

  • Рефакторинг back-end сервисов

  • Убрали часть легаси кода на фронте

  • Переработали некоторый UI элементы и добавили плавности

  • Добавили новый функционал

Чем бы дитя не тешилось, лишь бы не плакало

Именно так мы подумали и решили завершать первый важный этап нашего MVP проекта. Мы подготовили всю инфраструктуру к работе, подбили UI что бы если и есть баги - то которые мы явно упустили за 30 часов тестирования.

Новый функционал

Мы добавили в приложение следующее:

  1. Рассылка кодов авторизации

  2. Поиск серверных чатов

  3. Подписка у пользователя в сообщениях какая это роль

  4. Переработали дизайн тредов, теперь у него больше настроек

  5. Сохранение сообщений

Поиск общих чатов

Не есть что конечно, слизано с приложения Discord, но мое виденье его внутри компании немного другого формата.

В чем вообще задумка его для корпоративного мессенджера? Для начала легко найти чаты внутри команд или структур. Группировка - это настраиваемые элементы, мы вывели их в отдельный конфиг, так что поправить под компанию - 5 минут. Настраивается из настроек чата.

В будущем добавим и плейсхолдел для настроек, пока что так оставим.

В будущем добавим и плейсхолдел для настроек, пока что так оставим.

Подписка у пользователя в сообщениях какая это роль

Представим что к вам пришел новый сотрудник, а в команде 50 человек. И вот ему надо привыкнуть еще к тому кто разработчик, кто тестировщик, кто стрим лид и тп, а еще же ведь и правильных людей тегать. Эту проблему и позволяет решить данная приписка.

Переработали дизайн тредов, теперь у него больше настроек

Вот тут наверное самое важное, то что плохо реализовано в корпоративных тредах. Долго думали что же нам не хватает и как попытаться уместить все в обычную форму.

  1. Мы расширили настройки на создание тредов

Теперь кроме названия треда и иконки можно:

  • Проставить теги

  • Написать нормальное описание

После создания тредов теперь мы можем не только посмотреть их список, но и так же:

  • Отфильтровать по названию, даже по одному слову в середине текста названия или описания

  • Отфильтровать по тегам, идет сортировка по часто используемым

  • Закрепить тред (все закрепленные всегда будут вверху, только потом будут идти не закрепленные, даже при поступлении в них новых сообщений)

Возможно, предвижу, кому-то удобнее прям внутри сообщений писать, тем самым создавая обсуждения. Потом мы добавим такое, но не в рамки обсуждения, а в рамках внутренних комментариев.

Рассылка кодов авторизации

Инфраструктура под это дело заложена в сервис авторизации. При регистрации или авторизации сервис будет отправлять на почту пользователя сообщение в формате HTML.

Рендер письма который заложен в код процесса рассылки

Рендер письма который заложен в код процесса рассылки

Пока еще не заводили отдельную почту для нашего сервиса.

Рефакторинг back-end сервисов

  • Мы изменили логику проверки прав, она стала более замудренная, но в тоже время и более правильная.

Теперь Gateway (основной сервис который либо пропускает запрос, либо нет) - подключен к redis pub/sub, инвалидирует версию прав и бит маску. Если не было события изменения - берет из мемори, если была - обновляет свой кеш. Кеш одного пользователя занимает 600.B. что не является слишком много. Для тяжелых прав на 2000 пользователей в одном сервер чате это около 4.5мб. В целом - пойдет.

Кеш хранимый в gateway:

{
    'chat_id':  str,          # ObjectId, 24 символа
    'version':  int,          # монотонный счётчик
    'base':     int,          # ← OR всех ролей юзера, ОДНО число
    'topics':   {tid: int},   # только топики с overrides
    'is_owner': bool,         # админ или нет
}
  • Сервис топиков тоже потерпел изменения. теперь он не ходит в Permission сервис что бы уточнить права пользователя на просмотр, а Gateway: ProxyRouter приклеивает заголовки:

def build_perm_headers(self, snapshot: dict) -> dict:
    return {
        'X-Perm-Base':   str(snapshot.get('base', 0)),
        'X-Perm-Topics': json.dumps(snapshot.get('topics', {})),
        'X-Is-Owner':    '1' if snapshot.get('is_owner') else '0',
    }

А сервис топиков их начинает парсить:

def parse_perm_headers(request) -> Optional[dict]:
    base = int(request.headers.get('x-perm-base'))
    topics = json.loads(request.headers.get('x-perm-topics', '{}'))
    is_owner = request.headers.get('x-is-owner') == '1'
    return {'base': base, 'topics': topics, 'is_owner': is_owner}

На выход топик сервис уже отдает отфильтрованные темы которые соответствуют правам пользователя внутри его роли:

{
    "success": true,
    "topics": [
        {
            "topic_id": "69ee3a46dab658745b095c27",
            "chat_id": "69ee32fba41e74b3744d6502",
            "name": "59545",
            "created_by": "69edfdf3a6343fa670fe55db",
            "topic_type": "thread",
            "position": 0,
            "created_at": "2026-04-26T16:16:06.983000",
            "updated_at": "2026-04-28T07:09:30.006000",
            "is_active": true,
            "group_id": "69f05d25335af601c7accfe7",
            "unread_count": 0
        },
        {
            "topic_id": "69ee39a4dab658745b095c26",
            "chat_id": "69ee32fba41e74b3744d6502",
            "name": "55532",
            "created_by": "69edfdf3a6343fa670fe55db",
            "topic_type": "text",
            "position": 1,
            "created_at": "2026-04-26T16:13:24.480000",
            "updated_at": "2026-04-28T07:09:30.001000",
            "is_active": true,
            "group_id": "69f05d25335af601c7accfe7",
            "unread_count": 0
        },
        {
            "topic_id": "69f05cf4335af601c7accfe6",
            "chat_id": "69ee32fba41e74b3744d6502",
            "name": "fgfhd",
            "created_by": "69edfdf3a6343fa670fe55db",
            "topic_type": "voice",
            "position": 2,
            "created_at": "2026-04-28T07:08:36.007000",
            "updated_at": "2026-04-28T07:09:30.001000",
            "is_active": true,
            "unread_count": 0,
            "group_id": null
        }
    ],
    "groups": [
        {
            "chat_id": "69ee32fba41e74b3744d6502",
            "name": "tdrfhg",
            "created_by": "69edfdf3a6343fa670fe55db",
            "position": 0,
            "created_at": "2026-04-28T07:09:25.028000",
            "updated_at": "2026-04-28T07:09:25.028000",
            "is_active": true,
            "group_id": "69f05d25335af601c7accfe7"
        }
    ]
}
  • Наконец то вынесли все коллекции сервис в отдельные базы. Раньше была одна общая БД, делалось для быстрого написания кода, но пораждало много зависимостей и хождений в чужие коллекции. Теперь все сервисы имеют свою БД со своими коллециями. Отдельный инстанс имеет только сервис сообщений.

  • 50% сервисов перевели в режим публикации событий. Т.е. раньше было много HTTP вызовов между ними, что пораждало лишние задержки в 1-4мс. Мелочь, но в рамках 1000 или 10000 пользователей это уже существенная нагрузка. Теперь HTTP вызовы служат только для получения информации от другого сервиса, все события которые раньше были переложены на Redis. Пример: Пользователь зашел в новый чат. Сервис чата сформирует событие что у него появился новый memories, сервис прав подхватит это событие и присвоит ему права и положит их в Redis, сервис Gateway увидит новые данные и заберет их к себе.

    • Мы работаем над переводом остальных сервисов, но не все так быстро))

Удаление легаси кода

При создании проекта, я вообще ничего не знал о методах разработки фронтенда. Сейчас когда нас несколько уже и мы отходим от AI разработки - начинаем сталкиваться с проблемами. Например тогдлы переключения - так как фронт писал ИИ, он в каждую форму где есть тогл - делал новый стилевый файл, и таких файлов скопилось 15+ ед. Мы перевели их на shared и пере-используем. И таких компонентов было очень много. В итоге нам получилось подчистить примерно 2к стилевых строк кода, сократить в JSX около 150 строк, потому что теперь это общие подключения.

Выделили отдельные сервисы кеша. Тонкие обёртки над универсальным key-value store для кэширования. Не хранят данные сами — только формирует ключи и инкапсулирует логику работы с одним конкретным namespace. Пример ниже:

export class TopicCache {
    constructor(store) {
        this.store = store;
        this.KEY = 'topic_messages';
    }

    getMessages(chatId, topicId) {
        return this.store.get(this.store.key(this.KEY, chatId, topicId));
    }

    setMessages(chatId, topicId, messages) {
        this.store.set(this.store.key(this.KEY, chatId, topicId), messages);
    }

    invalidateMessages(chatId, topicId) {
        if (topicId) {
            this.store.invalidate(this.store.key(this.KEY, chatId, topicId));
        } else {
            this.store.invalidateByPrefix(this.store.key(this.KEY, chatId));
        }
    }

    appendMessage(chatId, topicId, message) {
        const cacheKey = this.store.key(this.KEY, chatId, topicId);
        const cached = this.store.get(cacheKey);
        
        if (cached) {
            const exists = cached.some(m => m.message_id === message.message_id);
            if (!exists) {
                const updated = [...cached, message];
                this.store.set(cacheKey, updated);
                console.log(`[CACHE] Appended message to topic ${chatId}:${topicId}, total: ${updated.length}`);
            }
        }
    }
}

Аналогично сделали и с WS сервисом, вынесли все WS действия в отдельные сервисы, для сообщений, топиков, прав, тредов и тп. Раньше это были одни монолитные файлы.

Большую часть действующих фронт сервисов перевели на isMobile проверку. Например анимации фона на мобилке - не нужны, мы их не грузим и в сборку они так же не попадут.

Изменения в UI

Часть изменений и доработок написал выше.

Изменение в тулбаре голосовой комнаты

Кнопки анимированные, при наведении на ПК показывают анимацию

Кнопки анимированные, при наведении на ПК показывают анимацию

Добавили выбор устройства на ПК:

Тоглам кнопкам добавили плавный переход, на фото это не будет видно.

Для мобильной версии сделали 2 вида тапа.

Короткий: Открывает меню взаимодействия с сообщениями

Длинный: позволяет выбрать несколько сообщений сразу. Удалить, переслать или ответить.

Итог

За 25 дней мы проделали огромную работу над проектом. Работали порой и до часу ночи. Все прошлые выходные провели с утра до ночи в нашем проекте.

Что сейчас:

Наши инфраструктурные сервисы готовы. Мы начинаем фазу тестирования. Активно ищем сервер в аренду с простой поддержкой и не очень дорогой. Хотели 20.04 уже запуститься, но не успели, мысли приходили на лету.