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.

pools.py 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. """
  2. kombu.pools
  3. ===========
  4. Public resource pools.
  5. """
  6. from __future__ import absolute_import
  7. import os
  8. from itertools import chain
  9. from .connection import Resource
  10. from .five import range, values
  11. from .messaging import Producer
  12. from .utils import EqualityDict
  13. from .utils.functional import lazy
  14. __all__ = ['ProducerPool', 'PoolGroup', 'register_group',
  15. 'connections', 'producers', 'get_limit', 'set_limit', 'reset']
  16. _limit = [200]
  17. _used = [False]
  18. _groups = []
  19. use_global_limit = object()
  20. disable_limit_protection = os.environ.get('KOMBU_DISABLE_LIMIT_PROTECTION')
  21. class ProducerPool(Resource):
  22. Producer = Producer
  23. def __init__(self, connections, *args, **kwargs):
  24. self.connections = connections
  25. self.Producer = kwargs.pop('Producer', None) or self.Producer
  26. super(ProducerPool, self).__init__(*args, **kwargs)
  27. def _acquire_connection(self):
  28. return self.connections.acquire(block=True)
  29. def create_producer(self):
  30. conn = self._acquire_connection()
  31. try:
  32. return self.Producer(conn)
  33. except BaseException:
  34. conn.release()
  35. raise
  36. def new(self):
  37. return lazy(self.create_producer)
  38. def setup(self):
  39. if self.limit:
  40. for _ in range(self.limit):
  41. self._resource.put_nowait(self.new())
  42. def close_resource(self, resource):
  43. pass
  44. def prepare(self, p):
  45. if callable(p):
  46. p = p()
  47. if p._channel is None:
  48. conn = self._acquire_connection()
  49. try:
  50. p.revive(conn)
  51. except BaseException:
  52. conn.release()
  53. raise
  54. return p
  55. def release(self, resource):
  56. if resource.__connection__:
  57. resource.__connection__.release()
  58. resource.channel = None
  59. super(ProducerPool, self).release(resource)
  60. class PoolGroup(EqualityDict):
  61. def __init__(self, limit=None):
  62. self.limit = limit
  63. def create(self, resource, limit):
  64. raise NotImplementedError('PoolGroups must define ``create``')
  65. def __missing__(self, resource):
  66. limit = self.limit
  67. if limit is use_global_limit:
  68. limit = get_limit()
  69. if not _used[0]:
  70. _used[0] = True
  71. k = self[resource] = self.create(resource, limit)
  72. return k
  73. def register_group(group):
  74. _groups.append(group)
  75. return group
  76. class Connections(PoolGroup):
  77. def create(self, connection, limit):
  78. return connection.Pool(limit=limit)
  79. connections = register_group(Connections(limit=use_global_limit))
  80. class Producers(PoolGroup):
  81. def create(self, connection, limit):
  82. return ProducerPool(connections[connection], limit=limit)
  83. producers = register_group(Producers(limit=use_global_limit))
  84. def _all_pools():
  85. return chain(*[(values(g) if g else iter([])) for g in _groups])
  86. def get_limit():
  87. return _limit[0]
  88. def set_limit(limit, force=False, reset_after=False):
  89. limit = limit or 0
  90. glimit = _limit[0] or 0
  91. if limit < glimit:
  92. if not disable_limit_protection and (_used[0] and not force):
  93. raise RuntimeError("Can't lower limit after pool in use.")
  94. reset_after = True
  95. if limit != glimit:
  96. _limit[0] = limit
  97. for pool in _all_pools():
  98. pool.limit = limit
  99. if reset_after:
  100. reset()
  101. return limit
  102. def reset(*args, **kwargs):
  103. for pool in _all_pools():
  104. try:
  105. pool.force_close_all()
  106. except Exception:
  107. pass
  108. for group in _groups:
  109. group.clear()
  110. _used[0] = False
  111. try:
  112. from multiprocessing.util import register_after_fork
  113. register_after_fork(connections, reset)
  114. except ImportError: # pragma: no cover
  115. pass