Экспорт в объектное хранилище

Один JSON-объект на достигнутую цель в вашем бакете. Путь во все хранилища данных, кроме BigQuery.

1. Какой пробел закрывается

Раньше был один путь из MousePlayer в хранилище — к Google. Для Snowflake, Redshift и ClickHouse пути не было, хотя все читают объектные хранилища.

Поэтому мост пишет в объектное хранилище, а не каждую систему отдельно. Snowflake, Redshift и ClickHouse читают S3, BigQuery — Google Cloud Storage. Один экспорт достигает всех.

КудаСпособ адресации
Amazon S3Signature Version 4, бакет в хосте
Cloudflare R2Signature Version 4 к эндпоинту аккаунта
Google Cloud Storageчерез S3-совместимый API с ключом HMAC
MinIO, Wasabi, Backblaze B2 и другиеSignature Version 4 к вашему эндпоинту
Azure Blob StorageSAS-ссылка контейнера — без подписи у нас

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 нет деловых отношений с поставщиками.