Google Cloud Datastore: экспорт объектов, соответствующих определенному запросу - PullRequest
0 голосов
/ 16 января 2019

Фон

Мне нужно отправить большую партию уведомлений примерно на ~ 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()

1 Ответ

0 голосов
/ 17 января 2019

Надежное решение этой проблемы - использование Google Dataflow. В настоящее время я использую его именно для этого, создавая CSV-файлы в облачном хранилище Google, которые содержат все ~ 500 тыс. Записей, соответствующих данному запросу хранилища данных.

Настройка может быть немного сложной, однако.

Перед тем, как начать, я использовал Очередь заданий Google с 10-минутным тайм-аутом вместо 30-секундного. Я не уверен, что вы можете сделать это исключительно в облачных функциях или вам нужно создать простой проект движка приложения, который будет выполнять функции обработчика запросов для этих задач

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...