Skip to content

Commit 2699606

Browse files
committed
feat: add gunicorn and python-daemon dependencies to pyproject.toml
1 parent 2fe1803 commit 2699606

File tree

18 files changed

+720
-0
lines changed

18 files changed

+720
-0
lines changed

apps/common/management/__init__.py

Whitespace-only changes.

apps/common/management/commands/__init__.py

Whitespace-only changes.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# coding=utf-8
2+
"""
3+
@project: MaxKB
4+
@Author:虎
5+
@file: celery.py
6+
@date:2024/8/19 11:57
7+
@desc:
8+
"""
9+
import os
10+
import subprocess
11+
12+
from django.core.management.base import BaseCommand
13+
14+
from maxkb.const import BASE_DIR
15+
16+
17+
class Command(BaseCommand):
18+
help = 'celery'
19+
20+
def add_arguments(self, parser):
21+
parser.add_argument(
22+
'service', nargs='+', type=str, choices=("celery", "model"), help='Service',
23+
)
24+
25+
def handle(self, *args, **options):
26+
service = options.get('service')
27+
os.environ.setdefault('CELERY_NAME', ','.join(service))
28+
server_hostname = os.environ.get("SERVER_HOSTNAME")
29+
if hasattr(os, 'getuid') and os.getuid() == 0:
30+
os.environ.setdefault('C_FORCE_ROOT', '1')
31+
if not server_hostname:
32+
server_hostname = '%h'
33+
cmd = [
34+
'celery',
35+
'-A', 'ops',
36+
'worker',
37+
'-P', 'threads',
38+
'-l', 'info',
39+
'-c', '10',
40+
'-Q', ','.join(service),
41+
'--heartbeat-interval', '10',
42+
'-n', f'{",".join(service)}@{server_hostname}',
43+
'--without-mingle',
44+
]
45+
kwargs = {'cwd': BASE_DIR}
46+
subprocess.run(cmd, **kwargs)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from .services.command import BaseActionCommand, Action
2+
3+
4+
class Command(BaseActionCommand):
5+
help = 'Restart services'
6+
action = Action.restart.value

apps/common/management/commands/services/__init__.py

Whitespace-only changes.
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import math
2+
3+
from django.core.management.base import BaseCommand
4+
from django.db.models import TextChoices
5+
6+
from .hands import *
7+
from .utils import ServicesUtil
8+
import os
9+
10+
11+
class Services(TextChoices):
12+
gunicorn = 'gunicorn', 'gunicorn'
13+
celery_default = 'celery_default', 'celery_default'
14+
local_model = 'local_model', 'local_model'
15+
web = 'web', 'web'
16+
celery = 'celery', 'celery'
17+
celery_model = 'celery_model', 'celery_model'
18+
task = 'task', 'task'
19+
all = 'all', 'all'
20+
21+
@classmethod
22+
def get_service_object_class(cls, name):
23+
from . import services
24+
services_map = {
25+
cls.gunicorn.value: services.GunicornService,
26+
cls.celery_default: services.CeleryDefaultService,
27+
cls.local_model: services.GunicornLocalModelService
28+
}
29+
return services_map.get(name)
30+
31+
@classmethod
32+
def web_services(cls):
33+
return [cls.gunicorn, cls.local_model]
34+
35+
@classmethod
36+
def celery_services(cls):
37+
return [cls.celery_default, cls.celery_model]
38+
39+
@classmethod
40+
def task_services(cls):
41+
return cls.celery_services()
42+
43+
@classmethod
44+
def all_services(cls):
45+
return cls.web_services() + cls.task_services()
46+
47+
@classmethod
48+
def export_services_values(cls):
49+
return [cls.all.value, cls.web.value, cls.task.value] + [s.value for s in cls.all_services()]
50+
51+
@classmethod
52+
def get_service_objects(cls, service_names, **kwargs):
53+
services = set()
54+
for name in service_names:
55+
method_name = f'{name}_services'
56+
if hasattr(cls, method_name):
57+
_services = getattr(cls, method_name)()
58+
elif hasattr(cls, name):
59+
_services = [getattr(cls, name)]
60+
else:
61+
continue
62+
services.update(set(_services))
63+
64+
service_objects = []
65+
for s in services:
66+
service_class = cls.get_service_object_class(s.value)
67+
if not service_class:
68+
continue
69+
kwargs.update({
70+
'name': s.value
71+
})
72+
service_object = service_class(**kwargs)
73+
service_objects.append(service_object)
74+
return service_objects
75+
76+
77+
class Action(TextChoices):
78+
start = 'start', 'start'
79+
status = 'status', 'status'
80+
stop = 'stop', 'stop'
81+
restart = 'restart', 'restart'
82+
83+
84+
class BaseActionCommand(BaseCommand):
85+
help = 'Service Base Command'
86+
87+
action = None
88+
util = None
89+
90+
def __init__(self, *args, **kwargs):
91+
super().__init__(*args, **kwargs)
92+
93+
def add_arguments(self, parser):
94+
parser.add_argument(
95+
'services', nargs='+', choices=Services.export_services_values(), help='Service',
96+
)
97+
parser.add_argument('-d', '--daemon', nargs="?", const=True)
98+
parser.add_argument('-w', '--worker', type=int, nargs="?",
99+
default=3 if os.cpu_count() > 6 else math.floor(os.cpu_count() / 2))
100+
parser.add_argument('-f', '--force', nargs="?", const=True)
101+
102+
def initial_util(self, *args, **options):
103+
service_names = options.get('services')
104+
service_kwargs = {
105+
'worker_gunicorn': options.get('worker')
106+
}
107+
services = Services.get_service_objects(service_names=service_names, **service_kwargs)
108+
109+
kwargs = {
110+
'services': services,
111+
'run_daemon': options.get('daemon', False),
112+
'stop_daemon': self.action == Action.stop.value and Services.all.value in service_names,
113+
'force_stop': options.get('force') or False,
114+
}
115+
self.util = ServicesUtil(**kwargs)
116+
117+
def handle(self, *args, **options):
118+
self.initial_util(*args, **options)
119+
assert self.action in Action.values, f'The action {self.action} is not in the optional list'
120+
_handle = getattr(self, f'_handle_{self.action}', lambda: None)
121+
_handle()
122+
123+
def _handle_start(self):
124+
self.util.start_and_watch()
125+
os._exit(0)
126+
127+
def _handle_stop(self):
128+
self.util.stop()
129+
130+
def _handle_restart(self):
131+
self.util.restart()
132+
133+
def _handle_status(self):
134+
self.util.show_status()
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import logging
2+
import os
3+
import sys
4+
5+
from maxkb.const import CONFIG, PROJECT_DIR
6+
7+
try:
8+
from apps.smartdoc import const
9+
10+
__version__ = const.VERSION
11+
except ImportError as e:
12+
print("Not found __version__: {}".format(e))
13+
print("Python is: ")
14+
logging.info(sys.executable)
15+
__version__ = 'Unknown'
16+
sys.exit(1)
17+
18+
HTTP_HOST = '0.0.0.0'
19+
HTTP_PORT = CONFIG.HTTP_LISTEN_PORT or 8080
20+
DEBUG = CONFIG.DEBUG or False
21+
22+
LOG_DIR = os.path.join(PROJECT_DIR, 'data', 'logs')
23+
APPS_DIR = os.path.join(PROJECT_DIR, 'apps')
24+
TMP_DIR = os.path.join(PROJECT_DIR, 'tmp')
25+
if not os.path.exists(TMP_DIR):
26+
os.makedirs(TMP_DIR)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .celery_default import *
2+
from .gunicorn import *
3+
from .local_model import *

0 commit comments

Comments
 (0)