command.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import math
  2. import os
  3. from django.core.management.base import BaseCommand
  4. from django.db.models import TextChoices
  5. from .utils import ServicesUtil
  6. class Services(TextChoices):
  7. gunicorn = 'gunicorn', 'gunicorn'
  8. celery_default = 'celery_default', 'celery_default'
  9. local_model = 'local_model', 'local_model'
  10. web = 'web', 'web'
  11. celery = 'celery', 'celery'
  12. celery_model = 'celery_model', 'celery_model'
  13. task = 'task', 'task'
  14. all = 'all', 'all'
  15. @classmethod
  16. def get_service_object_class(cls, name):
  17. from . import services
  18. services_map = {
  19. cls.gunicorn.value: services.GunicornService,
  20. cls.celery_default: services.CeleryDefaultService,
  21. cls.local_model: services.GunicornLocalModelService,
  22. }
  23. return services_map.get(name)
  24. @classmethod
  25. def web_services(cls):
  26. return [cls.gunicorn, cls.local_model]
  27. @classmethod
  28. def celery_services(cls):
  29. return [cls.celery_default, cls.celery_model]
  30. @classmethod
  31. def task_services(cls):
  32. return cls.celery_services()
  33. @classmethod
  34. def all_services(cls):
  35. return cls.web_services() + cls.task_services()
  36. @classmethod
  37. def export_services_values(cls):
  38. return [cls.all.value, cls.web.value, cls.task.value] + [s.value for s in cls.all_services()]
  39. @classmethod
  40. def get_service_objects(cls, service_names, **kwargs):
  41. services = set()
  42. for name in service_names:
  43. method_name = f'{name}_services'
  44. if hasattr(cls, method_name):
  45. _services = getattr(cls, method_name)()
  46. elif hasattr(cls, name):
  47. _services = [getattr(cls, name)]
  48. else:
  49. continue
  50. services.update(set(_services))
  51. service_objects = []
  52. for s in services:
  53. service_class = cls.get_service_object_class(s.value)
  54. if not service_class:
  55. continue
  56. kwargs.update({
  57. 'name': s.value
  58. })
  59. service_object = service_class(**kwargs)
  60. service_objects.append(service_object)
  61. return service_objects
  62. class Action(TextChoices):
  63. start = 'start', 'start'
  64. status = 'status', 'status'
  65. stop = 'stop', 'stop'
  66. restart = 'restart', 'restart'
  67. class BaseActionCommand(BaseCommand):
  68. help = 'Service Base Command'
  69. action = None
  70. util = None
  71. def __init__(self, *args, **kwargs):
  72. super().__init__(*args, **kwargs)
  73. def add_arguments(self, parser):
  74. parser.add_argument(
  75. 'services', nargs='+', choices=Services.export_services_values(), help='Service',
  76. )
  77. parser.add_argument('-d', '--daemon', nargs="?", const=True)
  78. parser.add_argument('-w', '--worker', type=int, nargs="?",
  79. default=3 if os.cpu_count() > 6 else max(1, math.floor(os.cpu_count() / 2)))
  80. parser.add_argument('-f', '--force', nargs="?", const=True)
  81. def initial_util(self, *args, **options):
  82. service_names = options.get('services')
  83. service_kwargs = {
  84. 'worker_gunicorn': options.get('worker')
  85. }
  86. services = Services.get_service_objects(service_names=service_names, **service_kwargs)
  87. kwargs = {
  88. 'services': services,
  89. 'run_daemon': options.get('daemon', False),
  90. 'stop_daemon': self.action == Action.stop.value and Services.all.value in service_names,
  91. 'force_stop': options.get('force') or False,
  92. }
  93. self.util = ServicesUtil(**kwargs)
  94. def handle(self, *args, **options):
  95. self.initial_util(*args, **options)
  96. assert self.action in Action.values, f'The action {self.action} is not in the optional list'
  97. _handle = getattr(self, f'_handle_{self.action}', lambda: None)
  98. _handle()
  99. def _handle_start(self):
  100. self.util.start_and_watch()
  101. os._exit(0)
  102. def _handle_stop(self):
  103. self.util.stop()
  104. def _handle_restart(self):
  105. self.util.restart()
  106. def _handle_status(self):
  107. self.util.show_status()