Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

zookeeper.py 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. """
  2. kombu.transport.zookeeper
  3. =========================
  4. Zookeeper transport.
  5. :copyright: (c) 2010 - 2013 by Mahendra M.
  6. :license: BSD, see LICENSE for more details.
  7. **Synopsis**
  8. Connects to a zookeeper node as <server>:<port>/<vhost>
  9. The <vhost> becomes the base for all the other znodes. So we can use
  10. it like a vhost.
  11. This uses the built-in kazoo recipe for queues
  12. **References**
  13. - https://zookeeper.apache.org/doc/trunk/recipes.html#sc_recipes_Queues
  14. - https://kazoo.readthedocs.io/en/latest/api/recipe/queue.html
  15. **Limitations**
  16. This queue does not offer reliable consumption. An entry is removed from
  17. the queue prior to being processed. So if an error occurs, the consumer
  18. has to re-queue the item or it will be lost.
  19. """
  20. from __future__ import absolute_import
  21. import os
  22. import socket
  23. from anyjson import loads, dumps
  24. from kombu.five import Empty
  25. from kombu.utils.encoding import bytes_to_str
  26. from . import virtual
  27. MAX_PRIORITY = 9
  28. try:
  29. import kazoo
  30. from kazoo.client import KazooClient
  31. from kazoo.recipe.queue import Queue
  32. KZ_CONNECTION_ERRORS = (
  33. kazoo.exceptions.SystemErrorException,
  34. kazoo.exceptions.ConnectionLossException,
  35. kazoo.exceptions.MarshallingErrorException,
  36. kazoo.exceptions.UnimplementedException,
  37. kazoo.exceptions.OperationTimeoutException,
  38. kazoo.exceptions.NoAuthException,
  39. kazoo.exceptions.InvalidACLException,
  40. kazoo.exceptions.AuthFailedException,
  41. kazoo.exceptions.SessionExpiredException,
  42. )
  43. KZ_CHANNEL_ERRORS = (
  44. kazoo.exceptions.RuntimeInconsistencyException,
  45. kazoo.exceptions.DataInconsistencyException,
  46. kazoo.exceptions.BadArgumentsException,
  47. kazoo.exceptions.MarshallingErrorException,
  48. kazoo.exceptions.UnimplementedException,
  49. kazoo.exceptions.OperationTimeoutException,
  50. kazoo.exceptions.ApiErrorException,
  51. kazoo.exceptions.NoNodeException,
  52. kazoo.exceptions.NoAuthException,
  53. kazoo.exceptions.NodeExistsException,
  54. kazoo.exceptions.NoChildrenForEphemeralsException,
  55. kazoo.exceptions.NotEmptyException,
  56. kazoo.exceptions.SessionExpiredException,
  57. kazoo.exceptions.InvalidCallbackException,
  58. socket.error,
  59. )
  60. except ImportError:
  61. kazoo = None # noqa
  62. KZ_CONNECTION_ERRORS = KZ_CHANNEL_ERRORS = () # noqa
  63. DEFAULT_PORT = 2181
  64. __author__ = 'Mahendra M <mahendra.m@gmail.com>'
  65. class Channel(virtual.Channel):
  66. _client = None
  67. _queues = {}
  68. def _get_path(self, queue_name):
  69. return os.path.join(self.vhost, queue_name)
  70. def _get_queue(self, queue_name):
  71. queue = self._queues.get(queue_name, None)
  72. if queue is None:
  73. queue = Queue(self.client, self._get_path(queue_name))
  74. self._queues[queue_name] = queue
  75. # Ensure that the queue is created
  76. len(queue)
  77. return queue
  78. def _put(self, queue, message, **kwargs):
  79. try:
  80. priority = message['properties']['delivery_info']['priority']
  81. except KeyError:
  82. priority = 0
  83. queue = self._get_queue(queue)
  84. queue.put(dumps(message), priority=(MAX_PRIORITY - priority))
  85. def _get(self, queue):
  86. queue = self._get_queue(queue)
  87. msg = queue.get()
  88. if msg is None:
  89. raise Empty()
  90. return loads(bytes_to_str(msg))
  91. def _purge(self, queue):
  92. count = 0
  93. queue = self._get_queue(queue)
  94. while True:
  95. msg = queue.get()
  96. if msg is None:
  97. break
  98. count += 1
  99. return count
  100. def _delete(self, queue, *args, **kwargs):
  101. if self._has_queue(queue):
  102. self._purge(queue)
  103. self.client.delete(self._get_path(queue))
  104. def _size(self, queue):
  105. queue = self._get_queue(queue)
  106. return len(queue)
  107. def _new_queue(self, queue, **kwargs):
  108. if not self._has_queue(queue):
  109. queue = self._get_queue(queue)
  110. def _has_queue(self, queue):
  111. return self.client.exists(self._get_path(queue)) is not None
  112. def _open(self):
  113. conninfo = self.connection.client
  114. port = conninfo.port or DEFAULT_PORT
  115. conn_str = '%s:%s' % (conninfo.hostname, port)
  116. self.vhost = os.path.join('/', conninfo.virtual_host[0:-1])
  117. conn = KazooClient(conn_str)
  118. conn.start()
  119. return conn
  120. @property
  121. def client(self):
  122. if self._client is None:
  123. self._client = self._open()
  124. return self._client
  125. class Transport(virtual.Transport):
  126. Channel = Channel
  127. polling_interval = 1
  128. default_port = DEFAULT_PORT
  129. connection_errors = (
  130. virtual.Transport.connection_errors + KZ_CONNECTION_ERRORS
  131. )
  132. channel_errors = (
  133. virtual.Transport.channel_errors + KZ_CHANNEL_ERRORS
  134. )
  135. driver_type = 'zookeeper'
  136. driver_name = 'kazoo'
  137. def __init__(self, *args, **kwargs):
  138. if kazoo is None:
  139. raise ImportError('The kazoo library is not installed')
  140. super(Transport, self).__init__(*args, **kwargs)
  141. def driver_version(self):
  142. return kazoo.__version__