Как правильно сохранить данные, которые будут отправлены с сервера на клиент через сокет после того, как клиент восстановит sh потерянное соединение - PullRequest
1 голос
/ 26 мая 2020

У меня .net core написано api и android mobile клиент. Между двумя из них установлено соединение signalr через сокет. Когда пользователь открывает event в мобильном приложении, я сохраняю этот event data в db на сервере и отправляю его другому users, который прослушивает event creator через сокет.
Я периодически контролирую соединение сокетов в мобильном приложении, и я могу повторно подключить их, если они потеряли соединение. У меня пока нет проблем .. Но у меня проблема с сохранением data для lost connection user

Позвольте мне объяснить на примере:
Есть пользователи: Producer1, Consumer1, Consumer2
Если Producer1 открывает событие через mobile app. Он отправляет data на server через httprequest, и я сохраняю его в db.
После сохранения данных в db, я отправляю это data на Consumer1 и Consumer2 через socket connection. Допустим, у Consumer2 нет сетевого подключения при отправке event data.
Consumer1, у которых есть сетевое подключение, успешно получает data, и у меня нет проблем с Consumer1.
Но, Consumer2 не смог получить data, потому что он потерял соединение с сокетом, и мы еще не подключились повторно. Отправленного event data уже нет. Таким образом, Consumer2 не получит event data.

Мой вопрос в том, как я могу сохранить data и отправить его за Consumer2, когда только Consumer2 reestabli sh его соединение. Каков эффективный и правильный способ сделать это?

Пример кода на стороне сервера:

    public async Task AddEvent(GetEventOutput getEventOutput)
    {
        if(getEventOutput.Active)
        {
            await _hubContext.Clients.Group(SignalR_EVENT + QUESTION_MARK + EVENT_WITH_USER + EQUAL_DASH + getEventOutput.UserID).SendAsync(CREATE_EVENT_ON_MOBILE, JsonConvert.SerializeObject(getEventOutput));
            sendEventCreateNotification(getEventOutput);
        }
    }

Пример кода на стороне клиента:

    hubConnection.on(CREATE_EVENT_ON_MOBILE, (getEventOutput) -> {
        System.out.println("CREATE_EVENT_ON_MOBILE : ");
        setUiAfterSignalrHandler.post(new Runnable() {
            @Override
            public void run() {
                if (!isNullOrEmpty(getEventOutput)) {
                    Event event = gson.fromJson(getEventOutput, Event.class);
                    eventsWithTimerRecyclerViewAdapter.insertItem(0, event);
                    setUiAfterSignalrHandler.removeCallbacks(this);
                    leftAndRightTextWithTimerRecyclerView.removeEmptyPlaceHolder(eventsWithTimerRecyclerViewAdapter);
                }
            }
        });
        restartSocket();
    }, String.class);

1 Ответ

1 голос
/ 26 мая 2020

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

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

Но для этого у вас должно быть:

  • Список всех подключенных клиентов, которые хотят получить событие.
  • Хранилище для этих событий (мы используем Cosmos Db но кеш будет работать хорошо).

Таким образом, вы не удалите событие, пока оно не будет завершено. Но тогда как вы повторно отправляете событие пользователю, который не был подключен в то время?

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

...