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.

couchdb.py 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. """
  2. kombu.transport.couchdb
  3. =======================
  4. CouchDB transport.
  5. :copyright: (c) 2010 - 2013 by David Clymer.
  6. :license: BSD, see LICENSE for more details.
  7. """
  8. from __future__ import absolute_import
  9. import socket
  10. from anyjson import loads, dumps
  11. from kombu.five import Empty
  12. from kombu.utils import uuid4
  13. from kombu.utils.encoding import bytes_to_str
  14. from . import virtual
  15. try:
  16. import couchdb
  17. except ImportError: # pragma: no cover
  18. couchdb = None # noqa
  19. DEFAULT_PORT = 5984
  20. DEFAULT_DATABASE = 'kombu_default'
  21. __author__ = 'David Clymer <david@zettazebra.com>'
  22. def create_message_view(db):
  23. from couchdb import design
  24. view = design.ViewDefinition('kombu', 'messages', """
  25. function (doc) {
  26. if (doc.queue && doc.payload)
  27. emit(doc.queue, doc);
  28. }
  29. """)
  30. if not view.get_doc(db):
  31. view.sync(db)
  32. class Channel(virtual.Channel):
  33. _client = None
  34. view_created = False
  35. def _put(self, queue, message, **kwargs):
  36. self.client.save({'_id': uuid4().hex,
  37. 'queue': queue,
  38. 'payload': dumps(message)})
  39. def _get(self, queue):
  40. result = self._query(queue, limit=1)
  41. if not result:
  42. raise Empty()
  43. item = result.rows[0].value
  44. self.client.delete(item)
  45. return loads(bytes_to_str(item['payload']))
  46. def _purge(self, queue):
  47. result = self._query(queue)
  48. for item in result:
  49. self.client.delete(item.value)
  50. return len(result)
  51. def _size(self, queue):
  52. return len(self._query(queue))
  53. def _open(self):
  54. conninfo = self.connection.client
  55. dbname = conninfo.virtual_host
  56. proto = conninfo.ssl and 'https' or 'http'
  57. if not dbname or dbname == '/':
  58. dbname = DEFAULT_DATABASE
  59. port = conninfo.port or DEFAULT_PORT
  60. server = couchdb.Server('%s://%s:%s/' % (proto,
  61. conninfo.hostname,
  62. port))
  63. # Use username and password if avaliable
  64. try:
  65. if conninfo.userid:
  66. server.resource.credentials = (conninfo.userid,
  67. conninfo.password)
  68. except AttributeError:
  69. pass
  70. try:
  71. return server[dbname]
  72. except couchdb.http.ResourceNotFound:
  73. return server.create(dbname)
  74. def _query(self, queue, **kwargs):
  75. if not self.view_created:
  76. # if the message view is not yet set up, we'll need it now.
  77. create_message_view(self.client)
  78. self.view_created = True
  79. return self.client.view('kombu/messages', key=queue, **kwargs)
  80. @property
  81. def client(self):
  82. if self._client is None:
  83. self._client = self._open()
  84. return self._client
  85. class Transport(virtual.Transport):
  86. Channel = Channel
  87. polling_interval = 1
  88. default_port = DEFAULT_PORT
  89. connection_errors = (
  90. virtual.Transport.connection_errors + (
  91. socket.error,
  92. getattr(couchdb, 'HTTPError', None),
  93. getattr(couchdb, 'ServerError', None),
  94. getattr(couchdb, 'Unauthorized', None),
  95. )
  96. )
  97. channel_errors = (
  98. virtual.Transport.channel_errors + (
  99. getattr(couchdb, 'HTTPError', None),
  100. getattr(couchdb, 'ServerError', None),
  101. getattr(couchdb, 'PreconditionFailed', None),
  102. getattr(couchdb, 'ResourceConflict', None),
  103. getattr(couchdb, 'ResourceNotFound', None),
  104. )
  105. )
  106. driver_type = 'couchdb'
  107. driver_name = 'couchdb'
  108. def __init__(self, *args, **kwargs):
  109. if couchdb is None:
  110. raise ImportError('Missing couchdb library (pip install couchdb)')
  111. super(Transport, self).__init__(*args, **kwargs)
  112. def driver_version(self):
  113. return couchdb.__version__