Как определить, сколько еще запросов может сделать мое приложение, прежде чем оно достигнет ограничения скорости API Twitter?

Мое приложение обычно делает запрос к API Twitter для временной шкалы пользователя (твиты пользователя).

Кроме того, я использую драгоценный камень twitter и настроил клиент Twitter, чтобы мое приложение могло выполнить запрос:

client = Twitter::REST::Client.new do |config|
  config.consumer_key        = ENV["TWITTER_CONSUMER_KEY"]
  config.consumer_secret     = ENV["TWITTER_CONSUMER_SECRET"]
  config.access_token        = ENV["TWITTER_ACCESS_TOKEN"]
  config.access_token_secret = ENV["TWITTER_ACCESS_TOKEN_SECRET"]
end

Конечная точка, к которой я обращаюсь - https://api.twitter.com/1.1/statuses/user_timeline.json - имеет ограничение скорости 900 запросов каждые 15 минут.

Если я правильно понимаю, есть 2 распространенных способа определить, достигло ли мое приложение своего предела скорости, но ни один из них мне не нужен:

Первый подход:

Это функция, которую я написал, которая пытается сделать запрос на твиты пользователя, и если приложение имеет ограничение скорости, оно вызовет исключение.

def get_tweets_from_TwitterAPI(twitter_handle)
  tweets = []
  begin
    tweets = CLIENT.user_timeline(twitter_handle)
  rescue Twitter::Error::TooManyRequests => error
    raise error
  end
  return tweets
end

Проблема такого подхода в том, что я хотел бы узнать, сколько еще запросов может безопасно выполнить мое приложение, прежде чем я сделаю запрос к API Twitter. Я боюсь, что при таком подходе мое приложение будет пинговать API Twitter через много времени после того, как оно достигнет ограничения скорости, и это откроет мое приложение для карательных действий со стороны Twitter (например, мое приложение будет занесено в черный список).

Второй подход Второй подход - сделать запрос к этой конечной точке Twitter - https://api.twitter.com/1.1/application/rate_limit_status.json - который отправляет данные обратно о том, где находится статус приложения для данного ограничения скорости.

Но опять же, у этой конечной точки также есть собственный предел скорости (180 запросов каждые 15 минут), который не очень высок. Мое приложение взорвется за этот предел. В идеальном мире я хотел бы определить текущий статус ограничения скорости моего приложения, прежде чем я сделаю запрос к API вообще. Так что:

def start_tweets_fetch
  number_of_requests_in_last_15 minutes = WHERE DO I GET THIS NUMBER FROM??
  if number_of_requests_in_last_15 minutes <= 900
    get_tweets_from_TwitterAPI(twitter_handle)
  end
end

Я представляю, что мне нужно увеличить число, которое я сохранил в своей базе данных, чтобы отслеживать запросы к API. Или есть более простой способ?

2 ответа

Я не могу говорить о драгоценном камне, который вы используете, но способ отследить лимиты ваших запросов без необходимости дополнительного вызова конечной точки rate_limit_status - это изучить X-Rate-Limit-Remaining заголовки при каждом вызове API. Однако я не знаю, доступны ли эти данные на геме Ruby, который вы используете.

редактировать

Это ответ на вопрос Энди Пайпера, который, я думаю, является самым простым способом отслеживать оставшиеся звонки.

Предполагая, что вы используете этот драгоценный камень Twitter, похоже, что каждый ответ от драгоценного камня будет заполнять Twitter::RateLimit объект с информацией из заголовков ограничения скорости, как предложил Энди.

Вы должны быть в состоянии получить доступ к этой информации, как это:

tweets = CLIENT.user_timeline(twitter_handle)

remaining_calls = tweets.rate_limit.remaining

Оттуда вы можете сохранить это значение, чтобы проверить его при следующем запросе. Как вы его сохраните и проверите, зависит от вас, но остальная часть моего ответа все еще может быть полезна для этого.


Примечание: я не пробовал этот метод раньше, но я бы попробовал в вашей ситуации одно из первых, если бы не сохранял журналы запросов на постоянной основе.

Одним из способов может быть использование встроенного в Cache API Rails. Это позволит вам хранить любое значение в кеш-хранилище, которое должно быть быстрее и легче, чем база данных.

number_of_requests_in_last_15 = Rails.cache.fetch("twitter_requests", expires_in: 15.minutes) { 0 }
if number_of_requests_in_last_15 minutes <= 900
  get_tweets_from_TwitterAPI(twitter_handle)
  Rails.cache.increment("twitter_requests")
end

Давайте разберем это

Rails.cache.fetch("twitter_requests", expires_in: 15.minutes) { 0 }:

  • fetch метод на Rails.cache будет пытаться получить значение для ключа twitter_requests,
  • Если ключ не существует, он оценивает блок и устанавливает возвращаемое значение в качестве нового значения ключа и возвращает его. В этом случае, если ключ twitter_requests не существует, новое значение ключа будет 0,
  • expires_in: 15.minutes опция, переданная методу извлечения, говорит об автоматической очистке этого ключа (twitter_requests каждые 15 минут

Rails.cache.increment("twitter_requests"):

  • Увеличивает значение в twitter_requests ключ на 1.

Заметки

  • По умолчанию Rails будет использовать хранилище данных в памяти. Это должно работать без проблем, но любые значения, хранящиеся в кеше, будут сбрасываться каждый раз, когда вы перезапускаете сервер rails.
  • Бэкэнд кеша настраивается и может быть изменен на другие популярные системы (например, memcache, redis), но они также должны быть запущены и доступны Rails.
  • Возможно, вы захотите увеличить кеш перед вызовом API, чтобы уменьшить вероятность истечения срока действия кеша между моментом его проверки и приращением. Увеличение ключа, который не существует, вернет nil,
Другие вопросы по тегам