Экспорт в объектное хранилище
Один JSON-объект на достигнутую цель в вашем бакете. Путь во все хранилища данных, кроме BigQuery.
1. Какой пробел закрывается
Раньше был один путь из MousePlayer в хранилище — к Google. Для Snowflake, Redshift и ClickHouse пути не было, хотя все читают объектные хранилища.
Поэтому мост пишет в объектное хранилище, а не каждую систему отдельно. Snowflake, Redshift и ClickHouse читают S3, BigQuery — Google Cloud Storage. Один экспорт достигает всех.
| Куда | Способ адресации |
|---|---|
| Amazon S3 | Signature Version 4, бакет в хосте |
| Cloudflare R2 | Signature Version 4 к эндпоинту аккаунта |
| Google Cloud Storage | через S3-совместимый API с ключом HMAC |
| MinIO, Wasabi, Backblaze B2 и другие | Signature Version 4 к вашему эндпоинту |
| Azure Blob Storage | SAS-ссылка контейнера — без подписи у нас |
2. Почему Azure отличается и это лучше
Azure Blob использует SharedKey, а не Signature Version 4. Вместо второй схемы подписи мост принимает SAS-ссылку контейнера — URL из вашего хранилища с готовой подписью.
Меньше кода у нас, меньше доверия от вас. Ключ аккаунта нам не виден: вы передаёте ограниченное вами разрешение на один контейнер со своим сроком, отзываемое независимо от остального.
Для S3 полезна та же сдержанность: разрешите ключу запись только в этот префикс . Ключ с правом лишь добавлять в mouseplayer/goals/ не сможет читать другие бакеты даже при утечке.
3. Объект на цель, ключ по дате
В объектном хранилище нет добавления в конец. Дневной файл пришлось бы переписывать целиком, а две одновременные цели перезаписали бы друг друга. Поэтому каждой цели — свой объект.
Цена — много маленьких объектов; структура ключа делает это удобным:
prefix/YYYY/MM/DD/channel/session-goal.json
Хранилище читает день как партицию; дозагрузка — сканирование префикса, не запрос. Для разбиения по проекту вместо даты добавьте ID канала в префикс.
Каждый объект — строка JSON
Намеренно без отступов: целый префикс читается как NDJSON без открытия объектов по одному. Время, проект, сеанс, ID клиента, цель, ценность, валюта и ссылка воспроизведения.
Пустое значение — null, а не ноль
Цель без денежной ценности записывает null. Ноль вошёл бы в несуществующую сумму: различие «сумма не задана» и «нулевая сумма» сохраняется.
4. Если ответ 403, сначала это
Отклонённый запрос S3 мало что говорит. Наш журнал объясняет больше, потому что регион входит в подпись. Неверный регион и ключ дают одинаковый 403; ключ виноват лишь в половине случаев.
Проверяйте по порядку:
- Регион точно как у бакета. R2 и Google Cloud Storage принимают
autoбез проверки, остальные проверяют. - Право на префикс. Ключ с областью
mouseplayer/не может писать вmouseplayer-goals/— завершающий слеш важен в ARN ресурса. - Эндпоинт для R2 и S3-совместимых хранилищ. Вставляйте хост без
https://; мы удалим префикс, но добавленный путь означает другой бакет.
ID ключа намеренно хранится открыто: по замыслу он в каждом подписанном запросе, шифрование не добавит защиты. Секрет зашифрован, не показывается повторно и не входит во внутреннюю очередь задачи.
Все названные товарные знаки принадлежат владельцам. У MousePlayer нет деловых отношений с поставщиками.