import logging import pickle try: import kafka except ImportError: kafka = None from .pubsub_manager import PubSubManager logger = logging.getLogger('socketio') class KafkaManager(PubSubManager): # pragma: no cover """Kafka based client manager. This class implements a Kafka backend for event sharing across multiple processes. To use a Kafka backend, initialize the :class:`Server` instance as follows:: url = 'kafka://hostname:port' server = socketio.Server(client_manager=socketio.KafkaManager(url)) :param url: The connection URL for the Kafka server. For a default Kafka store running on the same host, use ``kafka://``. For a highly available deployment of Kafka, pass a list with all the connection URLs available in your cluster. :param channel: The channel name (topic) on which the server sends and receives notifications. Must be the same in all the servers. :param write_only: If set to ``True``, only initialize to emit events. The default of ``False`` initializes the class for emitting and receiving. """ name = 'kafka' def __init__(self, url='kafka://localhost:9092', channel='socketio', write_only=False): if kafka is None: raise RuntimeError('kafka-python package is not installed ' '(Run "pip install kafka-python" in your ' 'virtualenv).') super().__init__(channel=channel, write_only=write_only) urls = [url] if isinstance(url, str) else url self.kafka_urls = [url[8:] if url != 'kafka://' else 'localhost:9092' for url in urls] self.producer = kafka.KafkaProducer(bootstrap_servers=self.kafka_urls) self.consumer = kafka.KafkaConsumer(self.channel, bootstrap_servers=self.kafka_urls) def _publish(self, data): self.producer.send(self.channel, value=pickle.dumps(data)) self.producer.flush() def _kafka_listen(self): for message in self.consumer: yield message def _listen(self): for message in self._kafka_listen(): if message.topic == self.channel: yield pickle.loads(message.value)