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-effortresult/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 devWorker регистрирует 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 |
make test # pytest -q
make test-cov # branch-coverage + порог через check_branch_coverage.py
make lint # ruff + black --check + mypytests/ зеркалит пакет: 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 при компрометации процесса.
Для 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-directTor-режим (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.
torchaudio2.9+ грузит аудио через TorchCodec, которому нужныtorchcodec(в extrasdemucs) и 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_SECRETBackend-админка показывает один раз при регистрации. Потерял - ротация обязательна.- Сужай 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.