19 марта 2024

comet (push) serverПару месяцев назад устроился на обычную работу. Больше для дисциплины, но и деньги кончились от двухмесячного валяния дурака. Делаем там внутреннюю систему продвижения собственных сайтов. Довольно много процедур длительных и вынесены в фон. Но красиво же, когда состояние задач обновляется автоматически. Погуглил Websocket comet-серверы. Ничего интересного не нашел. Все какое-то навороченное: с базами данных, кучей зависимостей. Решил написать свой простенький. Можно было писать на питоне и asyncio, но мне показалось, что такую задачу лучше решить микросервисом на Go. Получилось вроде неплохо. Нужные задачи выполняет хорошо. Хотя есть куда развивать. Итак, собственно сам Golang Push-server.

А теперь, как им пользоваться:

На странице нужно подключить скрипт pusher.js.

А затем подписаться на любое событие:

pushSub(«событие»,function(obj) {});

В коллбэк передается объект от сервера. Я использую такую маркировку: событие: «канал.приложение.объект[.ид_объекта, если нужен]». Сервер передает {«id»:123, «status»: «completed»}

Отписаться от события можно с помощью

pushUnsub(«событие»);

В python/django можно приложениях можно воспользоваться готовым модулем pusher.py:

from pusher import push_intent
push_intent(intent, obj)

В качестве объекта можно передать строку, словарь, список или ничего. Событие всегда строковое. Сервер находит подписчика на именно это событие и отправляет ему оповещение. В будущем можно будет реализовать маску типа «channel.app.*».

Теперь, как это работает на более низком уровне:

При загрузке страницы клиент подключается к ws://сервер:8095/sub (порт пока фиксированный) и отправляет:

{«op»: «sub», «intent»: «channelname.taskname.12345»}

Сервер пока ничего не возвращает. Если сообщение отправилось, значит подписка активна.

Приложение на сервере просто отправляет post/get запрос:

http://сервер:8095/pub?intent=channelname.taskname.12345?obj={«id»:123}

И если push-сервер находит подключенного подписанного клиента, отправляет ему сообщение вида:

{«op»: «intent», «intent»: «channelname.taskname.12345», «obj»: {\»id\»:123}»}

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