diff --git a/Dockerfile b/Dockerfile index 5baa41232b9be3d60e11d1e96ab7462ecb05adc6..83d57b4d2a7ca144a36bec48c8aecd7232986b13 100644 --- a/Dockerfile +++ b/Dockerfile @@ -171,6 +171,7 @@ COPY --chown=${USER} ssh ${HOME}/.ssh COPY --chown=${USER} mod_wsgi.conf wait-for-it.sh manage.py ${HOME}/ COPY --chown=${USER} utils/ ${HOME}/utils COPY --chown=${USER} cvat/ ${HOME}/cvat +COPY --chown=${USER} rqscheduler.py ${HOME} # RUN all commands below as 'django' user USER ${USER} diff --git a/docker-compose.yml b/docker-compose.yml index d84256cae2029f02aeb498b86418b8a6250229f2..412b12a7b06a3c58e653b665ec15bc90896ddbc4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -176,6 +176,28 @@ services: networks: - cvat + cvat_worker_quality_reports: + container_name: cvat_worker_quality_reports + image: cvat/server:${CVAT_VERSION:-dev} + restart: always + depends_on: + - cvat_redis + - cvat_db + environment: + CVAT_REDIS_HOST: 'cvat_redis' + CVAT_POSTGRES_HOST: 'cvat_db' + DJANGO_LOG_SERVER_HOST: vector + DJANGO_LOG_SERVER_PORT: 80 + no_proxy: clickhouse,grafana,vector,nuclio,opa,${no_proxy:-} + NUMPROCS: 1 + command: -c supervisord/worker.quality_reports.conf + volumes: + - cvat_data:/home/django/data + - cvat_keys:/home/django/keys + - cvat_logs:/home/django/logs + networks: + - cvat + cvat_ui: container_name: cvat_ui image: cvat/ui:${CVAT_VERSION:-dev} diff --git a/rqscheduler.py b/rqscheduler.py new file mode 100644 index 0000000000000000000000000000000000000000..ef0767b998c1f5b5915c173cac602e9a6ec7ffe5 --- /dev/null +++ b/rqscheduler.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +import argparse +import sys +import os + +from cvat.wsgi import application + +from redis import Redis +from rq_scheduler.scheduler import Scheduler + +from rq_scheduler.utils import setup_loghandlers + + +def main(): + parser = argparse.ArgumentParser(description='Runs RQ scheduler') + parser.add_argument('-b', '--burst', action='store_true', default=False, help='Run in burst mode (quit after all work is done)') + parser.add_argument('-H', '--host', default=os.environ.get('RQ_REDIS_HOST', 'localhost'), help="Redis host") + parser.add_argument('-p', '--port', default=int(os.environ.get('RQ_REDIS_PORT', 6379)), type=int, help="Redis port number") + parser.add_argument('-d', '--db', default=int(os.environ.get('RQ_REDIS_DB', 0)), type=int, help="Redis database") + parser.add_argument('-P', '--password', default=os.environ.get('RQ_REDIS_PASSWORD'), help="Redis password") + parser.add_argument('--verbose', '-v', action='store_true', default=False, help='Show more output') + parser.add_argument('--quiet', action='store_true', default=False, help='Show less output') + parser.add_argument('--url', '-u', default=os.environ.get('RQ_REDIS_URL') + , help='URL describing Redis connection details. \ + Overrides other connection arguments if supplied.') + parser.add_argument('-i', '--interval', default=60.0, type=float + , help="How often the scheduler checks for new jobs to add to the \ + queue (in seconds, can be floating-point for more precision).") + parser.add_argument('--path', default='.', help='Specify the import path.') + parser.add_argument('--pid', help='A filename to use for the PID file.', metavar='FILE') + parser.add_argument('-j', '--job-class', help='Custom RQ Job class') + parser.add_argument('-q', '--queue-class', help='Custom RQ Queue class') + + args = parser.parse_args() + + if args.path: + sys.path = args.path.split(':') + sys.path + + if args.pid: + pid = str(os.getpid()) + filename = args.pid + with open(filename, 'w') as f: + f.write(pid) + + if args.url is not None: + connection = Redis.from_url(args.url) + else: + connection = Redis(args.host, args.port, args.db, args.password) + + if args.verbose: + level = 'DEBUG' + elif args.quiet: + level = 'WARNING' + else: + level = 'INFO' + setup_loghandlers(level) + + scheduler = Scheduler(connection=connection, + interval=args.interval, + job_class=args.job_class, + queue_class=args.queue_class) + scheduler.run(burst=args.burst) + +if __name__ == '__main__': + main()