Чанковая передача
Объект передаётся частями в рамках сессии. Сессия переживает разрыв связи, части можно лить параллельно и в любом порядке, а повторная отправка одной и той же части безопасна.
#Схема
Весь обмен происходит на префиксе /v1/chunks. Четыре обязательных шага и две ветки на случай, когда что-то пошло не так.
-
POST
Открытие
Сервис выдаёт
uploadIdи размер части -
PUT ×N
Части
Параллельно, в любом порядке, каждая — со своим
etag -
POST
Завершение
Сверка списка и сборка версии объекта
-
GET / DELETE
Докачка и отмена
Ветки на случай обрыва или ненужной сессии
#Открытие сессии
Сессия создаётся один раз на объект. В теле передаётся ключ объекта, полный размер в байтах и, если нужно, регион — иначе берётся регион по умолчанию из токена.
curl -X POST https://vault.goida.fun/v1/chunks \
-H "Authorization: Bearer vlt_ag_7Q2m4Xd9pKcRt6Yb" \
-H "X-Vault-Space: sp_3f9a21" \
-H "Content-Type: application/json" \
-d '{"key":"pg/main.dump","size":45742891008,"region":"ru"}'
{
"uploadId": "up_5KpR2n8vQz",
"key": "pg/main.dump",
"region": "ru",
"partSize": 8388608,
"parts": 5451,
"expiresAt": "2026-07-31T22:14:07Z"
}
partSize — рекомендация, а не требование: сервис подбирает её по размеру объекта и региону. Свой размер задавать можно, но он должен попадать в диапазон из раздела лимитов, иначе первая же часть вернёт E1004.
Сессия живёт 24 часа с момента открытия. Это окно на докачку, а не на передачу: если агент упал и вернулся через сутки, сессия уже закрыта и нужна новая.
#Отправка частей
Номера частей начинаются с единицы. Все части, кроме последней, должны быть одного размера — того, что вернулся при открытии сессии. Последняя может быть меньше.
curl -X PUT https://vault.goida.fun/v1/chunks/up_5KpR2n8vQz/1 \
-H "Authorization: Bearer vlt_ag_7Q2m4Xd9pKcRt6Yb" \
-H "Content-Type: application/octet-stream" \
-H "Content-Length: 8388608" \
--data-binary @part-00001.enc
{
"partNumber": 1,
"etag": "b71c4e9a02f8",
"size": 8388608,
"receivedAt": "2026-07-30T22:15:31Z"
}
Тело части — шифротекст, сервис его не разбирает. Заголовок Content-Length обязателен: без него запрос отклоняется с 411, потому что сервис резервирует место в квоте до начала приёма.
Части независимы, поэтому агент льёт их параллельно. Разумный потолок — 12 одновременных потоков на агента; выше начинается конкуренция за канал, и суммарная скорость падает, а не растёт.
Повторная отправка безопасна. Если часть с таким номером уже принята и её содержимое совпадает, сервис вернёт тот же etag и код 200, ничего не перезаписывая. Если содержимое отличается — 409 и код E1011: значит, агент собрал часть из других данных, и продолжать эту сессию нельзя.
#Завершение
Завершение — это заявление агента о том, из каких именно частей состоит объект. Сервис сверяет присланный список с тем, что принял, и расходится с ним не молча.
curl -X POST https://vault.goida.fun/v1/chunks/up_5KpR2n8vQz/complete \
-H "Authorization: Bearer vlt_ag_7Q2m4Xd9pKcRt6Yb" \
-H "Content-Type: application/json" \
-d '{"parts":[{"partNumber":1,"etag":"b71c4e9a02f8"},
{"partNumber":2,"etag":"3d0a8815ce64"}]}'
{
"key": "pg/main.dump",
"version": "v_2026073022_41",
"size": 45742891008,
"parts": 5451,
"region": "ru",
"copies": 3,
"completedAt": "2026-07-30T23:02:44Z"
}
После завершения версия объекта неизменяема. Новая копия того же ключа создаёт новую версию, старая остаётся доступной по своему идентификатору, пока её не удалит политика хранения пространства.
Поле copies — сколько копий части уже разложено по дисковым узлам региона. Целевое значение три; сразу после завершения там может стоять меньше, недостающие досоздаются в фоне за минуты. Подробнее — в разделе Надёжность хранения.
#Докачка после разрыва
Обрыв связи не требует начинать заново. Запрос состояния сессии возвращает список уже принятых частей — агенту остаётся долить недостающие.
curl https://vault.goida.fun/v1/chunks/up_5KpR2n8vQz \
-H "Authorization: Bearer vlt_ag_7Q2m4Xd9pKcRt6Yb"
{
"uploadId": "up_5KpR2n8vQz",
"key": "pg/main.dump",
"partSize": 8388608,
"parts": 5451,
"received": 4188,
"missing": [4189, 4190, 4191],
"expiresAt": "2026-07-31T22:14:07Z"
}
Список missing усечён до тысячи номеров — на объектах в десятки тысяч частей полный список сам по себе становится тяжёлым ответом. Если частей не хватает больше, запрашивайте состояние повторно по мере долива.
#Отмена
Ненужную сессию лучше закрыть явно: принятые части сразу освобождают место в квоте, не дожидаясь истечения суток.
curl -X DELETE https://vault.goida.fun/v1/chunks/up_5KpR2n8vQz \
-H "Authorization: Bearer vlt_ag_7Q2m4Xd9pKcRt6Yb"
Отмена необратима: восстановить закрытую сессию нельзя, части удаляются. Уже завершённые версии объекта отмена не трогает.
#Выгрузка и Range
Восстановление — обратная операция. Объект отдаётся потоком, с поддержкой докачки через Range: восстановление на сотни гигабайт нередко прерывается, и перекачивать всё заново никто не хочет.
curl https://vault.goida.fun/v1/objects/pg/main.dump \
-H "Authorization: Bearer vlt_ag_7Q2m4Xd9pKcRt6Yb" \
-H "X-Vault-Version: v_2026073022_41" \
-H "Range: bytes=8388608-16777215" \
-o part.enc
HTTP/2 206
Accept-Ranges: bytes
Content-Range: bytes 8388608-16777215/45742891008
Content-Length: 8388608
X-Vault-Version: v_2026073022_41
Без заголовка X-Vault-Version отдаётся последняя версия ключа. Диапазон за пределами объекта возвращает 416 с кодом E2015.
Выгрузка идёт из того региона, где объект был принят, — в другом регионе его просто нет. Если регион недоступен целиком, ждать придётся его возвращения: копий за пределами региона мы не держим, см. Надёжность хранения.
#Известные ограничения
- Докачка после истечения суток невозможна:
uploadIdзакрывается вместе с сессией, нужна новая. Мы несколько раз обсуждали продление окна, но длинные сессии держат место в квоте и мешают тем, кто укладывается в норму. - Список
missingусечён до 1000 номеров. - Смена региона у открытой сессии не поддерживается — только через отмену и повторное открытие.
- Параллельная запись в один ключ из двух агентов создаст две независимые версии. Это не ошибка, но обычно означает, что расписания задвоились.