• Почему я вижу stdout app'а из контейнера в /var/log/syslog хоста, хотя ничего не настраивал?

    @wawa Автор вопроса
    rustler2000, зачем мне две системы (системд и докер), отвечающие за перезапуск упавших процессов. Лучше одну юзать -> меньше энтропии. А от системд я избавиться не могу, она же и запуском занимается при старте сервера, поэтому за контейнерами она и следит.
  • Каков порядок проектирования веб сервиса?

    @wawa Автор вопроса
    ок. и так продолжая мой список:
    3) схема БД
    4) ендпойнты АПИ
    5) UI
    так?
    а когда на 5ом шаге взаимодействие UI<->API приводит к N+1 проблеме, это признак ошибки на более раннем шаге или это норм и просто нужно подпилить API?
  • Каков порядок проектирования веб сервиса?

    @wawa Автор вопроса
    stratosmi, ок. Но и для MVP нужен какой-никакой алгоритм (последовательность) разработки. Можно объяснить как вы это делаете касаемо пунктов а,б,в?
  • Каков порядок проектирования веб сервиса?

    @wawa Автор вопроса
    Артемий Прототипы, спасибо. То что вы описали - это всё делается до /во время шага (2). А что потом? я имею ввиду пункты а,б,в. Можно именно по этим пунктам пройтись?
  • Каков порядок проектирования веб сервиса?

    @wawa Автор вопроса
    извините, но вопрос не об этом
  • Зачем нужен Swagger/OpenAPI?

    @wawa Автор вопроса
    NaName, не вижу как исключать возвращаемые поля. Может тыкнуть где это?
  • Зачем нужен Swagger/OpenAPI?

    @wawa Автор вопроса
    NaName, в бест практис рекомендуют в GET запросах юзать поле "fields", которое указывает какие поля нужно вернуть: site.ru/api/users?age=22&sex=f&fields=name,salary - где age и sex это фильтр, а fields - интересующие поля. Swagger спека это как-то учитывает?
    Вы пишите, что в yaml указывается и формат ответа. Swagger спека это учитывает (что могут вернуться не все поля из-за "fields")?
  • Как отменять таски, которые уже в очереди?

    @wawa Автор вопроса
    dimonchik2013, если чистить очередь, то потеряются и актуальные таски. Хотя может я вас не правильно понял - можно объяснить?
  • Как отменять таски, которые уже в очереди?

    @wawa Автор вопроса
    dimonchik2013, ну это не серьезно.
    Мне нужно решение без допиливания существующих технологиях.
    Вообще идея есть, но боюсь велосипед изобрести.
  • Как отменять таски, которые уже в очереди?

    @wawa Автор вопроса
    dimonchik2013 ок. снабдил я айдишником каждый таск. но он уже в очереди (rabbit например), как теперь изъять его оттуда?
  • Порядок вызовов asyncio.Event.set() гарантированно соответствует порядку пробуждения висящих на них корутин?

    @wawa Автор вопроса
    Владимир Олохтонов, спасибо.
    (2) - это что-то вроде заглушки, имитирующей вызов какой-то другой await-операции. Сильно обращать на это внимание не стоит.
    Вы в фиксированном порядке вызываете ev.set(), что приводит к точно такому-же фиксированному порядку оповещения подписчиков.

    Да, в фиксированном порядке я устанавливаю флаг пробуждения. Но обязательно ли этот порядок сохраниться относительно самого пробуждения корутин? Иными словами обладает ли планировщик внутренней очередью, в которую попадает корутина после соответствующего ей ev.set()? Ведь технически эта очередь может отсутствовать. Хоть я и устанавливаю флаги пробуждения в фиксированном порядке, делаю я это строго выполняя только синхронные операции, не отдавая планировщику управление пока не пройдусь по всем ивентам. В итоге на момент передачи управления (второй вызов asyncio.sleep(2)), все корутины готовы выполняться и планировщик может запустить их в рандомном порядке, если только он (планировщик) не обладает внутренней очередью. Поэтому мой вопрос к этому и сводится: есть ли у него эта самая очередь? И насчет кода, вы абсолютно правы, но я не смог обнаружить эту очередь - сложновато для меня. Может у вас получится?
    Еще раз попробую немного переделать вопрос (наверно сумбурно изъясняюсь, ибо сложная для меня тема): непосредственно вызов ev.set() помещает ли соответствующую корутину (ждущую на этом Event) в предполагаемую мной очередь планировщика, тем самым гарантируя, что эта корутина продолжит своё выполнение раньше тех корутин, чьи ev.set() были вызваны позже и позже тех корутин, чьи ev.set() были вызваны раньше?
  • Как развить абстрактное мышление?

    @wawa
    Олег Петров, эту книгу не нужно просматривать. Нужно открыть страницу первую, вдумчиво прочитать, осознать и представить. Далее перейти к странице второй... Если что не понятно - to google. Не недооценивайте себя и не пугайтесь обилием формул. Вам не экзамен сдавать, дедлайна нет.
  • Как развить абстрактное мышление?

    @wawa
    https://www.ozon.ru/context/detail/id/21839075/
    Можно скачать бесплатно в эл. виде если...
    Очень плавное ведение рассуждений, постепенно повышаемый уровень абстракций. В общем гуд, сам часто читаю в метро, пока еду на работу.
  • Как работает Django channels?

    @wawa Автор вопроса
    wawa, с чего вы это взяли? Consumer'ы так же stateless.

    Сергей Горностаев, посмотрите на код консюмера из оф. тутора https://channels.readthedocs.io/en/latest/tutorial...
    В методе connect создаются переменные room_group_name и room_name и они доступны в методе disconnect и не только. connect вызывается в самом начале, а дисконнект в самом конце. Т.е. инстанс консюмера должен жить очень долго (минутами, часами, ...)

    from asgiref.sync import async_to_sync
    from channels.generic.websocket import WebsocketConsumer
    import json
    
    class ChatConsumer(WebsocketConsumer):
        def connect(self):
            self.room_name = self.scope['url_route']['kwargs']['room_name']
            self.room_group_name = 'chat_%s' % self.room_name
    
            # Join room group
            async_to_sync(self.channel_layer.group_add)(
                self.room_group_name,
                self.channel_name
            )
    
            self.accept()
    
        def disconnect(self, close_code):
            # Leave room group
            async_to_sync(self.channel_layer.group_discard)(
                self.room_group_name,
                self.channel_name
            )
    
        # Receive message from WebSocket
        def receive(self, text_data):
            text_data_json = json.loads(text_data)
            message = text_data_json['message']
    
            # Send message to room group
            async_to_sync(self.channel_layer.group_send)(
                self.room_group_name,
                {
                    'type': 'chat_message',
                    'message': message
                }
            )
    
        # Receive message from room group
        def chat_message(self, event):
            message = event['message']
    
            # Send message to WebSocket
            self.send(text_data=json.dumps({
                'message': message
            }))

    P.S: я работаю со 2ой версией channels
  • Как работает Django channels?

    @wawa Автор вопроса
    Сергей Горностаев, нет, коллега выше говорит об одной важной детали.
    uWSGI воркер (обычный инстанс джанги в CPython процессе ОС) - stateless, и поэтому, отработав на один http запрос, будет готов обработать другой.
    И поэтому неважно что воркеров меньше, чем клиентов, главное чтобы они успевали все запросы обработать. Т.е. здесь одно узкое место - производительность системы (бд например).
    Консюмеры же (я про синхронные), работают каждый в своем треде как воркеры uWSGI работают каждый в своем процессе (- тут отличие незначительное). И они (консюмеры) !привязаны каждый к своему клиенту (т.е. stateful). Поэтому консюмер-тред в отстутствие данных от своего клиента !не может обрабатывать сообщения от других клиентов и просто !впустую жрёт ресурсы (накладные расходы на содержание треда). Почему так? Почему консюмеры не stateless?
  • Как работает Django channels?

    @wawa Автор вопроса
    Roman Kitaev, Спасибо за ответы.
    Можно еще один вопрос, для меня краеугольный в понимании каналов.
    Почему [Daphne - консюмеры] не работают с вебсокетами также как [Nginx - uWSGI воркеры] работают с http?
    Я имею в виду, что данные по вебсокету делятся на сообщения, которые делятся на фреймы. В итоге в моем наивном понимании:
    1. Daphne, эффективно работая на epoll, собирает у себя в памяти(Redis?) фреймы
    2. Получив последний фрейм, отправляет уже целое сообщение в воркер.
    3. Воркер быстро обрабатывает сообщение и, если надо, отвечает Дафну. После чего он опять готов обрабатывать новые сообщения. Причем НЕВАЖНО от какого клиента.
    И в итоге не нужно (в синхронном случае) для каждого клиента юзать отдельный тред на !протяжении! всего соединения. Важно лишь сколько сообщений приходит !одновременно!.
    Почему это работает не так?
  • Как работает Django channels?

    @wawa Автор вопроса
    Сергей Горностаев, спасибо за ответ. Я тоже так думал. Это по аналогии того как 10 воркеров uWSGI обрабатывают тысячи запросов, которые проксирует NGINX. Я это понимаю.
    НО, как объясняет коллега выше, всё работает не так.
    Честно говоря, я сейчас не могу понять почему это не работает так, как вы описали.
  • Как работает Django channels?

    @wawa Автор вопроса
    Чтобы разобраться в азах технологии - читать исходники? O_o
    Насчет документации, да, ты прав - не дочитал.
    Тем не менее, тредпул ограничен и самое главное ASGI_THREADS и кол-во воркеров фиксировано в работе аппа. Т.е. желая остаться в синхронном коде мне нужно запастисть тредами впрок? При каких числах это становится ужасной идеей? 1000, 2000? Что-то не очень хорошая схема выходит.
    Что если использовать AsyncWebsocketConsumer и уже в нем использовать синхронные орм-запросы через тредпул? Ведь при увеличении коннектов к БД перфоманс растет только в самом начале, потом нет, и поэтому нет смысла в большом тредпуле. Так же эффективнее, верно?
  • Как работает Django channels?

    @wawa Автор вопроса
    Сергей Горностаев, конечно же я видел этот вопрос. Я раз 10 его перечитал, но там нет ответа на мой вопрос.