- Go 66.3%
- TypeScript 31%
- JavaScript 1.6%
- Shell 1%
- Dockerfile 0.1%
|
|
||
|---|---|---|
| client-go | ||
| client-ts | ||
| cmd | ||
| data | ||
| docs | ||
| internal | ||
| packaging | ||
| tests | ||
| .dockerignore | ||
| .gitignore | ||
| .woodpecker.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| Dockerfile.ci | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| README.md | ||
chunker-upload
Сервис чанковой загрузки файлов с адаптацией к качеству сети.
Многоарендная архитектура с авторизацией TokenApp, тремя storage-бэкендами и вебхуками.
Быстрый старт
go run ./cmd/chunker-upload --addr :3000 --storage-backend inmemory
curl -X POST http://localhost:3000/myapp/init \
-H 'Authorization: Bearer my-token' \
-H 'Content-Type: application/json' \
-d '{"app_id":"myapp","file_name":"photo.jpg","file_size":10485760}'
Полный пример — cmd/chunker-demo/main.go (init → upload чанков → finish → webhook).
Конфигурация
Все параметры настраиваются через CLI-флаги, переменные окружения или YAML-файл (--config config.yaml / CONFIG_FILE).
| Параметр | CLI | Env | Default | Описание |
|---|---|---|---|---|
| Адрес | --addr |
ADDR |
:3000 |
HTTP адрес для привязки |
| Storage backend | --storage-backend |
STORAGE_BACKEND |
inmemory |
inmemory / sqlite / redis |
| SQLite путь | --database-path |
DATABASE_PATH |
./data/chunker.db |
Путь к файлу БД |
| Redis адрес | --redis-addr |
REDIS_ADDR |
localhost:6379 |
Адрес Redis/Valkey |
| Redis пароль | --redis-password |
REDIS_PASSWORD |
"" |
Пароль Redis/Valkey |
| Redis БД | --redis-db |
REDIS_DB |
0 |
Номер БД Redis |
| Директория uploads | --upload-dir |
UPLOAD_DIR |
./data/uploads |
Временные файлы загрузки |
| Директория completed | --completed-dir |
COMPLETED_DIR |
./data/completed |
Готовые файлы |
| CORS origins | --cors-origins |
CORS_ORIGINS |
* |
Разрешённые Origin (* для всех, или через запятую) |
| Публичный URL | --public-url |
PUBLIC_URL |
— | Внешний адрес чанкера (напр. https://chunker.example.com) |
| Audit-лог | --audit-log |
AUDIT_LOG |
./data/audit.jsonl |
JSONL-лог операций |
| Config файл | --config |
CONFIG_FILE |
— | YAML/JSON файл конфигурации |
TokenApp настраивается только в YAML-файле (секция token_apps):
token_apps:
- app_id: "myapp"
token: "secret-token"
base_path: "/myapp"
webhook_url: "https://app.example.com/webhook"
ttl_upload: 24h
ttl_completed: 72h
webhook_max_attempts: 5
webhook_initial_interval: 10s
webhook_max_interval: 5m
Приоритет: CLI → Env → Config file → Defaults.
Архитектура
HTTP-клиент (TS / Go SDK) ──► chunker-upload (Go) ──► Storage (InMemory / SQLite / Redis)
│
└──► FileStore (uploads/ → completed/)
└──► Webhook (POST на URL по завершении)
└──► Prometheus /metrics
| Компонент | Описание |
|---|---|
cmd/chunker-upload/ |
Точка входа сервера |
cmd/chunker-demo/ |
Демо (init → upload → finish → webhook) |
cmd/e2e-server/ |
Вспомогательный сервер для E2E тестов |
internal/handler/ |
HTTP-роуты (init, upload, finish, status, file, /metrics) |
internal/storage/ |
MetadataStorage: InMemory, SQLite (modernc.org/sqlite), Redis |
internal/filestore/ |
WriteAt-запись, SHA-256, перемещение файлов |
internal/webhook/ |
Асинхронные уведомления с retry и dead-letter |
internal/cleanup/ |
Фоновая очистка по TTL |
internal/metrics/ |
9 Prometheus-метрик |
internal/config/ |
CLI + env + YAML конфигурация |
client-ts/ |
TypeScript SDK (@ymnuk/chunker-upload-client) |
client-go/ |
Go SDK (зеркало TS-клиента) |
packaging/ |
systemd unit, nfpm-конфиг для deb/rpm/apk |
API
| Метод | Путь | Аутентификация | Описание |
|---|---|---|---|
| POST | /{basePath}/init |
Bearer token | Создать сессию загрузки |
| PUT | /{basePath}/upload/{id} |
— | Отправить чанк (CRC32, идемпотентность) |
| PUT | /{basePath}/finish/{id} |
— | Завершить (SHA-256, move, webhook) |
| GET | /{basePath}/status?id=... |
Bearer token | Статус сессии (получено байт, пропуски) |
| GET | /{basePath}/file/{id} |
Bearer token | Скачать завершённый файл |
| GET | /metrics |
— | Prometheus-метрики |
Жизненный цикл файла
Клиент (SDK) chunker-upload Storage (metadata) FileStore (disk)
│ │ │ │
│ POST /{basePath}/init │ │ │
│ Authorization: Bearer ◄────┤── CreateSession() ───────────► │ │
│◄──── {upload_id, public_url}│ │ │
│ │ │ │
│ PUT /{basePath}/upload/{id} │ │
│ X-Chunk-Offset, X-Chunk-Size │ │
│ X-Chunk-Crc32, X-Chunk-Id │ │ │
│ ├──── чанк 1 ──────────────►│── SaveChunk() ───────────────► │ │
│ │ │── WriteChunk() ────────────────────────────────────────►│
│ ├──── чанк 2 ──────────────►│── SaveChunk() ───────────────► │ │
│ │ │── WriteChunk() ────────────────────────────────────────►│
│ ├──── чанк N ──────────────►│── SaveChunk() ───────────────► │ │
│ │ │── WriteChunk() ────────────────────────────────────────►│
│ │ │ │
│ PUT /{basePath}/finish/{id} │ │ │
│ {"hash": "<SHA-256>"} │ │ │
│ │── ComputeHash() ───────────────────────────────────────►│
│ │── MoveToCompleted() ───────────────────────────────────►│
│ │── UpdateSession(status=completed) ───► │
│ │── POST webhook (Session JSON) ───► Приложение │
│◄──── {ok} │ │ │
│ │ │ │
│ │ │ │
│ Приложение (по вебхуку знает upload_id) │ │
│ │ │ │
│ GET /{basePath}/file/{id} │ │ │
│ Authorization: Bearer ◄────┤── GetSession() ───────────────►│ │
│ (проверка: статус completed, │ │
│ BasePath совпадает, │ │
│ файл есть на диске) │ │ │
│◄──── body (.final file) │── ServeFile() ─────────────────────────────────────────►│
Детальная спецификация — docs/openapi.yaml.
Storage-бэкенды
Переключение через --storage-backend / STORAGE_BACKEND.
| Бэкенд | Когда использовать | Плюсы | Минусы |
|---|---|---|---|
inmemory |
Разработка, тесты | Нет зависимостей | Всё теряется при перезапуске |
sqlite |
Одиночный сервер, малый/средний объём | Персистентность, zero-ops | Не масштабируется горизонтально |
redis |
Кластер, высокая нагрузка | Скорость, горизонтальное масштабирование | Нужен внешний Redis/Valkey |
Клиентские SDK
TypeScript (client-ts/)
npm install @ymnuk/chunker-upload-client
- UploadManager с параллельной отправкой, resume, адаптивным чанкингом
- 6 фильтров (EWMA, Kalman, HullMA, Median, SMA, CUSUM) + Mean Shift кластеризация
- Retry с экспоненциальной задержкой
- Адаптер для Angular
Go (client-go/)
import chunkeruploadclient "git.ymnuktech.ru/ymnuk/chunker-upload/client-go"
transport := chunkeruploadclient.NewHTTPTransport("https://upload.example.com")
uploader := chunkeruploadclient.NewUploader(transport)
result, err := uploader.Upload(ctx, "myapp", uploadID, "file.bin", reader, fileSize, token)
Полное зеркало TS-клиента: Transport, Uploader, Chunker, NetworkMonitor, Ensemble, Retry.
Установка
Docker
docker run -p 3000:3000 \
-v data:/data \
-e STORAGE_BACKEND=sqlite \
git.ymnuktech.ru/ymnuk/chunker-upload:latest
Пакеты (deb / rpm / apk)
См. docs/ci-cd.md — пакеты создаются в CI и содержат systemd unit, sysusers, tmpfiles.
Документация
Все разделы — docs/README.md:
- Конфигурация
- Протокол передачи
- Архитектура клиента
- Адаптация к сети
- Модель данных
- TokenApp и вебхуки
- CI/CD и сборка пакетов
- План развития
Лицензия
MIT