| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- import argparse
- import logging
- import os
- import sys
- import time
- import django
- from django.core import management
- BASE_DIR = os.path.dirname(os.path.abspath(__file__))
- APP_DIR = os.path.join(BASE_DIR, 'apps')
- os.chdir(BASE_DIR)
- sys.path.insert(0, APP_DIR)
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "maxkb.settings")
- def collect_static():
- """
- 收集静态文件到指定目录
- 本项目主要是将前端vue/dist的前端项目放到静态目录下面
- :return:
- """
- logging.info("Collect static files")
- try:
- management.call_command('collectstatic', '--no-input', '-c', verbosity=0, interactive=False)
- logging.info("Collect static files done")
- except:
- pass
- def perform_db_migrate():
- """
- 初始化数据库表
- wait-for-it 仅检测 TCP 端口,PostgreSQL 崩溃恢复期间端口已开放但拒绝查询,
- 因此在此处增加重试逻辑,等待数据库真正就绪后再执行 migrate。
- """
- logging.info("Check database structure change ...")
- logging.info("Migrate model change to database ...")
- max_retries = 10
- retry_interval = 5 # seconds
- for attempt in range(1, max_retries + 1):
- try:
- management.call_command('migrate')
- return
- except Exception as e:
- err_msg = str(e)
- # 判断是否为数据库仍在启动中(崩溃恢复场景)
- is_db_starting = (
- 'the database system is starting up' in err_msg
- or 'starting up' in err_msg
- or 'Connection refused' in err_msg
- )
- if is_db_starting and attempt < max_retries:
- logging.warning(
- f'Database is not ready yet (attempt {attempt}/{max_retries}), '
- f'retrying in {retry_interval}s... Error: {err_msg}'
- )
- time.sleep(retry_interval)
- else:
- logging.error('Perform migrate failed, exit', exc_info=True)
- sys.exit(11)
- def start_services():
- services = args.services if isinstance(args.services, list) else [args.services]
- start_args = []
- if args.daemon:
- start_args.append('--daemon')
- if args.force:
- start_args.append('--force')
- if args.worker:
- start_args.extend(['--worker', str(args.worker)])
- else:
- worker = os.environ.get('MAXKB_CORE_WORKER')
- if isinstance(worker, str) and worker.isdigit():
- start_args.extend(['--worker', worker])
- try:
- management.call_command(action, *services, *start_args)
- except KeyboardInterrupt:
- logging.info('Cancel ...')
- time.sleep(2)
- except Exception as exc:
- logging.error("Start service error {}: {}".format(services, exc))
- time.sleep(2)
- def dev():
- services = args.services if isinstance(args.services, list) else args.services
- if services.__contains__('web'):
- management.call_command('runserver', "0.0.0.0:8080")
- elif services.__contains__('celery'):
- management.call_command('celery', 'celery')
- elif services.__contains__('local_model'):
- from maxkb.const import CONFIG
- bind = f'{CONFIG.get("LOCAL_MODEL_HOST")}:{CONFIG.get("LOCAL_MODEL_PORT")}'
- management.call_command('runserver', bind)
- if __name__ == '__main__':
- os.environ['HF_HOME'] = '/opt/maxkb-app/model/base'
- os.environ['TMPDIR'] = '/opt/maxkb-app/tmp'
- parser = argparse.ArgumentParser(
- description="""
- qabot service control tools;
- Example: \r\n
- %(prog)s start all -d;
- """
- )
- parser.add_argument(
- 'action', type=str,
- choices=("start", "dev", "upgrade_db", "collect_static"),
- help="Action to run"
- )
- args, e = parser.parse_known_args()
- parser.add_argument(
- "services", type=str, default='all' if args.action == 'start' else 'web', nargs="*",
- choices=("all", "web", "task") if args.action == 'start' else ("web", "celery", 'local_model'),
- help="The service to start",
- )
- parser.add_argument('-d', '--daemon', nargs="?", const=True)
- parser.add_argument('-w', '--worker', type=int, nargs="?")
- parser.add_argument('-f', '--force', nargs="?", const=True)
- args = parser.parse_args()
- action = args.action
- services = args.services if isinstance(args.services, list) else args.services
- if services.__contains__('web'):
- os.environ.setdefault('SERVER_NAME', 'web')
- elif services.__contains__('local_model'):
- os.environ.setdefault('SERVER_NAME', 'local_model')
- django.setup()
- if action == "upgrade_db":
- perform_db_migrate()
- elif action == "collect_static":
- collect_static()
- elif action == 'dev':
- collect_static()
- perform_db_migrate()
- dev()
- else:
- collect_static()
- perform_db_migrate()
- start_services()
|