All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.pubnub.api.managers.ReconnectionManager.kt Maven / Gradle / Ivy

Go to download

PubNub is a cross-platform client-to-client (1:1 and 1:many) push service in the cloud, capable of broadcasting real-time messages to millions of web and mobile clients simultaneously, in less than a quarter second!

There is a newer version: 10.2.0
Show newest version
package com.pubnub.api.managers

import com.pubnub.api.PNConfiguration
import com.pubnub.api.PubNub
import com.pubnub.api.callbacks.ReconnectionCallback
import com.pubnub.api.enums.PNReconnectionPolicy
import org.slf4j.LoggerFactory
import java.util.Calendar
import java.util.Timer
import java.util.TimerTask
import kotlin.math.pow

internal class ReconnectionManager(val pubnub: PubNub) {

    private val log = LoggerFactory.getLogger("ReconnectionManager")

    private companion object {
        private const val LINEAR_INTERVAL = 3
        private const val MIN_EXPONENTIAL_BACKOFF = 1
        private const val MAX_EXPONENTIAL_BACKOFF = 32

        private const val MILLISECONDS = 1000
    }

    internal lateinit var reconnectionCallback: ReconnectionCallback

    private var exponentialMultiplier = 1
    private var failedCalls = 0

    private lateinit var pnReconnectionPolicy: PNReconnectionPolicy
    private var maxConnectionRetries = -1

    private var timer: Timer? = null

    internal fun startPolling(pnConfiguration: PNConfiguration) {
        pnReconnectionPolicy = pnConfiguration.reconnectionPolicy
        maxConnectionRetries = pnConfiguration.maximumReconnectionRetries

        if (isReconnectionPolicyUndefined())
            return

        exponentialMultiplier = 1
        failedCalls = 0

        registerHeartbeatTimer()
    }

    private fun registerHeartbeatTimer() {
        // make sure only one timer is running at a time.
        stopHeartbeatTimer()

        if (isReconnectionPolicyUndefined()) {
            return
        }

        if (maxConnectionRetries != -1 && failedCalls >= maxConnectionRetries) {
            reconnectionCallback.onMaxReconnectionExhaustion()
            return
        }
        timer = Timer("Reconnection Manager timer", true)
        timer?.schedule(
            object : TimerTask() {
                override fun run() {
                    callTime()
                }
            },
            getBestInterval() * MILLISECONDS.toLong()
        )
    }

    private fun getBestInterval(): Int {
        var timerInterval = LINEAR_INTERVAL
        if (pnReconnectionPolicy == PNReconnectionPolicy.EXPONENTIAL) {
            timerInterval = (2.0.pow(exponentialMultiplier.toDouble()) - 1).toInt()
            if (timerInterval > MAX_EXPONENTIAL_BACKOFF) {
                timerInterval = MIN_EXPONENTIAL_BACKOFF
                exponentialMultiplier = 1
                log.info("timerInterval > MAXEXPONENTIALBACKOFF at: " + Calendar.getInstance().time.toString())
            } else if (timerInterval < 1) {
                timerInterval = MIN_EXPONENTIAL_BACKOFF
            }
            log.info("timerInterval = " + timerInterval + " at: " + Calendar.getInstance().time.toString())
        }
        if (pnReconnectionPolicy == PNReconnectionPolicy.LINEAR) {
            timerInterval = LINEAR_INTERVAL
        }
        return timerInterval
    }

    private fun stopHeartbeatTimer() {
        timer?.cancel()
    }

    private fun callTime() {
        pubnub.time()
            .async { _, status ->
                if (!status.error) {
                    stopHeartbeatTimer()
                    reconnectionCallback.onReconnection()
                } else {
                    log.info("callTime at ${System.currentTimeMillis()}")
                    exponentialMultiplier++
                    failedCalls++
                    registerHeartbeatTimer()
                }
            }
    }

    private fun isReconnectionPolicyUndefined(): Boolean {
        if (pnReconnectionPolicy == PNReconnectionPolicy.NONE) {
            log.info("reconnection policy is disabled, please handle reconnection manually.")
            return true
        }
        return false
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy