Реализация длинного опроса с модифицированными и kotlin каналами - PullRequest
2 голосов
/ 06 апреля 2020

Я пытаюсь реализовать длинный опрос, который учитывает жизненный цикл (в Activity / Fragment). Опрос будет ограничен фрагментом, который отправляет запрос API на сервер каждый фиксированный интервал времени. Однако я не могу его реализовать.

Вот как я хочу, чтобы реализация была похожа на

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

Рассмотрим:

HARD_TIMEOUT = 10 с

POLLING_INTERVAL = 2s enter image description here

 Request 1: Started at: 0sec      Response delay:1.2sec   Duration left: 0.8sec
 Request 2: Started at: 2sec      Response delay:0.4sec   Duration left: 1.6sec
 Request 3: Started at: 4sec      Response delay:2.5sec   Duration left: 0sec
 Request 4: Started at: 6.5sec    Response delay:0.5sec   Duration left: 1.0sec
 Request 5: Started at: 8sec      Response delay:0.8sec   Duration left: 1.2sec

В этом случае я хочу использовать опрос вместо сокета. Любая идея / решения будут оценены. Спасибо.

1 Ответ

0 голосов
/ 08 апреля 2020

ок, разобрался с решением для опроса с использованием каналов. это должно помочь кому-то в поиске примера.

    private val pollingChannel = Channel<Deferred<Result<OrderStatus>>>()
    val POLLING_TIMEOUT_DURATION = 10000L
    val POLLING_FREQUENCY = 2000L

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

    val pollingChannel = Channel<Deferred<Pair<Int,Int>>>()

QUEUE EXECUTOR : он выберет асиную задачу c и начнет выполнять ее в порядке FIFO.

    CoroutineScope(Dispatchers.IO).launch {
        for (i in pollingChannel) {
            val x = i.await()
            println("${SimpleDateFormat("mm:ss.SSS").format(Calendar.getInstance().time)} Request ${x.first}: value ${x.second}")
        }
    }

ФУНКЦИЯ ОПРОСА : добавляет асиную задачу c в канал опроса каждый фиксированный интервал времени до истечения времени ожидания.

    CoroutineScope(Dispatchers.IO).launch {
        var reqIndex = 1
        val timedOut = withTimeoutOrNull(POLLING_TIMEOUT_DURATION) {
            while (receiverJob.isActive) {
                pollingChannel.send(async {
                    getRandomNumber(reqIndex++)
                })
                delay(POLLING_FREQUENCY)
            }
        }
    }

АСИНХРОННАЯ ЭКСПЛУАТАЦИЯ

во избежание многословности ответа Я создал функцию со случайной задержкой, замените ее на требуемый вызов API

   private suspend fun getRandomNumber(index: Int): Pair<Int,Int> {
    val randomDuration = (1..6L).random() * 500
    delay(randomDuration)
    return Pair(index,(0..100).random())
}

SAMPLE OUTPUT

enter image description here

...