Как стать автором
Обновить
12
0

Разработчик

Отправить сообщение

Годик поработайте на одном проекте с таким подходом — станете совсем иначе воспринимать этот "оверхед"

Это же элементарно, Ватсон. Неужели вы никогда не подключались к существующему проекту? Обилие таких нюансов ни разу не идёт на пользу скорости погружения нового человека в проект

Конечно приемлим. Здравый смысл? Не, не слышал.

  1. Множественное присваивание и распаковка кортежей
    >> # Вместо этого:
    >> code = 404
    >> message = "Not Found"
    >> 
    >> # Характерный для Python способ:
    >> code, message = 404, "Not Found"

Отличный пример, но читаемость ни разу не выросла. На code review я за такое бью по рукам.


  1. Тернарное выражение
    >> # Вместо этого: 
    >> if got_even_number():
    ...     state = "Even"
    ... else:
    ...     state = "Odd"
    ... 
    >> # Характерный для Python способ:
    >> state = "Even" if got_even_number() else "Odd"

Тернарный оператор — очень скользкая дорожка. Чаще я сталкиваюсь с таким:


state = "Long description in case of `got_even_number` returns 1" \
    if got_even_number() else \
    "Another long description used when `got_even_number` returns 0"

В данном примере обычный if предпочтительнее. А ещё лучше обойтись вообще без if:


states = (
    "Another long description used when `got_even_number` returns 0",
    "Long description in case of `got_even_number` returns 1",
)
number = got_even_number()
state = states[number]
  • Профиль нагрузки на сервер.

Нет, серьёзно, когда приложение лезет в БД, результаты бенчмарков сильно меняются

Конечно не нужна. Поэтому там из коробки пулы prefork, eventlet и gevent, и внешним пакетом был реализован пул treadpoolexecutor.

ммм, ссылки на статьи почти десятилетней давности подъехали

И после этого "Linux это не система, а ворох разнородных поделок, смотанных изолентой". То ли дело windows — сам разберись, какой dll не хватает, сам скачай её с варезника, сам подкинь. Просто, понятно, логично

Это не упрощение. Это усложнение — лишний слой абстракции, скрывающий под капотом реальные аргументы команды. За это придется платить.

Всё смешалось: люди, кони. Речь идёт о предоставлении единого интерфейса к разным сервисам — или упрощении интерфейса. Был ли упрощён интерфейс? Был.


Ценой чего был упрощён интерфейс? Верно, ценой абстракции — усложнения реализации
А вот мысль "За это придется платить." прошу пояснить: за годы работы в саппорте понял, что игра в угадайку — неблагодарное занятие


По сути, мысль можно свести к следующему...

По сути, так любую здравую мысль можно свести к абсурду. Гротеск такой гротеск.


C-программисты — в make, Java — в maven goal, JS — в scripts в package.json, а питонисты пусть для manage.py модули пишут.

Перевожу на русский язык: "я не знаю, зачем нужен make, maven, package.json и manage.py, но соберу в одну кучу и покажу, какой я дофига умный". Возможно, повезёт в следующий раз


Только вот под лишним слоем абстракции всегда теряется понимание внутренних процессов и во время траблшутинга наступает час расплаты… Я уже это в мире Windows видел, где люди управляют серверами мышкой и не отдупляют, что у них вообще происходит.

И снова всё смешалось. Абстракция не есть сокрытие реализации, и сравнение с Windows ошибочно.


А давайте откажемся от файловых систем — они скрывают реализацию хранения данных на носителях. Давайте к каждому носителю обращаться напрямую — ведь за слои абстракций над носителями приходится платить! Давайте обращаться к цилиндрам на HDD. К чёрту файловые системы — эти абстракции так легко рушатся, а при траблшутинге никто дупля не отрезает, что на самом деле происходит и где на самом деле данные хранятся на диске


Вы прослушали миниатюру "Гротеск". Или, может, не всё ли равно, как носители работают внутри, если нам важен интерфейс — хранилище?




Выводы:


  • Абстракции не всегда есть "зло, за которое придётся платить"
  • Абстракции хороши, будучи применёнными к месту и в нужном объёме
В некоторых случаях нет готового хорошего инструмента

Правда чтоль? https://en.wikipedia.org/wiki/Message_queue#See_also
И правда, ни одного готового хорошего инструмента


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

Тут следует оговориться: я щупал MQ только через API Celery (по ссылке выше его кстати отнесли к MQ, хотя формально он пользователь MQ):
https://github.com/kai3341/celery-pool-asyncio/blob/master/celery_pool_asyncio/executors.py#L108
Из всего этого важно: accept_callback, callback (on_success), timeout_callback, error_callback. Всё это позволяет в полном объёме обработать исключения. API Celery также умеет в отложенную доставку.


сколько в этой очереди новых задач и сколько повторных?

Смотрю в DEBUG-лог Celery. Перед попаданием таски в пул в stdout печатается само сообщение. Там фигурирует 'retries': 0. Здесь тело интересующего нас сообщения инкапсулировано в структуру, передающую также метаданные.


Тогда давайте разделим очередь на две: в одну пишем новые, в другую — упавшие с задержкой. Отлично. Как теперь балансировать нагрузку на воркеры? 50% на новые, 50% на упавшие? А если упавших мало, то 50% мощностей будут простаивать? Брать задачи из каждой очереди по очереди?

Если мне не изменяет память, о балансировке рассказывал Олег Чуркин в докладе "50 оттенков Celery".


Как узнать, какие основные причины, по которым задачи попадают в очередь упавших? Ну, наверное, надо логи погрепать…

Ну помимо логов, в error_callback передаётся также информация об ошибке


А как быть уверенным, что в очереди находятся действительно все упавшие задачи, и какая-то не потерялась?

В этом смысл accept_callback, success_callback и error_callback. Все они предназначены в том числе и для отслеживания выполнения задач


А зачем нам тогда очередь, если у нас уже есть таблица с задачами

Допустим, Вы решаете задачу электрификации. Для того, чтобы провести линию в некий удалённый посёлок, нужно очистить площадь от деревьев, поставить столбы, на них поставить изоляторы, и уже на изоляторы положить кабель. Очистка территории от леса дело дорогое, столбы тоже дорогие. И тут вам приходит светлая мысль: А зачем нам вырезать деревья и после ставить столбы, если можно прикрутить изоляторы прямо к деревьям?


Мораль грузинский басня прост: из схожести интерфейсов не следует, что одно решение можно заменить другим.


Эти программисты так любят что-то менять в БД, они что, не понимают, что при этом каждый раз создаётся новая запись?! Давайте им запретим.

Ближайший аналог — конкатенация иммутабельных строк в python. Вам никто не запрещает выполнять их конкатенацию в цикле. Только вычислительная сложность под капотом выходит O(N!). А что пользователи? Подождут, куда денутся


активно используется ActiveMQ. И её использование в некоторых случаях не соответствует эксплуатационным требованиям

Ну так не используйте её в этих некоторых случаях.

Краткое содержание:
Статья "как плохо решить задачу неподходящими инструментами"
Комментарий "Оно просто не работает как очередь задач (MQ), потому как не соответствует требованиям MQ"
Ответ: "а тот факт, что оно не выполняет возложенных задач, никак не относится к статье"


От себя добавлю, что выбор постгреса в качестве очереди задач (помимо того, что решение попросту неэффективно) крайне неудачен ввиду особенностей реализации MVCC: постгрес на каждый update создаёт новую запись. Режим работы — минимум 1 update для каждой записи.


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


Изюминка ситуации в том, что в моём текущем проекте заказчик настоял на использовании БД (постгрес) в качестве резервной очереди задач. И я реализовал нечто подобное.
Разница в том, что с самого начала я знал, что творю маразм

В детстве меня пугали бабайкой. Сейчас пугают O(N^2). Интересно, что не было ни бабайки, ни O(N^2)

Статья в духе "я продолжаю начинать изучать программирование". Автор копнул глубоко — в дизассемблер байткода, и в то же время безумно поверхностно:


  1. Не рассмотрены generator expressions
  2. Выбор между map и list/generator expression определяется в первую очередь сложностью обработки каждого элемента. Одно дело, если каждый элемент надо возвести в квадрат, и совсем другое дело, если для каждого элемента нужно сходить в базу, потом в сторонний сервис, а ещё это залогировать
Ознакомился. В проекте взаимодействуют 2 разных инстанса Celery, каждый со своим изолированным набором тасок. Прямо вот в этом месте dramatiq и huey с их глобальным app становятся непригодными

Спасибо.
А вот стыдно пускай будет (должно быть) тем кто на govnokod.ru выкладывает чужой код и стебется над ним.
Серьёзно? Идея говнокода вовсе не в том, чтобы просто стебаться.
PS: О, его отмодерировали
Спасибо за статью
Большое спасибо, в ближайшее время ознакомлюсь
celery-redbeat решает проблему

Неа, эту проблему решает просто внешний шедулер, и стандартного хватит. Когда появляется слово «динамика», стандартный шедулер уходит в закат

А за библиотечки спасибо — celery-redbeat выглядит поприятнее, чем redisbeat. python-redis-lock интересен тем, что он идёт в поставке с celery-redbeat
Ох, точно, это и была та самая причина, по которой я отбросил затею с классами Task. Знатно подо мной тогда стул прогорел — а в чём смысл класса?

А обработку ошибок я в примерах и предложил направить в метод task. Разве что всё под рукой — в базовом классе, а не снаружи

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность

Специализация

Fullstack Developer
Senior
Git
Linux
SQL
Python
OOP
MySQL
PostgreSQL
Docker
Nginx
High-loaded systems