а есть что насчет декодирования бинарных форматов данных (при использовани того же extended query protocol) в tshark, или он всегда корректно отображает содержимое полей типа bytea?
но вообще, все это звучит так: «нам можно халтурить, потому что мы для новичков»
смотрите, в том то и проблема, что Хабр - это не площадка для сознательных упрощений, которые превращаются в фактические ошибки. здесь ЦА в основном технари, которые приходят за экспертизой. даже джун, прочитав про лонг поллинг с диаграммами, где изображен классический шорт поллинг, сформирует в голове неверную ментальную модель, хотя правды ради, джун увидит в вашей статье ошибку буквально сразу
ценность технического текста не в чтобы не сойти с ума, а в том, чтобы дать точную, пусть и упрощённую, но КОРРЕКТНУЮ картину. ваше объяснение про прикладной уровень - это попытка задним числом выдать фундаментальное непонимание темы за педагогический приём, который активно применяют во всех университетах неграмотные преподватели
вы пишете, что не рассматриваете архитектурные различия, но это именно ТО, что отличает подходы! long polling это не просто другой способ доставки, это постоянная нагрузка на ваше приложение, которое должно держать множество висящих соединений, это свои сложности с балансировщиками, это проблема неупорядоченных доставок» при масштабировании.
что касается вебхуков, это совсем другая история, событийная модель, необходимость идемпотентности, правильная обработка повторных отправок от телеги, борьба с race conditions, о которой вы в статье хоть как то упомянули, но так, что даже это звучит как абстрактная страшилка. сводить это к просто кафе с десертом, это не упрощение, это профанация
для вебхуков нужен постоянный публичный айпи, настроенный хтппс, отказоустойчивый эндпоинт, который не должен ложиться, правильно настроенные обработчики
для long polling на первых порах достаточно простейшего скрипта на дешёвом впс. он конечно со временем упрётся в лимиты, но для 90% ботов их хватит на годы. Ваше заявление, что не тот кейс это просто отмазка. любой новичков, который прочтёт вашу статью, побежит делать вебхуки, потому что они дешевле и современнее, и потратит кучу времени и денег на настройку того, что ему объективно не нужно
вот и получается, что статья не просто поверхностная, она вредна
что касается тейка о том, что пометка "простой" снимает всю ответственность за качество контента. на Хабре статьи с пометкой "простой" - это зачастую как раз те, где авторы не просто объясняют сложное доступно, а делают это точно, без смыслового брака, взгляните на материалы по пайтону, раст, си т.п. указание уровня в статье - это не индульгенция для неточностей, а даже очень тяжелый вызов, объяснить сложное так, чтобы было и понятно, и без искажений
печально, но это сейчас просто тренд, вместо того чтобы учить людей мыслить и понимать архитектуру, плодятся статьи однодневки, которые создают больше проблем, чем решают
согласен, статья откровенно слабая даже для новичков
"разница только в том, как телеграм доставляет события"
это ГРУБОЕ упрощение! На самом деле это фундаментально разные архитектурные подходы. Long polling требует постоянного соединения, а вебхуки публичного эндпоинта, про аналогию с десертом без комментареив
диаграммы вводят в заблуждение. в long polling запрос не закрывается и открывается заново постоянно, соединение держится открытым до таймаута или получения данных. вы путаете short polling и long polling, хотя сама статья якобы про последний
особенно забавно читать про то, чтовебхуки дешевле. для прода с тысячей пользователей как раз long polling выйдет дешевле
и в целом много воды, простейшие аналогии и ноль технической глубины, как будто собрали из первых ссылок в гугле или gpt. OTUS платят за такие тексты или нет? если нет, то понятно. потому что иначе объяснить, зачем выпускать такой поверхностный контент, сложно
Простите, но после прочтения складывается впечатление, что статью писал не QA-инженер, а ChatGPT по первому запросу " напиши легкую статью для всех про микросервисные паттерны". Тот самый уровень воды, который пытаются выдавить на собеседованиях джуны, когда делают вид, что в теме, но не могут ответить ни на один уточняющий вопрос
Возьмем тот же Circuit Breaker, автор пересказывает теорию про три состояния, но полностью игнорирует практическую реализацию. Где конкретика по порогам срабатывания? Какие метрики отслеживать, таймауты, 5xx, slow responses? Какой процент ошибок считать критическим, 50% или 80%? Как избежать ложных срабатываний при скачках нагрузки? Оказывается, можно написать целую статью и не ответить ни на один по-настоящему важный вопрос.
Статья не просто бесполезна, она вредна. Новички поведутся на этот псевдо-экспертный тон, а опытные ребята сразу увидят сборник очевидных тезисов, которые гуглятся за 5 минут. Уровень плохого реферата, а не материала для профессионального сообщества
это вправду прям большая проблема раста, c это структурой всё не так очевидно, но конечно решаемо
нельзя просто так взять и иметь несколько изменяемых ссылок на один объект, язык этого не позволяет из за правл владения
самый адекватный способ - комбо Rc и RefCell, узлы хранятся как Rc<RefCell<Node>>, а перекрест ссылки как Weak<RefCell<Node>>. при копировании создаёшь временную мапу, где ключ указатель на старый узел, а значение ссылка на новый, далее встречаешь узел, проверяешь, не копировал ли уже его, и либо используешь существующую копию, либо просто создаем новую
еще можно вместо ссылок использовать индексы. создаешь Vec<Node>, а все связи между узлами выражаешь через обычные индексы этого вектора
конечно беруши от высоких частот не спасут, но тут еще интересно понять, какого качества у вас были беруши? Обычно качественные, например, alpine sleepsoft сидят как родные
Rust не гарантирует TCO. Хотя для некоторых простых случаев, как с Fibonacci, оптимизации компилятора могут помочь, но это скорее редкий бонус, чем прям специфика языка.
В Rust есть обходные пути, тот же crate tailcall, который позволяет добавлять аннотацию хвостовой рекурсии через trampoline, но это больше костыль, чем полноценная функция языка. Также иногда возможны оптимизации через LLVM.
Основное, что важно понимать: автоматической TCO в Rust нет, и полагаться на неё без явных проверок не стоит
Да, в Rust надо прописывать типажи для шаблонов, зато сразу ясно, что и где можно вызывать, и без сюрпризиков на этапе компиляции. В C++ свободы больше, но и баги могут всплыть неожиданно (по моему опыту).
&str — это как раз оптимальный выбор для аргументов, когда нам не нужна лишняя аллокация. &str — легковесная ссылка, работает быстрее и без лишнего копирования данных, так что для большинства задач это именно то, что нужно. Rust вообще сделан так, чтобы по возможности избегать лишних аллокаций, и &str здесь идеально вписывается.
А вотToString можно использовать его для некой гибкости, но он сразу вызывает to_string(), а значит, создает новую строку. А для проекта, где скорость к примеру критична, это не лучший вариант — если нужна просто ссылка, то лишняя аллокация с ToString и to_string() добавляет ненужную нагрузку
Отличный комментарий, но не согласен, что unwrap() и expect() вообще нельзя использовать в продакшене. Наоборот, они полезны в ситуациях, где данные гарантированно корректны, и отсутствие значения указывает на баг, а не на ожидаемую ситуацию. Например, если заранее проверили данные и знаем, что значение точно есть, unwrap() явно упростит этот код, избавляя от ненужных проверок и сигнализируя, что отсутствие данных здесь просто невозможно.
А с expect() можно добавлять кастомные сообщения об ошибках.
Но если ошибка вполне ожидаема и требует обработки, то ? или Result конечно подходят лучше.
Спасибо за поправку, Вы абсолютно правы! Я использовал Box<dyn Processable>, чтобы показать саму идею динамической диспетчеризации и владения объектом — иногда это нужно, когда надо передать объект с динамическим трейт-типом. Но для большинства случаев и правда лучше обойтись ссылкой без аллокации в куче.
Ваш вариант с &dyn Processable проще и экономичнее, так что спасибо за напоминание — добавлю его в статью как способ оптимизации!
Добрый день! Тут июль больше о том, что даже в абсолютно не новогоднее время, запах мандаринок у многих вызовет ассоциации с Новым Годом
отличное дополнение к статье
благодарю! вы настоящий хранитель очепяток
а есть что насчет декодирования бинарных форматов данных (при использовани того же extended query protocol) в tshark, или он всегда корректно отображает содержимое полей типа bytea?
вы имеете полное право стоять на своём :)
но вообще, все это звучит так: «нам можно халтурить, потому что мы для новичков»
смотрите, в том то и проблема, что Хабр - это не площадка для сознательных упрощений, которые превращаются в фактические ошибки. здесь ЦА в основном технари, которые приходят за экспертизой. даже джун, прочитав про лонг поллинг с диаграммами, где изображен классический шорт поллинг, сформирует в голове неверную ментальную модель, хотя правды ради, джун увидит в вашей статье ошибку буквально сразу
ценность технического текста не в чтобы не сойти с ума, а в том, чтобы дать точную, пусть и упрощённую, но КОРРЕКТНУЮ картину. ваше объяснение про прикладной уровень - это попытка задним числом выдать фундаментальное непонимание темы за педагогический приём, который активно применяют во всех университетах неграмотные преподватели
вы пишете, что не рассматриваете архитектурные различия, но это именно ТО, что отличает подходы! long polling это не просто другой способ доставки, это постоянная нагрузка на ваше приложение, которое должно держать множество висящих соединений, это свои сложности с балансировщиками, это проблема неупорядоченных доставок» при масштабировании.
что касается вебхуков, это совсем другая история, событийная модель, необходимость идемпотентности, правильная обработка повторных отправок от телеги, борьба с race conditions, о которой вы в статье хоть как то упомянули, но так, что даже это звучит как абстрактная страшилка. сводить это к просто кафе с десертом, это не упрощение, это профанация
для вебхуков нужен постоянный публичный айпи, настроенный хтппс, отказоустойчивый эндпоинт, который не должен ложиться, правильно настроенные обработчики
для long polling на первых порах достаточно простейшего скрипта на дешёвом впс. он конечно со временем упрётся в лимиты, но для 90% ботов их хватит на годы. Ваше заявление, что не тот кейс это просто отмазка. любой новичков, который прочтёт вашу статью, побежит делать вебхуки, потому что они дешевле и современнее, и потратит кучу времени и денег на настройку того, что ему объективно не нужно
вот и получается, что статья не просто поверхностная, она вредна
что касается тейка о том, что пометка "простой" снимает всю ответственность за качество контента. на Хабре статьи с пометкой "простой" - это зачастую как раз те, где авторы не просто объясняют сложное доступно, а делают это точно, без смыслового брака, взгляните на материалы по пайтону, раст, си т.п. указание уровня в статье - это не индульгенция для неточностей, а даже очень тяжелый вызов, объяснить сложное так, чтобы было и понятно, и без искажений
печально, но это сейчас просто тренд, вместо того чтобы учить людей мыслить и понимать архитектуру, плодятся статьи однодневки, которые создают больше проблем, чем решают
Доброго вам дня! Учту.
согласен, статья откровенно слабая даже для новичков
"разница только в том, как телеграм доставляет события"
это ГРУБОЕ упрощение! На самом деле это фундаментально разные архитектурные подходы. Long polling требует постоянного соединения, а вебхуки публичного эндпоинта, про аналогию с десертом без комментареив
диаграммы вводят в заблуждение. в long polling запрос не закрывается и открывается заново постоянно, соединение держится открытым до таймаута или получения данных. вы путаете short polling и long polling, хотя сама статья якобы про последний
особенно забавно читать про то, чтовебхуки дешевле. для прода с тысячей пользователей как раз long polling выйдет дешевле
и в целом много воды, простейшие аналогии и ноль технической глубины, как будто собрали из первых ссылок в гугле или gpt. OTUS платят за такие тексты или нет? если нет, то понятно. потому что иначе объяснить, зачем выпускать такой поверхностный контент, сложно
Кину свои пять копеек про изменяемые аргументы по умолчанию
Смотрим:
А все потому что
[]создается ОДИН РАЗ при загрузке функции и живет там как синглтон. Каждый вызов без аргумента тащит тот же самый списокФикс простой, юзаем None:
Простите, но после прочтения складывается впечатление, что статью писал не QA-инженер, а ChatGPT по первому запросу " напиши легкую статью для всех про микросервисные паттерны". Тот самый уровень воды, который пытаются выдавить на собеседованиях джуны, когда делают вид, что в теме, но не могут ответить ни на один уточняющий вопрос
Возьмем тот же Circuit Breaker, автор пересказывает теорию про три состояния, но полностью игнорирует практическую реализацию. Где конкретика по порогам срабатывания? Какие метрики отслеживать, таймауты, 5xx, slow responses? Какой процент ошибок считать критическим, 50% или 80%? Как избежать ложных срабатываний при скачках нагрузки? Оказывается, можно написать целую статью и не ответить ни на один по-настоящему важный вопрос.
Статья не просто бесполезна, она вредна. Новички поведутся на этот псевдо-экспертный тон, а опытные ребята сразу увидят сборник очевидных тезисов, которые гуглятся за 5 минут. Уровень плохого реферата, а не материала для профессионального сообщества
очень странная gpt статья про базовые вещи, которые знают все
это вправду прям большая проблема раста, c это структурой всё не так очевидно, но конечно решаемо
нельзя просто так взять и иметь несколько изменяемых ссылок на один объект, язык этого не позволяет из за правл владения
самый адекватный способ - комбо Rc и RefCell, узлы хранятся как Rc<RefCell<Node>>, а перекрест ссылки как Weak<RefCell<Node>>. при копировании создаёшь временную мапу, где ключ указатель на старый узел, а значение ссылка на новый, далее встречаешь узел, проверяешь, не копировал ли уже его, и либо используешь существующую копию, либо просто создаем новую
еще можно вместо ссылок использовать индексы. создаешь Vec<Node>, а все связи между узлами выражаешь через обычные индексы этого вектора
попробуете сам Rust, многое встанет на свои места. с++ после него уже не тот, так что добро пожаловать ;)
занятно
конечно беруши от высоких частот не спасут, но тут еще интересно понять, какого качества у вас были беруши? Обычно качественные, например, alpine sleepsoft сидят как родные
чего только не придумают
Rust не гарантирует TCO. Хотя для некоторых простых случаев, как с Fibonacci, оптимизации компилятора могут помочь, но это скорее редкий бонус, чем прям специфика языка.
В Rust есть обходные пути, тот же crate
tailcall, который позволяет добавлять аннотацию хвостовой рекурсии черезtrampoline, но это больше костыль, чем полноценная функция языка. Также иногда возможны оптимизации через LLVM.Основное, что важно понимать: автоматической TCO в Rust нет, и полагаться на неё без явных проверок не стоит
Да, в Rust надо прописывать типажи для шаблонов, зато сразу ясно, что и где можно вызывать, и без сюрпризиков на этапе компиляции. В C++ свободы больше, но и баги могут всплыть неожиданно (по моему опыту).
&str— это как раз оптимальный выбор для аргументов, когда нам не нужна лишняя аллокация.&str— легковесная ссылка, работает быстрее и без лишнего копирования данных, так что для большинства задач это именно то, что нужно. Rust вообще сделан так, чтобы по возможности избегать лишних аллокаций, и&strздесь идеально вписывается.А вот
ToStringможно использовать его для некой гибкости, но он сразу вызываетto_string(), а значит, создает новую строку. А для проекта, где скорость к примеру критична, это не лучший вариант — если нужна просто ссылка, то лишняя аллокация сToStringиto_string()добавляет ненужную нагрузкуОтличный комментарий, но не согласен, что
unwrap()иexpect()вообще нельзя использовать в продакшене. Наоборот, они полезны в ситуациях, где данные гарантированно корректны, и отсутствие значения указывает на баг, а не на ожидаемую ситуацию. Например, если заранее проверили данные и знаем, что значение точно есть,unwrap()явно упростит этот код, избавляя от ненужных проверок и сигнализируя, что отсутствие данных здесь просто невозможно.А с
expect()можно добавлять кастомные сообщения об ошибках.Но если ошибка вполне ожидаема и требует обработки, то
?илиResultконечно подходят лучше.Советую прочесть эту статью, которая раскрывает эту проблему https://blog.burntsushi.net/unwrap/
Спасибо за поправку, Вы абсолютно правы! Я использовал
Box<dyn Processable>, чтобы показать саму идею динамической диспетчеризации и владения объектом — иногда это нужно, когда надо передать объект с динамическим трейт-типом. Но для большинства случаев и правда лучше обойтись ссылкой без аллокации в куче.Ваш вариант с
&dyn Processableпроще и экономичнее, так что спасибо за напоминание — добавлю его в статью как способ оптимизации!