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

com.pubnub.api.subscribe.eventengine.state.SubscribeState.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.subscribe.eventengine.state

import com.pubnub.api.PubNubException
import com.pubnub.api.enums.PNOperationType
import com.pubnub.api.enums.PNStatusCategory
import com.pubnub.api.eventengine.State
import com.pubnub.api.eventengine.noTransition
import com.pubnub.api.eventengine.transitionTo
import com.pubnub.api.models.consumer.PNStatus
import com.pubnub.api.subscribe.eventengine.effect.SubscribeEffectInvocation
import com.pubnub.api.subscribe.eventengine.event.SubscribeEvent
import com.pubnub.api.subscribe.eventengine.event.SubscriptionCursor

internal sealed class SubscribeState : State {
    object Unsubscribed : SubscribeState() {
        override fun transition(event: SubscribeEvent): Pair> {
            return when (event) {
                is SubscribeEvent.SubscriptionChanged -> {
                    transitionTo(Handshaking(event.channels, event.channelGroups))
                }

                is SubscribeEvent.SubscriptionRestored -> {
                    transitionTo(Handshaking(event.channels, event.channelGroups, event.subscriptionCursor))
                }

                else -> {
                    noTransition()
                }
            }
        }
    }

    data class Handshaking(
        val channels: Set,
        val channelGroups: Set,
        val subscriptionCursor: SubscriptionCursor? = null,
    ) : SubscribeState() {
        override fun onEntry() = setOf(SubscribeEffectInvocation.Handshake(channels, channelGroups))
        override fun onExit() = setOf(SubscribeEffectInvocation.CancelHandshake)

        override fun transition(event: SubscribeEvent): Pair> {
            return when (event) {
                is SubscribeEvent.HandshakeSuccess -> {
                    transitionTo(
                        state = Receiving(
                            channels,
                            channelGroups,
                            subscriptionCursor?.copy(region = event.subscriptionCursor.region)
                                ?: event.subscriptionCursor
                        ),
                        SubscribeEffectInvocation.EmitStatus(
                            PNStatus(
                                category = PNStatusCategory.PNConnectedCategory,
                                operation = PNOperationType.PNSubscribeOperation,
                                error = false,
                                affectedChannels = channels.toList(),
                                affectedChannelGroups = channelGroups.toList()
                            )
                        )
                    )
                }

                is SubscribeEvent.SubscriptionRestored -> {
                    transitionTo(Handshaking(event.channels, event.channelGroups, event.subscriptionCursor))
                }

                is SubscribeEvent.HandshakeFailure -> {
                    transitionTo(HandshakeReconnecting(channels, channelGroups, 0, event.reason, subscriptionCursor))
                }

                is SubscribeEvent.SubscriptionChanged -> {
                    transitionTo(Handshaking(event.channels, event.channelGroups))
                }

                is SubscribeEvent.Disconnect -> {
                    transitionTo(HandshakeStopped(channels, channelGroups, reason = null))
                }

                is SubscribeEvent.UnsubscribeAll -> {
                    transitionTo(Unsubscribed)
                }

                else -> {
                    noTransition()
                }
            }
        }
    }

    data class HandshakeReconnecting(
        val channels: Set,
        val channelGroups: Set,
        val attempts: Int,
        val reason: PubNubException?,
        val subscriptionCursor: SubscriptionCursor? = null
    ) : SubscribeState() {
        override fun onEntry() =
            setOf(SubscribeEffectInvocation.HandshakeReconnect(channels, channelGroups, attempts, reason))

        override fun onExit() = setOf(SubscribeEffectInvocation.CancelHandshakeReconnect)

        override fun transition(event: SubscribeEvent): Pair> {
            return when (event) {
                is SubscribeEvent.HandshakeReconnectFailure -> {
                    transitionTo(
                        HandshakeReconnecting(
                            this.channels, this.channelGroups, this.attempts + 1, event.reason, subscriptionCursor
                        )
                    )
                }

                is SubscribeEvent.SubscriptionChanged -> {
                    transitionTo(Handshaking(event.channels, event.channelGroups, subscriptionCursor))
                }

                is SubscribeEvent.Disconnect -> {
                    transitionTo(HandshakeStopped(channels, channelGroups, reason))
                }

                is SubscribeEvent.HandshakeReconnectGiveup -> {
                    transitionTo(
                        HandshakeFailed(channels, channelGroups, event.reason),
                        SubscribeEffectInvocation.EmitStatus(
                            PNStatus(
                                category = PNStatusCategory.PNConnectionError,
                                operation = PNOperationType.PNSubscribeOperation,
                                error = true,
                                affectedChannels = channels.toList(),
                                affectedChannelGroups = channelGroups.toList(),
                                exception = reason
                            )
                        )
                    )
                }

                is SubscribeEvent.HandshakeReconnectSuccess -> {
                    transitionTo(
                        state = Receiving(channels, channelGroups, subscriptionCursor ?: event.subscriptionCursor),
                        SubscribeEffectInvocation.EmitStatus(
                            PNStatus(
                                category = PNStatusCategory.PNConnectedCategory,
                                operation = PNOperationType.PNSubscribeOperation,
                                error = false,
                                affectedChannels = channels.toList(),
                                affectedChannelGroups = channelGroups.toList()
                            )
                        )
                    )
                }

                is SubscribeEvent.SubscriptionRestored -> {
                    transitionTo(Handshaking(event.channels, event.channelGroups, event.subscriptionCursor))
                }

                is SubscribeEvent.UnsubscribeAll -> {
                    transitionTo(Unsubscribed)
                }

                else -> {
                    noTransition()
                }
            }
        }
    }

    data class HandshakeStopped(
        val channels: Set,
        val channelGroups: Set,
        val reason: PubNubException?
    ) : SubscribeState() {

        override fun transition(event: SubscribeEvent): Pair> {
            return when (event) {
                is SubscribeEvent.Reconnect -> {
                    transitionTo(Handshaking(channels, channelGroups))
                }

                is SubscribeEvent.SubscriptionChanged -> {
                    transitionTo(
                        HandshakeStopped(
                            event.channels,
                            event.channelGroups,
                            reason = null
                        )
                    )
                }

                is SubscribeEvent.SubscriptionRestored -> {
                    transitionTo(
                        HandshakeStopped(
                            event.channels,
                            event.channelGroups,
                            reason = null
                        )
                    )
                }

                is SubscribeEvent.UnsubscribeAll -> {
                    transitionTo(Unsubscribed)
                }

                else -> {
                    noTransition()
                }
            }
        }
    }

    data class HandshakeFailed(
        val channels: Set,
        val channelGroups: Set,
        val reason: PubNubException,
        val subscriptionCursor: SubscriptionCursor? = null
    ) : SubscribeState() {

        override fun transition(event: SubscribeEvent): Pair> {
            return when (event) {
                is SubscribeEvent.SubscriptionChanged -> {
                    transitionTo(Handshaking(event.channels, event.channelGroups))
                }

                is SubscribeEvent.SubscriptionRestored -> {
                    transitionTo(
                        Handshaking(
                            event.channels, event.channelGroups, event.subscriptionCursor
                        )
                    )
                }

                is SubscribeEvent.Reconnect -> {
                    transitionTo(Handshaking(channels, channelGroups))
                }

                is SubscribeEvent.UnsubscribeAll -> {
                    transitionTo(Unsubscribed)
                }

                else -> {
                    noTransition()
                }
            }
        }
    }

    data class Receiving(
        private val channels: Set,
        private val channelGroups: Set,
        private val subscriptionCursor: SubscriptionCursor
    ) : SubscribeState() {
        override fun onEntry() = setOf(
            SubscribeEffectInvocation.ReceiveMessages(
                channels, channelGroups, subscriptionCursor
            )
        )

        override fun onExit() = setOf(SubscribeEffectInvocation.CancelReceiveMessages)

        override fun transition(event: SubscribeEvent): Pair> {

            return when (event) {
                is SubscribeEvent.ReceiveFailure -> {
                    transitionTo(
                        ReceiveReconnecting(
                            channels, channelGroups, subscriptionCursor, 0, event.reason
                        )
                    )
                }

                is SubscribeEvent.Disconnect -> {
                    transitionTo(
                        state = ReceiveStopped(channels, channelGroups, subscriptionCursor),
                        SubscribeEffectInvocation.EmitStatus(
                            PNStatus(
                                category = PNStatusCategory.PNDisconnectedCategory,
                                operation = PNOperationType.PNDisconnectOperation,
                                error = false,
                                affectedChannels = channels.toList(),
                                affectedChannelGroups = channelGroups.toList()
                            )
                        )
                    )
                }

                is SubscribeEvent.SubscriptionChanged -> {
                    transitionTo(Receiving(event.channels, event.channelGroups, subscriptionCursor))
                }

                is SubscribeEvent.SubscriptionRestored -> {
                    transitionTo(Receiving(event.channels, event.channelGroups, event.subscriptionCursor))
                }

                is SubscribeEvent.ReceiveSuccess -> {
                    transitionTo(
                        state = Receiving(channels, channelGroups, event.subscriptionCursor),
                        SubscribeEffectInvocation.EmitMessages(event.messages)
                    )
                }

                is SubscribeEvent.UnsubscribeAll -> {
                    transitionTo(
                        state = Unsubscribed,
                        SubscribeEffectInvocation.EmitStatus(
                            PNStatus(
                                category = PNStatusCategory.PNDisconnectedCategory,
                                operation = PNOperationType.PNUnsubscribeOperation,
                                error = false,
                                affectedChannels = channels.toList(),
                                affectedChannelGroups = channelGroups.toList()
                            )
                        )
                    )
                }

                else -> {
                    noTransition()
                }
            }
        }
    }

    data class ReceiveReconnecting(
        val channels: Set,
        val channelGroups: Set,
        val subscriptionCursor: SubscriptionCursor,
        val attempts: Int,
        val reason: PubNubException?
    ) : SubscribeState() {
        override fun onEntry() =
            setOf(
                SubscribeEffectInvocation.ReceiveReconnect(
                    channels,
                    channelGroups,
                    subscriptionCursor,
                    attempts,
                    reason
                )
            )

        override fun onExit() = setOf(SubscribeEffectInvocation.CancelReceiveReconnect)

        override fun transition(event: SubscribeEvent): Pair> {
            return when (event) {
                is SubscribeEvent.ReceiveReconnectFailure -> {
                    transitionTo(
                        ReceiveReconnecting(
                            channels, channelGroups, subscriptionCursor, attempts + 1, event.reason
                        )
                    )
                }

                is SubscribeEvent.SubscriptionChanged -> {
                    transitionTo(
                        Receiving(event.channels, event.channelGroups, subscriptionCursor)
                    )
                }

                is SubscribeEvent.Disconnect -> {
                    transitionTo(
                        ReceiveStopped(channels, channelGroups, subscriptionCursor),
                        SubscribeEffectInvocation.EmitStatus(
                            PNStatus(
                                category = PNStatusCategory.PNDisconnectedCategory,
                                operation = PNOperationType.PNDisconnectOperation,
                                error = false,
                                affectedChannels = channels.toList(),
                                affectedChannelGroups = channelGroups.toList()
                            )
                        )
                    )
                }

                is SubscribeEvent.ReceiveReconnectGiveup -> {
                    transitionTo(
                        state = ReceiveFailed(channels, channelGroups, subscriptionCursor, event.reason),
                        SubscribeEffectInvocation.EmitStatus(
                            PNStatus(
                                category = PNStatusCategory.PNUnexpectedDisconnectCategory,
                                operation = PNOperationType.PNSubscribeOperation,
                                error = false,
                                affectedChannels = channels.toList(),
                                affectedChannelGroups = channelGroups.toList()
                            )
                        )
                    )
                }

                is SubscribeEvent.ReceiveReconnectSuccess -> {
                    transitionTo(
                        state = Receiving(channels, channelGroups, event.subscriptionCursor),
                        SubscribeEffectInvocation.EmitMessages(event.messages),
                    )
                }

                is SubscribeEvent.SubscriptionRestored -> {
                    transitionTo(Receiving(event.channels, event.channelGroups, subscriptionCursor))
                }

                is SubscribeEvent.UnsubscribeAll -> {
                    transitionTo(
                        state = Unsubscribed,
                        SubscribeEffectInvocation.EmitStatus(
                            PNStatus(
                                category = PNStatusCategory.PNDisconnectedCategory,
                                operation = PNOperationType.PNUnsubscribeOperation,
                                error = false,
                                affectedChannels = channels.toList(),
                                affectedChannelGroups = channelGroups.toList()
                            )
                        )
                    )
                }

                else -> {
                    noTransition()
                }
            }
        }
    }

    data class ReceiveStopped(
        private val channels: Set,
        val channelGroups: Set,
        val subscriptionCursor: SubscriptionCursor
    ) : SubscribeState() {
        override fun transition(event: SubscribeEvent): Pair> {
            return when (event) {
                is SubscribeEvent.Reconnect -> {
                    transitionTo(Handshaking(channels, channelGroups, subscriptionCursor))
                }

                is SubscribeEvent.SubscriptionChanged -> {
                    transitionTo(
                        ReceiveStopped(
                            event.channels,
                            event.channelGroups,
                            subscriptionCursor
                        )
                    )
                }

                is SubscribeEvent.SubscriptionRestored -> {
                    transitionTo(
                        ReceiveStopped(
                            event.channels,
                            event.channelGroups,
                            event.subscriptionCursor
                        )
                    )
                }

                is SubscribeEvent.UnsubscribeAll -> {
                    transitionTo(Unsubscribed)
                }

                else -> {
                    noTransition()
                }
            }
        }
    }

    data class ReceiveFailed(
        private val channels: Set,
        val channelGroups: Set,
        val subscriptionCursor: SubscriptionCursor,
        val reason: PubNubException
    ) : SubscribeState() {
        override fun transition(event: SubscribeEvent): Pair> {
            return when (event) {
                is SubscribeEvent.Reconnect -> {
                    transitionTo(Handshaking(channels, channelGroups, subscriptionCursor))
                }

                is SubscribeEvent.SubscriptionChanged -> {
                    transitionTo(Handshaking(event.channels, event.channelGroups, subscriptionCursor))
                }

                is SubscribeEvent.SubscriptionRestored -> {
                    transitionTo(Handshaking(event.channels, event.channelGroups, event.subscriptionCursor))
                }

                is SubscribeEvent.UnsubscribeAll -> {
                    transitionTo(Unsubscribed)
                }

                else -> {
                    noTransition()
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy