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

com.pubnub.api.endpoints.remoteaction.ComposableRemoteAction.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.endpoints.remoteaction

import com.pubnub.api.PubNubException
import com.pubnub.api.enums.PNOperationType
import com.pubnub.api.enums.PNStatusCategory
import com.pubnub.api.models.consumer.PNStatus

class ComposableRemoteAction(
    private val remoteAction: ExtendedRemoteAction,
    private val createNextRemoteAction: (T) -> ExtendedRemoteAction,
    private var checkpoint: Boolean
) : ExtendedRemoteAction {
    private var nextRemoteAction: ExtendedRemoteAction? = null
    private var isCancelled = false
    fun  then(factory: (U) -> ExtendedRemoteAction): ComposableRemoteAction {
        return ComposableRemoteAction(this, factory, false)
    }

    @Synchronized
    fun checkpoint(): ComposableRemoteAction {
        checkpoint = true
        return this
    }

    @Throws(PubNubException::class)
    override fun sync(): U? {
        return remoteAction.sync()?.let { result ->
            createNextRemoteAction(result).sync()
        }
    }

    override fun async(callback: (result: U?, status: PNStatus) -> Unit) {
        remoteAction.async { r: T?, s: PNStatus ->
            if (s.error) {
                callback(null, switchRetryReceiver(s))
            } else {
                try {
                    synchronized(this) {
                        if (!isCancelled) {
                            val newNextRemoteAction =
                                createNextRemoteAction(r!!) // if s is not error r shouldn't be null
                            nextRemoteAction = newNextRemoteAction
                            newNextRemoteAction.async { r2: U?, s2: PNStatus ->
                                if (s2.error) {
                                    callback(null, switchRetryReceiver(s2))
                                } else {
                                    callback(r2, switchRetryReceiver(s2))
                                }
                            }
                        }
                    }
                } catch (ex: PubNubException) {
                    callback(
                        null,
                        PNStatus(
                            category = PNStatusCategory.PNBadRequestCategory,
                            error = true,
                            operation = operationType()
                        )
                    )
                }
            }
        }
    }

    private fun switchRetryReceiver(s: PNStatus): PNStatus {
        return s.copy().apply { executedEndpoint = this@ComposableRemoteAction }
    }

    @Synchronized
    override fun retry() {
        if (checkpoint && nextRemoteAction != null) {
            nextRemoteAction!!.retry()
        } else {
            remoteAction.retry()
        }
    }

    @Synchronized
    override fun silentCancel() {
        isCancelled = true
        remoteAction.silentCancel()
        if (nextRemoteAction != null) {
            nextRemoteAction!!.silentCancel()
        }
    }

    override fun operationType(): PNOperationType {
        return nextRemoteAction?.operationType() ?: remoteAction.operationType()
    }

    class ComposableBuilder(private val remoteAction: ExtendedRemoteAction) {
        private var checkpoint = false
        fun  then(factory: (T) -> ExtendedRemoteAction): ComposableRemoteAction {
            return ComposableRemoteAction(remoteAction, factory, checkpoint)
        }

        fun checkpoint(): ComposableBuilder {
            checkpoint = true
            return this
        }
    }

    companion object {
        fun  firstDo(remoteAction: ExtendedRemoteAction): ComposableBuilder {
            return ComposableBuilder(remoteAction)
        }
    }
}