shared_uwsgi.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. import time
  3. from typing import Optional
  4. import uwsgi # pylint: disable=E0401
  5. from . import shared_abstract
  6. _last_signal = 10
  7. class UwsgiCacheSharedDict(shared_abstract.SharedDict):
  8. def get_int(self, key: str) -> Optional[int]:
  9. value = uwsgi.cache_get(key)
  10. if value is None:
  11. return value
  12. else:
  13. return int.from_bytes(value, 'big')
  14. def set_int(self, key: str, value: int):
  15. b = value.to_bytes(4, 'big')
  16. uwsgi.cache_update(key, b)
  17. def get_str(self, key: str) -> Optional[str]:
  18. value = uwsgi.cache_get(key)
  19. if value is None:
  20. return value
  21. else:
  22. return value.decode('utf-8')
  23. def set_str(self, key: str, value: str):
  24. b = value.encode('utf-8')
  25. uwsgi.cache_update(key, b)
  26. def schedule(delay, func, *args):
  27. """
  28. Can be implemented using a spooler.
  29. https://uwsgi-docs.readthedocs.io/en/latest/PythonDecorators.html
  30. To make the uwsgi configuration simple, use the alternative implementation.
  31. """
  32. global _last_signal
  33. def sighandler(signum):
  34. now = int(time.time())
  35. key = 'scheduler_call_time_signal_' + str(signum)
  36. uwsgi.lock()
  37. try:
  38. updating = uwsgi.cache_get(key)
  39. if updating is not None:
  40. updating = int.from_bytes(updating, 'big')
  41. if now - updating < delay:
  42. return
  43. uwsgi.cache_update(key, now.to_bytes(4, 'big'))
  44. finally:
  45. uwsgi.unlock()
  46. func(*args)
  47. signal_num = _last_signal
  48. _last_signal += 1
  49. uwsgi.register_signal(signal_num, 'worker', sighandler)
  50. uwsgi.add_timer(signal_num, delay)
  51. return True