Exemplo n.º 1
0
    def _completeLazySubscription(self, schema_name, typename,
                                  fieldname_and_value, typedef, identities,
                                  connectedChannel):
        index_vals = self._buildIndexValueMap(typedef, schema_name, typename,
                                              identities)

        connectedChannel.channel.write(
            ServerToClient.LazySubscriptionData(
                schema=schema_name,
                typename=typename,
                fieldname_and_value=fieldname_and_value,
                identities=identities,
                index_values=index_vals))

        # just send the identities
        self._markSubscriptionComplete(schema_name,
                                       typename,
                                       fieldname_and_value,
                                       identities,
                                       connectedChannel,
                                       isLazy=True)

        connectedChannel.channel.write(
            ServerToClient.SubscriptionComplete(
                schema=schema_name,
                typename=typename,
                fieldname_and_value=fieldname_and_value,
                tid=self._cur_transaction_num))
Exemplo n.º 2
0
    def _handleSubscriptionInForeground(self, channel, msg):
        #first see if this would be an easy subscription to handle
        with Timer("Handle subscription in foreground: %s/%s/%s/isLazy=%s over %s",
                    msg.schema, msg.typename, msg.fieldname_and_value, msg.isLazy, lambda: len(identities)):
            typedef, identities = self._parseSubscriptionMsg(channel, msg)

            if not (msg.isLazy and len(identities) < self.MAX_LAZY_TO_SEND_SYNCHRONOUSLY or len(identities) < self.MAX_NORMAL_TO_SEND_SYNCHRONOUSLY):
                self._subscriptionQueue.put((channel, msg))
                return

            #handle this directly
            if msg.isLazy:
                self._completeLazySubscription(
                    msg.schema, msg.typename, msg.fieldname_and_value,
                    typedef,
                    identities,
                    channel
                    )
                return

            self._sendPartialSubscription(
                channel,
                msg.schema,
                msg.typename,
                msg.fieldname_and_value,
                typedef,
                identities,
                set(identities),
                BATCH_SIZE=None,
                checkPending=False
                )

            self._markSubscriptionComplete(
                msg.schema,
                msg.typename,
                msg.fieldname_and_value,
                identities,
                channel,
                isLazy=False
                )

            channel.channel.write(
                ServerToClient.SubscriptionComplete(
                    schema=msg.schema,
                    typename=msg.typename,
                    fieldname_and_value=msg.fieldname_and_value,
                    tid=self._cur_transaction_num
                    )
                )
Exemplo n.º 3
0
    def handleSubscriptionOnBackgroundThread(self, connectedChannel, msg):
        with Timer(
                "Subscription requiring %s messages and produced %s objects for %s/%s/%s/isLazy=%s",
                lambda: messageCount, lambda: len(identities), msg.schema,
                msg.typename, msg.fieldname_and_value, msg.isLazy):
            try:
                with self._lock:
                    typedef, identities = self._parseSubscriptionMsg(
                        connectedChannel, msg)

                    if connectedChannel.channel not in self._clientChannels:
                        self._logger.warn(
                            "Ignoring subscription from dead channel.")
                        return

                    if msg.isLazy:
                        if (msg.fieldname_and_value is not None
                                and msg.fieldname_and_value[0] != '_identity'):
                            raise Exception(
                                "It makes no sense to lazily subscribe to specific values!"
                            )

                        messageCount = 1

                        self._completeLazySubscription(msg.schema,
                                                       msg.typename,
                                                       msg.fieldname_and_value,
                                                       typedef, identities,
                                                       connectedChannel)
                        return True

                    self._pendingSubscriptionRecheck = []

                # we need to send everything we know about 'identities', keeping in mind that we have to
                # check any new identities that get written to in the background to see if they belong
                # in the new set
                identities_left_to_send = set(identities)

                messageCount = 0
                while True:
                    locktime_start = time.time()

                    if self._subscriptionBackgroundThreadCallback:
                        self._subscriptionBackgroundThreadCallback(
                            messageCount)

                    with self._lock:
                        messageCount += 1
                        if messageCount == 2:
                            self._logger.info(
                                "Beginning large subscription for %s/%s/%s",
                                msg.schema, msg.typename,
                                msg.fieldname_and_value)

                        self._sendPartialSubscription(connectedChannel,
                                                      msg.schema, msg.typename,
                                                      msg.fieldname_and_value,
                                                      typedef, identities,
                                                      identities_left_to_send)

                        self._pendingSubscriptionRecheck = []

                        if not identities_left_to_send:
                            self._markSubscriptionComplete(
                                msg.schema,
                                msg.typename,
                                msg.fieldname_and_value,
                                identities,
                                connectedChannel,
                                isLazy=False)

                            connectedChannel.channel.write(
                                ServerToClient.SubscriptionComplete(
                                    schema=msg.schema,
                                    typename=msg.typename,
                                    fieldname_and_value=msg.
                                    fieldname_and_value,
                                    tid=self._cur_transaction_num))

                            break

                    # don't hold the lock more than 75% of the time.
                    time.sleep((time.time() - locktime_start) / 3)

                if self._subscriptionBackgroundThreadCallback:
                    self._subscriptionBackgroundThreadCallback("DONE")
            finally:
                with self._lock:
                    self._pendingSubscriptionRecheck = None