Cometd: несколько вкладок для управления онлайн-пользователями, создающими ложный онлайн-статус

Я работаю над веб-приложением на основе Spring-MVC, которое использует Cometd для чата. Для управления в режиме реального времени, какой пользователь находится в сети, мы отправляем уведомления, когда пользователь находится в сети. Итак, когда окно закрыто, уведомления не появляются, и через 30 секунд определяется, что пользователь не в сети или недоступен.

Теперь проблема возникает, когда пользователь использует несколько браузеров. Давайте просто оставим это на 2 сейчас. Итак, через 10 минут мы устанавливаем статус пользователя «Вдали от клавиатуры» (AFK). Но если пользователь находится в сети в одном браузере, то мы получаем мигающий статус, в течение нескольких секунд из-за того, что браузер находится в «Режиме ожидания», мы получаем AFK, а с активной машины мы получаем статус «Доступен».

Как мы можем решить эту проблему? Любые идеи, предложения. Я думал об использовании логического флага и пары с IP-адресом, который будет проверяться перед перезаписью уведомления, но у него есть проблема с устаревшими уведомлениями.

Это мой код для отправки уведомлений онлайн всем слушателям (друзьям пользователя).

Код :

 @Listener(value = "/service/online")
    public void OnlineNotifications(ServerSession remote, ServerMessage.Mutable message) {
        Person sender = this.personService.getCurrentlyAuthenticatedUser();
        Map<String, Object> input = message.getDataAsMap();
        String onlineStatus = (String) input.get("status");
        Map<String, Object> output = new HashMap<>();
        output.put("status", onlineStatus);
        output.put("id", sender.getId());
        ServerChannel serverChannel = bayeux.createChannelIfAbsent("/online/" + sender.getId()).getReference();
        serverChannel.setPersistent(true);
        serverChannel.publish(serverSession, output);
    }

Любые идеи приветствуются. Большое спасибо. :-)


person We are Borg    schedule 20.07.2015    source источник


Ответы (1)


Ваше приложение может легко связать несколько устройств с одним и тем же userName. Вы можете сделать это из своего SecurityPolicy, просто свяжите строку userName с List<ServerSession> или любой другой структурой данных, которая лучше подходит для вашего случая.

Таким образом, ваше онлайн-состояние для определенного userName является функцией всех ServerSession этого конкретного userName. Таким образом, это сопоставление userName со списком онлайн-состояний.

Если представить, что пользователь bob зашел в систему из двух браузеров, сопоставление его онлайн-статуса может быть следующим:

"bob" -> ["afk", "online"]

Чтобы вычислить онлайн-статус для bob, вы просто просматриваете все онлайн-статусы для каждого ServerSession, и если есть хотя бы один online, то он онлайн, если все afk, то он не на клавиатуре и так далее.

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

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

person sbordet    schedule 25.07.2015
comment
Это помогло, но я реализовал свою собственную структуру данных, которая показалась мне более удобной для удовлетворения требований. Большое спасибо. :-) - person We are Borg; 31.07.2015
comment
Привет, у меня возникла проблема с запуском кода консольного чата для Cometd, так как библиотечный метод (из BayeuxClient) не работает. Не могли бы вы проверить это редактирование сообщений: stackoverflow.com/questions/33668915/ - person We are Borg; 12.11.2015