mt5-manager/docs/architecture.md

Устройство приложения и API

Документация · Конфигурация · Эксплуатация

Компоненты

Браузер → FastAPI → TerminalManager → процессы MT5 (/portable)
                 → ConfigStore   → личный JSON
                 → MT5_Control   → psutil + чтение SQLite
Каждый MT5 → ServiceStateWriter → общая SQLite в Common/Files
Файл Ответственность
run.py Параметры запуска Uvicorn; --reload включается только явно
main.py Страницы, проверка входных данных, HTTP API и время жизни менеджера
config.py Проверка JSON, разрешение путей и атомарное сохранение
terminal_manager.py Создание, подключение счетов, запуск, остановка и очередь задач
mt5_control.py Поиск процессов по пути EXE и чтение последних данных сервиса
project_updates.py Проверка upstream, fast-forward, сборка и копирование сервиса
ServiceStateWriter.mq5 Регистрация терминала и запись текущего состояния
deploy_service.py Первоначальный сценарий развёртывания; общая функция компиляции
templates/, static/ Jinja2, локальные CSS/SVG и JavaScript без Bootstrap/jQuery

SQLite содержит terminals с уникальным именем папки и сведениями об установке и states с последним снимком счёта/соединения. Сервис работает независимо от графиков, использует WAL, тайм-аут блокировки и UPSERT. История ещё не записывается. Временные метки — Unix-секунды UTC (TimeGMT() на стороне MQL5).

Python определяет наличие процесса через psutil. Если процесс есть и данные не старее 30 секунд, внутренний статус — running; иначе при живом процессе starting, при отсутствии — stopped. Интерфейс дополнительно различает подключённый счёт и отсутствие торгового соединения.

Фоновые операции

Длительная команда возвращает HTTP 202 и объект задачи. Это подтверждает постановку в очередь, а не успех. Клиент запрашивает GET /api/jobs/{id} до done или error. Задачи выполняются одним рабочим потоком; повторная команда для того же экземпляра пока его задача не завершена отклоняется. Глобальные операции проекта не принимаются при других незавершённых задачах и на время своей работы блокируют новые команды терминалам.

{
  "id": "идентификатор",
  "folder": "MetaTrader5.5",
  "action": "create",
  "status": "queued",
  "stage": "Ожидание",
  "warnings": []
}

Состояния: queued, running, done, error. При ошибке добавляется error, у операций проекта — также result при наличии результата. В глобальных задачах folder — пустая строка. Задачи находятся в памяти; старые завершённые записи постепенно удаляются (сохраняется примерно 50 последних). Они не переживают перезапуск менеджера и не являются постоянным журналом.

Маршруты

Метод и путь Назначение
GET / Главная страница
GET /settings Настройки
POST /instances/{name} Текущее состояние указанного экземпляра
POST /start/{name} Запуск и проверка, 202
POST /stop/{name} Остановка, 202
POST /create/{name} Создание с именем в пути, 202; тело AccountInput необязательно
POST /api/terminals Создание, 202; имя можно предложить автоматически
PUT /api/terminals/{name}/account Сохранение/применение реквизитов, 202
GET /api/jobs/{id} Состояние задачи; неизвестный id — 404
GET /api/settings Общие параметры, записи счетов без паролей, файлы и предлагаемое имя
PUT /api/settings Сохранение общих настроек
PUT /api/files/{kind} Загрузка исходного файла как необработанного тела запроса
GET /api/project Локальные сведения Git, сборки, различий EX5 и автозапуска без сетевого fetch
POST /api/project/check Проверка удалённой ветки, 202
POST /api/project/update Загрузка через fast-forward, 202
POST /api/project/deploy Принудительная сборка/копирование сервиса, 202

AccountInput содержит name, login, server, password, clear_account. Для создания через /api/terminals к нему добавляется folder; пустое значение выбирает свободное имя автоматически. Пример без счёта:

{"folder": "MetaTrader5.5", "name": "Новый экземпляр"}

PUT /api/settings принимает полный набор редактируемых общих полей: mt5_folder, terminal_template, mt5_installation, service_ex5, startup_timeout_sec, disk_warning_mb. Остальная конфигурация сохраняется. Это не универсальный PATCH произвольного JSON.

Пути экземпляров вычисляются как mt5_folder / ключ в terminals общей функцией instance_directory(). В JSON у экземпляров нет собственного path; старое поле игнорируется при чтении. В ответах API поле path остаётся вычисляемым значением для отображения, а не настройкой расположения.

Загрузки: kind равен terminal, editor, servers или service. Используется бинарное тело, не multipart; предел для servers — 16 МиБ, для остальных — 256 МиБ. Пустые файлы отклоняются, у EXE проверяется сигнатура MZ. Это не полная проверка содержимого исполняемого файла.

Ошибки входных типов возвращают 422 без исходного объекта и пароля; известные ошибки запуска задач/настроек — обычно 400. Ошибка уже принятой операции видна в объекте задачи при HTTP 200 на запрос её состояния. Интерактивная схема FastAPI доступна по /docs, OpenAPI — /openapi.json.

Создание и авторизация

Новый экземпляр получает два EXE, config/servers.dat, сервис и config/services.ini с именем общей базы. В JSON он регистрируется до запуска. Ожидание сервиса проверяет свежесть, полный путь установки и при заданном счёте — логин, сервер и подключение. При неудаче удаляется только новая папка, принадлежащая этой операции, и её запись.

Для первого входа используются временный INI и KeepPrivate=1 в основной конфигурации терминала. После успешного подключения главное окно закрывается через WM_CLOSE, временный файл удаляется, затем проверяется обычный запуск. Обновление существующего счёта не удаляет папку терминала при ошибке.

Проверки разработки

python -m unittest discover -s tests -v

test_provisioning.py использует временные папки и имитирует границу с MT5, проверяя выбор файлов, учётные записи, сохранение и откат. test_http.py поднимает изолированный сервер на свободном порту и проверяет маршруты и отсутствие паролей в ответах. test_project_updates.py работает с временным локальным Git-remote: проверяет fetch, fast-forward, защиту правок и распространение EX5 с имитацией ME. Сетевой репозиторий и рабочие терминалы пользователя тесты не меняют.

Для ручной проверки реального MT5 есть tools/smoke_create_terminal.py. Он создаёт отдельную тестовую копию и базу, затем удаляет собственные файлы. Инструмент привязан к локальной установке C:\MT5\MetaTrader5.1 и пути общей базы из config.json; перед использованием проверьте эти значения. Вариант --with-account запрашивает реквизиты при запуске; логин и сервер можно передать через --login и --server, пароль вводится скрыто через getpass и не передаётся аргументом командной строки. Файл tools/test_first_login.py не используется. Это инструмент разработчика, а не шаг установки.