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))
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 ) )
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