Сервер отправляет события с помощью Pyramid - как определить, потеряно ли соединение с клиентом - PullRequest
1 голос
/ 17 марта 2019

У меня есть приложение-пирамида, которое отправляет сообщения SSE. Это работает в основном так:

def message_generator():
    for i in range(100):
        print("Sending message:" + str(i))
        yield "data: %s\n\n" % json.dumps({'message': str(i)})
        time.sleep(random.randint(1, 10))

@view_config(route_name='events')
def events(request):
    headers = [('Content-Type', 'text/event-stream'),
               ('Cache-Control', 'no-cache')]
    response = Response(headerlist=headers)
    response.app_iter = message_generator()
    return response

Когда я просматриваю / events, я получаю события. Когда я перехожу на другую страницу, события останавливаются, когда я закрываю браузер, события останавливаются.

Проблема возникает, например, если я нахожусь в / события и я выключаю компьютер . Сервер не знает, что клиент потерян, и message_generator продолжает отправлять сообщения в void.

На этой странице: Взгляд на отправленные сервером события упомяните это:

... сервер должен обнаружить это (когда клиент останавливается) и остановить отправка дальнейших событий, поскольку клиент больше их не слушает Если сервер этого не делает, то по сути он будет отправлять события в пустоту.

Есть ли способ обнаружить это с помощью пирамиды? Я пробовал с

request.add_finished_callback()

но этот обратный вызов, кажется, вызывается с

return response

Я использую Gunicorn с gevent для запуска сервера.

Любая идея высоко ценится

1 Ответ

0 голосов
/ 26 марта 2019

из PEP 3333:

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

Обычно сервер WSGI «должен» вызывать метод close() на app_iter, когда клиент отключается (все генераторы, такие как в вашем примере, поддерживают это автоматически). Однако для этого не требуется сервер, и, похоже, многие серверы WSGI этого не делают. Например, вы упомянули gunicorn (который я не проверил самостоятельно), но я проверил, что официантка тоже не делает. В результате я открыл [1] для официантки и работал над исправлением. Потоковые ответы в средах WSGI в лучшем случае шатки и обычно зависят от сервера. Например, для официантки необходимо установить send_bytes=0, чтобы избежать буферизации данных ответа.

[1] https://github.com/Pylons/waitress/issues/236

...