Уведомлять вакансии, когда заканчивается другая работа

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

Как я могу сделать это с помощью сопрограмм?


person Gabrielle    schedule 16.04.2019    source источник
comment
Этот вопрос довольно непонятный. Кроме того, это звучит как просьба о полной дизайнерской / дизайнерской идее, а не решение одной конкретной проблемы, и приглашение к обсуждению вместо определенных ответов.   -  person Marko Topolnik    schedule 16.04.2019
comment
@MarkoTopolnik Спасибо за ответ. Я думаю, вы правы. Перед этим вопросом я написал еще один: stackoverflow.com/questions/55647810/ Может быть, эти вопросы вместе помогут прояснить мою проблему.   -  person Gabrielle    schedule 16.04.2019
comment
У меня много классов на уровне обслуживания, каждый делает запросы к серверу для определенных сущностей. Например, MessageService отправляет запрос на получение всех сообщений с сервера. Когда он возвращается со статусом 401 http, AuthenticationService запускает запрос refreshToken. Я нашел решение отправить при обратном вызове обновления что-то, что указывает на то, что токен был успешно обновлен, но это заставляет каждое задание воссоздавать его при получении этой информации от refreshToken. Я новичок в Coroutine, и я спросил, есть ли способ подписаться на задание, узнать, когда оно будет завершено и т. Д.   -  person Gabrielle    schedule 16.04.2019
comment
@MarkoTopolnik invokeOnCompletion - это решение с обратным вызовом, как я упоминал выше. Возможно ли с актером, каналами? Я не знаю, как ими пользоваться.   -  person Gabrielle    schedule 16.04.2019
comment
Вы также можете использовать job.onJoin в операторе select.   -  person Marko Topolnik    schedule 17.04.2019


Ответы (1)


Сначала давайте определим, как обновляется токен:

1) Если запроса на обновление токена еще нет, запустите новый

2) Если что-то уже происходит, просто подождите.

В Котлине это можно было бы записать как:

  var retrieveToken : Deferred<String>? = null

  suspend fun getToken(refresh: Boolean = false): String {
    if(retrieveToken == null || refresh && !retrieveToken.isActive)
      retrieveToken = async { API.getToken() }
    return retrieveToken.await()
  }

Теперь повторить попытку API становится довольно просто:

  suspend fun requestAPIAndRetry(api: String) {
     try {
       val token = getToken()
       val result = API.call(api, token)
     } catch(error) {
      // verifiy if it is 401
      val token = getToken(refresh = true)
      var result = API.call(api, token)
    }
 }

Теперь, если запросы начинают терпеть неудачу, происходит следующее:

1) Первый вызов getToken(refresh = true) запустит запрос к API и вернет его.

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

3) Если токен есть, отложенное разрешение разрешится, и все API будут повторять попытку (возможно, даже параллельно).

person Jonas Wilms    schedule 16.04.2019