Фон
Мне нужно отправить большую партию уведомлений примерно на ~ 1 млн устройств, и я создаю ее с помощью облачных функций Google.
В текущей настройке я ставлю каждый маркер устройства как сообщение PubSub, которое:
- хранит ожидающее уведомление в хранилище данных, которое используется для отслеживания попыток и статуса успеха
- пытается отправить уведомление
- помечает уведомление как успешное или неуспешное, если оно достаточно повторено и не прошло
Этот процесс запускается вручную человеком, загружающим CSV со всеми токенами. Встроенной повторной попытки должно быть достаточно в принципе, но я хотел убедиться, что если что-то не так с самими облачными функциями или с APN / FCM, я мог бы вернуть CSV всех неисправных токенов в том же формате, который был загружен, так что что пользователь может повторить попытку только в том случае, если / если он считает, что это хорошая идея.
Я запускаю уведомления как часть задания, которое я использую для запросов вместе со статусом уведомления. Для этого я настроил составной индекс на job_id
и status
и запускаю запрос по всем соответствующим уведомлениям и хочу либо направить его пользователю в виде файла, либо сохранить его в облачном хранилище Google, чтобы пользователь может загрузить его оттуда.
Выпуск
Предполагая, что что-то близкое к общему количеству уведомлений не удалось, и что я хочу получить все токены в одном файле, моя первая реализация была просто перебирать все совпадающие записи и строить результат. Проблема в том, что при их получении таким способом требуется около 1 минуты на 100_000 записей. Для чего-то, близкого ко всем уведомлениям, у меня ушло бы больше максимального таймаута облачной функции. Каждый объект занимает около 300 байтов, что делает весь экспорт около 300 МБ. Вероятно, я мог бы уменьшить это примерно до половины / двух третей размера, добавив больший индекс, который позволил бы мне делать проекцию только для полей, которые я хочу.
Единственная альтернатива, которую я могу придумать, - это шардинг уведомлений, чтобы разделить всю группу, скажем, на 100 шардов, создать 100 файлов с уведомлениями по 10 Кб каждый, а затем загрузить их все и соединить их вместе, когда пользователь пытается загрузить файл. ,
Причина, по которой я отправляю вопрос, состоит в том, что это похоже на относительно простую проблему, и это решение кажется более сложным, чем я ожидал, поэтому я полагаю, что я что-то упустил.
Вопросы
- Мне не хватает очевидного, более простого способа достичь того, чего я хочу?
- Раздражает ли ожидаемый путь чего-то подобного, и я должен просто принять сложность?
Код
Просто для ясности, это фрагмент кода, который я выполняю, и я просто перебираю ответ, который он возвращает, чтобы получить вывод.
def get_failures(job_id):
query = client.query(kind = Notification.kind)
query.add_filter('job_id', '=', str(job_id))
query.add_filter('status', '=', "failure")
return query.fetch()