Skip to content

network-user/DotSoundComputeWorker

Repository files navigation

DotSoundComputeWorker

Python 3.12 Platform Category 8k+ lines of code

DotSoundComputeWorker

security audit passed - full, leaks + code audit date

Pull-воркер платформы DotSound. Опрашивает Backend по HMAC-подписанному HTTP, выполняет тяжёлый compute (Whisper-транскрипция, Demucs, аудио-фичи, нормализация каталога) вне публичного процесса Backend и отправляет результаты обратно. Репозиторий - транспортно-оркестрационный слой: продуктовые правила (пороги, веса, порядок fallback, выбор провайдера) живут в приватном пакете DotSoundPrivateCore и здесь не реализуются.

Source-available инженерный showcase. Репозиторий открыт для чтения кода и архитектурной оценки. Приватное ядро DotSoundPrivateCore намеренно не публикуется и требуется для полного локального запуска и сборки образов.

Что внутри

  • Два тракта, 18 типов задач. ASR идёт через /api/v1/internal/audio-compute/*, generic compute - через /api/v1/internal/compute/* (реестр HANDLERS[job_type]: аудио-фичи и эмбеддинги, similarity артистов и треков, нормализация каталога, SoundCloud-синхронизация, транскодирование, waveform, обложки). Каждый тракт включается флагом, HMAC-контракт общий.
  • Безопасность транспорта. Каждый запрос подписан HMAC: METHOD\nPATH\nTIMESTAMP\nNONCE\nSHA256(BODY), ключ - sha256(raw_secret) (сырой секрет в сеть не уходит), nonce на каждый запрос, trust_env=False. На старте валидируются worker_id и секрет, иначе воркер не стартует. На исходящих - SSRF-guard (блок private/loopback/metadata-адресов + повторный резолв через getaddrinfo против DNS-rebinding) и TLS-guard (HTTPS обязателен в prod); секреты редактируются в логах.
  • Resilience без ручного вмешательства. Результаты и фейлы ретраятся на сетевых ошибках и статусах {408, 425, 429, 500, 502, 503, 504} (экспонента, до 4 попыток), поверх - per-source rate-limit backoff со strike-счётчиком (2s → cap 30s). Таймаут задачи зажат между deadline_at из claim, полом 60s и потолком 1800s, чтобы lease освобождался вовремя. Завершение по SIGINT/SIGTERM дренажит in-flight задачи и шлёт best-effort result/fail.
  • Control plane через heartbeat. Ответы heartbeat несут claims_paused (пауза/резюм claim) и cancel_job_ids (per-job отмена); отмена проверяется между стадиями ASR-пайплайна, без отдельного управляющего канала.
  • Грабли продакшена решены. Аудио тянется через Backend-proxy (?proxy=1) с JSON-indirection и отказом от HLS, многослойными таймаутами и SHA-256 на лету, а для прямых CDN-URL - детерминированная per-host ротация User-Agent. ASR умеет quality-driven fallback (если Demucs ухудшил разметку Whisper - ретранскрипция оригинала и выбор лучшего) и одноразовый CUDA→CPU фолбэк на Windows.
  • Наблюдаемость. Структурные логи с correlation-scope (correlation_id/job_id/worker_id) и опциональные Prometheus-метрики: время стадий пайплайна, исход задач, lag heartbeat, in-flight.

Запуск

Секция для владельцев полного workspace DotSound. Публичный checkout без соседнего приватного пакета предназначен для ревью кода, а не для standalone-запуска.

# 1) Backend (в отдельном терминале)
cd ../DotSoundBackend
make dev-full
# Скопируй напечатанные worker_id + worker_secret в ./.env

# 2) Worker
cp .env.example .env
poetry install --with gpu,demucs,dev
make dev

Worker регистрирует heartbeat против http://localhost:8000 и начинает опрашивать задачи. На старте по умолчанию прелоадит модель Whisper в фоне; чтобы пропустить (например, для heartbeat-only прогонов), поставь WORKER_PRELOAD_ASR_ON_STARTUP=false в .env. Чтобы избежать неаутентифицированных загрузок модели и получить лучшие лимиты, добавь read-токен как WORKER_HF_TOKEN=<read-token> - worker сам прокинет его в HF_TOKEN для Hub-клиента.

Команды

Команда Назначение
make install-cpu poetry install --with cpu,dev - CPU-профиль
make install-gpu poetry install --with gpu,demucs,dev - CUDA + Demucs
make install-demucs только Demucs-группа
make dev / make run python -m worker - запуск воркера
make test pytest -q
make test-cov branch-coverage + scripts/check_branch_coverage.py (min 95%)
make lint ruff check + black --check + mypy worker
make format ruff check --fix + black
make docker-cpu / docker-gpu сборка CPU / GPU образов (контекст - родитель репо)
make docker-http лёгкий HTTP-образ через BuildKit named context
make docker-direct / docker-tor docker compose профили direct / tor

Стек

Python httpx Pydantic structlog Prometheus faster-whisper Demucs / PyTorch Docker Poetry pytest ruff mypy

Тесты

make test       # pytest -q
make test-cov   # branch-coverage + порог через check_branch_coverage.py
make lint       # ruff + black --check + mypy

tests/ зеркалит пакет: tests/worker/ (client, pipeline, main, preload, pull_control, asr, audio, observability, security) и tests/handlers/ (registry, dispatch, soundcloud, offload stubs). Markers s3, redis, slow объявлены в pyproject.toml.

Запуск на удалённой машине

poetry install --with gpu,demucs,dev   # при наличии CUDA GPU
make run

Или через Docker. Dockerfile.cpu / Dockerfile.gpu требуют build-контекст, содержащий и DotSoundComputeWorker/, и DotSoundPrivateCore/, поэтому собирай из родителя репо:

cd ..   # родитель (содержит DotSoundComputeWorker + DotSoundPrivateCore)
docker build \
  -f DotSoundComputeWorker/docker/Dockerfile.gpu \
  -t dotsound-compute-worker:gpu .
docker run --rm --gpus all \
  --read-only --tmpfs /tmp:size=2G \
  --env-file DotSoundComputeWorker/.env \
  dotsound-compute-worker:gpu

--read-only + tmpfs /tmp рекомендуются: пайплайну нужен только /tmp под короткоживущие аудиофайлы, остальная ФС остаётся неизменяемой, что ограничивает blast radius при компрометации процесса.

Docker HTTP-воркер (compute без ASR)

Для HTTP-задач без ASR используется лёгкий образ docker/Dockerfile.http. Сборки используют BuildKit named context для приватного ядра, поэтому команды запускай из DotSoundComputeWorker. Backend-запросы (heartbeat, claim, result, fail) всегда прямые и игнорируют HTTP_PROXY / ALL_PROXY - не запускай контейнер через torsocks, Tor настраивается только как job-proxy.

Native server IP (docker compose --profile direct):

WORKER_ID=w_...
WORKER_SECRET=...
WORKER_BACKEND_BASE_URL=https://backend.example.com
WORKER_HANDLES_ASR=false
WORKER_HANDLES_COMPUTE=true
WORKER_COMPUTE_CONCURRENCY_LIMIT=1
WORKER_DEFAULT_PROXY=
WORKER_PROXY_BY_TYPE_JSON=
docker compose --profile direct up -d --build worker-direct
docker compose logs -f worker-direct

Tor-режим (docker compose --profile tor):

WORKER_PROXY_BY_TYPE_JSON={"external_http":["socks5h://user:pass@proxy:9050"]}
docker compose --profile tor up -d --build worker-tor
docker compose logs -f worker-tor

Встроенный proxy-сервис - пример изолированного исходящего роутинга. На устройствах с собственным IP оставляй proxy-переменные пустыми.

Платформенные нюансы

  • CUDA на Windows. Если GPU-сборка не может загрузить cublas64_12.dll (CUDA 12 runtime не на PATH, хотя PyTorch видит GPU), первый transcribe залогирует whisper_cuda_runtime_failed_falling_back_cpu и продолжит на CPU. Поставь WORKER_ASR_DEVICE=cpu, чтобы пропустить неудачный GPU-путь, либо установи совместимый CUDA 12 runtime.
  • Demucs / FFmpeg. torchaudio 2.9+ грузит аудио через TorchCodec, которому нужны torchcodec (в extras demucs) и shared-библиотеки FFmpeg/libav в том же процессе (например, avcodec-*.dll). GPU-образ ставит ffmpeg через apt. На Windows используй full shared сборку и укажи WORKER_DEMUCS_FFMPEG_BIN на её bin; если не помогает - WSL2 или Linux-контейнер, плюс MSVC 2015-2022 x64 redistributable.

Безопасность

  • Никогда не редактируй .env ничем, кроме собственной shell. Worker и агенты не читают секретные файлы.
  • WORKER_SECRET Backend-админка показывает один раз при регистрации. Потерял - ротация обязательна.
  • Сужай per-worker allowed_ip_cidrs в Backend ровно до egress-IP, с которых работаешь.
  • Запускай за фаерволом: worker инициирует все соединения, ему нужен только outbound HTTPS до хоста Backend.

Протокол

HMAC + claim/result + heartbeat задокументированы в Backend: DotSoundBackend/docs/compute-worker-protocol.md (ASR-пути). Generic compute использует те же заголовки и HMAC, эндпоинты - под /api/v1/internal/compute/…, JSON-тела - как в internal compute router Backend. Wire-format считается compatibility-sensitive: при его изменении обновляется документация протокола в Backend и version в pyproject.toml.

Архитектура

worker/main.py поднимает долгоживущие async-петли в одном event loop: heartbeat, ASR-claim, compute-claim, submit результата/фейла и опциональный Prometheus. ASR-петля гоняет run_pipeline (download → Demucs → Whisper → align), compute-петля разбирает HANDLERS[job_type] с per-type семафорами. Бизнес-логика вызывается из DotSoundPrivateCore; сам воркер остаётся транспортом.

DotSoundComputeWorker/
├── worker/
│   ├── main.py            # asyncio-вход: heartbeat + claim + submit + сигналы
│   ├── config.py          # pydantic-settings, валидация HTTPS в prod
│   ├── backend_client.py  # HMAC-подписанный httpx.AsyncClient
│   ├── pull_control.py    # пауза/отмена claim по сигналам heartbeat
│   ├── pipeline.py        # ASR: download → demucs → whisper → align
│   ├── handlers/          # HANDLERS[job_type] для generic compute
│   ├── asr/               # обёртки Whisper / Demucs / align
│   ├── audio/             # download, ffmpeg env, embedding-провайдеры
│   ├── observability/     # structlog, correlation, метрики, redaction
│   └── security/          # secret loader, TLS-guard, SSRF-guard
├── docker/                # образы CPU + GPU + HTTP, tor
├── scripts/               # check_branch_coverage.py
├── tests/                 # security, observability, pipeline, client, handlers
└── docker-compose.yml     # профили direct / tor
  • Transport-only: пороги, веса, fallback, выбор провайдера, anti-abuse и quality policy - в приватном DotSoundPrivateCore, не здесь.
  • Outbound-only: worker инициирует все соединения; входящих портов нет, нужен только исходящий HTTPS к Backend.
  • HMAC везде: каждый Backend-запрос подписан; схема совпадает с compute-worker-protocol.md, другую подпись не изобретать.
  • Прямой Backend-тракт: heartbeat/claim/result/fail игнорируют HTTP_PROXY/ALL_PROXY; прокси - только для job-трафика.
  • Два тракта по флагам: ASR (/audio-compute/*) и generic compute (/compute/*) включаются независимо, оба off - воркер останавливается.
  • Секреты не утекают: .env не читается и не логируется, redaction в observability обязательна.

Лицензия

© 2026 DotSound. Все права защищены. Распространяется по DotSound Source-Available License 1.0: исходный код открыт только для чтения, ревью и непродакшен-оценки. Production, коммерческое использование, хостинг как сервис, распространение и производные продукты запрещены без письменного разрешения. См. LICENSE и NOTICE.

About

воркер для вычислений

Topics

Resources

License

Stars

1 star

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages