# Path: deepstreampy/constants/actions.py
# PING = 'PI'
# PONG = 'PO'
# ACK = 'A'
# REDIRECT = 'RED'
# CHALLENGE = 'CH'
# CHALLENGE_RESPONSE = 'CHR'
# READ = 'R'
# CREATE = 'C'
# UPDATE = 'U'
# PATCH = 'P'
# DELETE = 'D'
# SUBSCRIBE = 'S'
# UNSUBSCRIBE = 'US'
# HAS = 'H'
# SNAPSHOT = 'SN'
# INVOKE = 'I'
# SUBSCRIPTION_FOR_PATTERN_FOUND = 'SP'
# SUBSCRIPTION_FOR_PATTERN_REMOVED = 'SR'
# SUBSCRIPTION_HAS_PROVIDER = 'SH'
# LISTEN = 'L'
# UNLISTEN = 'UL'
# LISTEN_ACCEPT = 'LA'
# LISTEN_REJECT = 'LR'
# PROVIDER_UPDATE = 'PU'
# QUERY = 'Q'
# CREATEORREAD = 'CR'
# EVENT = 'EVT'
# ERROR = 'E'
# REQUEST = 'REQ'
# RESPONSE = 'RES'
# REJECTION = 'REJ'
# PRESENCE_JOIN = 'PNJ'
# PRESENCE_LEAVE = 'PNL'
# QUERY = 'Q'
# WRITE_ACKNOWLEDGEMENT = 'WA'
# def reverse_lookup(action):
# 
# Path: deepstreampy/constants/event.py
# CONNECTION_ERROR = 'connectionError'
# CONNECTION_STATE_CHANGED = 'connectionStateChanged'
# MAX_RECONNECTION_ATTEMPTS_REACHED = 'MAX_RECONNECTION_ATTEMPTS_REACHED'
# CONNECTION_AUTHENTICATION_TIMEOUT = 'CONNECTION_AUTHENTICATION_TIMEOUT'
# ACK_TIMEOUT = 'ACK_TIMEOUT'
# NO_RPC_PROVIDER = 'NO_RPC_PROVIDER'
# RESPONSE_TIMEOUT = 'RESPONSE_TIMEOUT'
# DELETE_TIMEOUT = 'DELETE_TIMEOUT'
# UNSOLICITED_MESSAGE = 'UNSOLICITED_MESSAGE'
# MESSAGE_DENIED = 'MESSAGE_DENIED'
# MESSAGE_PARSE_ERROR = 'MESSAGE_PARSE_ERROR'
# VERSION_EXISTS = 'VERSION_EXISTS'
# NOT_AUTHENTICATED = 'NOT_AUTHENTICATED'
# MESSAGE_PERMISSION_ERROR = 'MESSAGE_PERMISSION_ERROR'
# LISTENER_EXISTS = 'LISTENER_EXISTS'
# NOT_LISTENING = 'NOT_LISTENING'
# TOO_MANY_AUTH_ATTEMPTS = 'TOO_MANY_AUTH_ATTEMPTS'
# IS_CLOSED = 'IS_CLOSED'
# RECORD_NOT_FOUND = 'RECORD_NOT_FOUND'
# NOT_SUBSCRIBED = 'NOT_SUBSCRIBED'
# INVALID_RPC_CORRELATION_ID = 'INVALID_RPC_CORRELATION_ID'
# 
# Path: deepstreampy/constants/connection_state.py
# CLOSED = 'CLOSED'
# AWAITING_AUTHENTICATION = 'AWAITING_AUTHENTICATION'
# AWAITING_CONNECTION = 'AWAITING_CONNECTION'
# AUTHENTICATING = 'AUTHENTICATING'
# OPEN = 'OPEN'
# ERROR = 'ERROR'
# RECONNECTING = 'RECONNECTING'
# CHALLENGING = 'CHALLENGING'


from deepstreampy.constants import actions as action_constants
from deepstreampy.constants import event as event_constants
from deepstreampy.constants import connection_state
from pyee import EventEmitter
from tornado import concurrent
from functools import partial
from collections import namedtuple
import sys
import time
import random
    Makes sure that all functionality is resubscribed on reconnect. Subscription
    is called when the connection drops - which seems counterintuitive, but in
    fact just means that the re-subscription message will be added to the queue
    of messages that need re-sending as soon as the connection is
    re-established.

    Resubscribe logic should only occur once per connection loss.
    """

    def __init__(self, client, resubscribe):
        """
        Args:
            client: The deepstream client
            resubscribe: callable to call to allow resubscribing
        """
        self._client = client
        self._resubscribe = resubscribe

        self._is_reconnecting = False
        self._client.on(event_constants.CONNECTION_STATE_CHANGED,
                        self._handle_connection_state_changes)

    def destroy(self):
        self._client.remove_listener(event_constants.CONNECTION_STATE_CHANGED,
                                     self._handle_connection_state_changes)
        self._client = None

    def _handle_connection_state_changes(self, state):
        if state == connection_state.RECONNECTING and not self._is_reconnecting:
            self._is_reconnecting = True

# Path: deepstreampy/constants/actions.py
# PING = 'PI'
# PONG = 'PO'
# ACK = 'A'
# REDIRECT = 'RED'
# CHALLENGE = 'CH'
# CHALLENGE_RESPONSE = 'CHR'
# READ = 'R'
# CREATE = 'C'
# UPDATE = 'U'
# PATCH = 'P'
# DELETE = 'D'
# SUBSCRIBE = 'S'
# UNSUBSCRIBE = 'US'
# HAS = 'H'
# SNAPSHOT = 'SN'
# INVOKE = 'I'
# SUBSCRIPTION_FOR_PATTERN_FOUND = 'SP'
# SUBSCRIPTION_FOR_PATTERN_REMOVED = 'SR'
# SUBSCRIPTION_HAS_PROVIDER = 'SH'
# LISTEN = 'L'
# UNLISTEN = 'UL'
# LISTEN_ACCEPT = 'LA'
# LISTEN_REJECT = 'LR'
# PROVIDER_UPDATE = 'PU'
# QUERY = 'Q'
# CREATEORREAD = 'CR'
# EVENT = 'EVT'
# ERROR = 'E'
# REQUEST = 'REQ'
# RESPONSE = 'RES'
# REJECTION = 'REJ'
# PRESENCE_JOIN = 'PNJ'
# PRESENCE_LEAVE = 'PNL'
# QUERY = 'Q'
# WRITE_ACKNOWLEDGEMENT = 'WA'
# def reverse_lookup(action):
# 
# Path: deepstreampy/constants/event.py
# CONNECTION_ERROR = 'connectionError'
# CONNECTION_STATE_CHANGED = 'connectionStateChanged'
# MAX_RECONNECTION_ATTEMPTS_REACHED = 'MAX_RECONNECTION_ATTEMPTS_REACHED'
# CONNECTION_AUTHENTICATION_TIMEOUT = 'CONNECTION_AUTHENTICATION_TIMEOUT'
# ACK_TIMEOUT = 'ACK_TIMEOUT'
# NO_RPC_PROVIDER = 'NO_RPC_PROVIDER'
# RESPONSE_TIMEOUT = 'RESPONSE_TIMEOUT'
# DELETE_TIMEOUT = 'DELETE_TIMEOUT'
# UNSOLICITED_MESSAGE = 'UNSOLICITED_MESSAGE'
# MESSAGE_DENIED = 'MESSAGE_DENIED'
# MESSAGE_PARSE_ERROR = 'MESSAGE_PARSE_ERROR'
# VERSION_EXISTS = 'VERSION_EXISTS'
# NOT_AUTHENTICATED = 'NOT_AUTHENTICATED'
# MESSAGE_PERMISSION_ERROR = 'MESSAGE_PERMISSION_ERROR'
# LISTENER_EXISTS = 'LISTENER_EXISTS'
# NOT_LISTENING = 'NOT_LISTENING'
# TOO_MANY_AUTH_ATTEMPTS = 'TOO_MANY_AUTH_ATTEMPTS'
# IS_CLOSED = 'IS_CLOSED'
# RECORD_NOT_FOUND = 'RECORD_NOT_FOUND'
# NOT_SUBSCRIBED = 'NOT_SUBSCRIBED'
# INVALID_RPC_CORRELATION_ID = 'INVALID_RPC_CORRELATION_ID'
# 
# Path: deepstreampy/constants/connection_state.py
# CLOSED = 'CLOSED'
# AWAITING_AUTHENTICATION = 'AWAITING_AUTHENTICATION'
# AWAITING_CONNECTION = 'AWAITING_CONNECTION'
# AUTHENTICATING = 'AUTHENTICATING'
# OPEN = 'OPEN'
# ERROR = 'ERROR'
# RECONNECTING = 'RECONNECTING'
# CHALLENGING = 'CHALLENGING'


# Path: deepstreampy/utils.py
from deepstreampy.constants import actions as action_constants
from deepstreampy.constants import event as event_constants
from deepstreampy.constants import connection_state
from pyee import EventEmitter
from tornado import concurrent
from functools import partial
from collections import namedtuple
import sys
import time
import random

    Makes sure that all functionality is resubscribed on reconnect. Subscription
    is called when the connection drops - which seems counterintuitive, but in
    fact just means that the re-subscription message will be added to the queue
    of messages that need re-sending as soon as the connection is
    re-established.

    Resubscribe logic should only occur once per connection loss.
    """

    def __init__(self, client, resubscribe):
        """
        Args:
            client: The deepstream client
            resubscribe: callable to call to allow resubscribing
        """
        self._client = client
        self._resubscribe = resubscribe

        self._is_reconnecting = False
        self._client.on(event_constants.CONNECTION_STATE_CHANGED,
                        self._handle_connection_state_changes)

    def destroy(self):
        self._client.remove_listener(event_constants.CONNECTION_STATE_CHANGED,
                                     self._handle_connection_state_changes)
        self._client = None

    def _handle_connection_state_changes(self, state):
        if state == connection_state.RECONNECTING and not self._is_reconnecting:
            self._is_reconnecting = True

        elif state == connection_state.OPEN and self._is_reconnecting: