Scheduler

mlumina.scheduler

Отдельный FastAPI-сервис — приоритетная очередь задач поверх Ray Jobs API. Не заменяет ray.tune/ray.train — решает, когда и в каком порядке отправлять уже готовые job-скрипты в Ray-кластер, с учётом заявленных ресурсов и приоритета.

В Docker-стеке (docker-compose.yml) это сервис scheduler: собирается из корневого Dockerfile, зависит от head, слушает порт 8264, точка входа — python /home/ray/src/mlumina/scheduler/main.py.

import mlumina.scheduler.main имеет побочные эффекты: на уровне модуля создаётся Scheduler() (что сразу пытается подключиться к Ray-кластеру через JobSubmissionClient и ray.init()) и вызывается scheduler.start() (блокирующий запуск uvicorn на 0.0.0.0:8264). Импортировать этот модуль просто "для класса" нельзя — он запустит сервер.

Как это работает

HTTP API (порт 8264)

Метод Путь Описание
GET / HTML-дашборд (utils/index.html)
POST /add_task Поставить задачу в очередь (тело — TaskData, см. ниже)
POST /change_task_priority?task_id=...&set_priority=... Изменить приоритет задачи в очереди (0–9)
POST /cancel_task?task_id=... Отменить задачу (в очереди или уже запущенную — для запущенной вызывает ray_client.stop_job)
GET /get_task_queue Текущая очередь по приоритетам
GET /get_running_tasks_list Список запущенных задач
GET /get_resources_status Текущее использование/выделение ресурсов кластера
GET /get_resource_history История снепшотов ресурсов (накопленная с момента старта сервиса)

TaskData (тело POST /add_task)

class TaskData(BaseModel):
    name: str
    entrypoint: str        # команда запуска, например "python ray_wrapper/examples/fcnn/tune.py"
    runtime_env: dict       # ray runtime_env: working_dir, pip, env_vars и т.д.
    priority: int            # 0..9, больше — выше приоритет
    cpu: int                 # >= 0
    gpu: int                 # >= 0
    memory: int               # >= 0, в ГБ
    timeout: int              # >= 0, секунды; 0 = без таймаута

Пример вызова:

import requests

response = requests.post(
    "http://127.0.0.1:8264/add_task",
    json={
        "name": "my_job",
        "entrypoint": "python examples/scheduler/test.py",
        "runtime_env": {"working_dir": "/home/ray/src/mlumina"},
        "priority": 1,
        "cpu": 2,
        "gpu": 0,
        "memory": 4,
        "timeout": 300,
    },
    timeout=60,
)
print(response.status_code, response.json())

entrypoint выполняется в рабочей директории runtime_env["working_dir"] — это путь внутри контейнера, где запущен scheduler (в docker-compose это /home/ray/src, с примонтированным ./src), а не на машине, откуда отправляется HTTP-запрос. Больше примеров вызова — src/mlumina/ray_wrapper/examples/*/schedule_*.py и examples/scheduler/test.py (тривиальная тестовая задача-заглушка).

Идентификатор задачи (Task.id) генерируется как mlumina-{name}-priority-{priority}-{cpu}cpu-{gpu}gpu-{memory}memory-{uuid4} и используется и как ключ внутри планировщика, и как submission_id в Ray Jobs API — по нему же нужно передавать task_id в /change_task_priority и /cancel_task.


Revision #1
Created 2026-09-23 06:40:12 UTC by Маслов Алексей
Updated 2026-09-23 06:40:13 UTC by Маслов Алексей