2016-08-16 4 views
1

私はこのようなコードでアマゾンの製品の広告API要求している:私は、彼らが毎秒1つのリクエストをしたいことが判明You are submitting requests too quickly. Please retry your requests at a slower rate..mapループでリクエスト率を制限する方法は?

products = asins.map do |asin| 
    item = Amazon::Ecs.item_lookup(asin, response_group: :Large) 

    json = {asin: item.get_element('Item').get('ASIN'), 
      manufacturer: item.get_element('ItemAttributes').get('Manufacturer'), 
      model: item.get_element('ItemAttributes').get('Model')} 
end 

と503エラーを取得します。 私の場合、これを行う最良の方法は何ですか?

+0

複数のアイテムを一度に検索するAPIはありませんか? –

+0

私は、ItemLookupリクエストごとに最大10個のItemIdsを許可していると思います。しかし、私が使用しているamazon-ecsの宝石はそれをサポートしていないと信じています。彼らが10個のアイテムを許可しても、検索するアイテムが何百もあるので、質問はまだ有効です。 –

+2

@MarcinDoliwaマップループに 'sleep 1'を追加するだけではいかがですか? –

答えて

1

おそらくただの反復の間で第二を待っていることにより、減速:sleepを使用して

products = asins.map do |asin| 
    sleep 1 # wait one second before doing the next API call 
    item = Amazon::Ecs.item_lookup(asin, response_group: :Large) 

    { 
    asin:   item.get_element('Item').get('ASIN'), 
    manufacturer: item.get_element('ItemAttributes').get('Manufacturer'), 
    model:  item.get_element('ItemAttributes').get('Model') 
    } 
end 
0

は心に来る最初のソリューション確かです。私の意見では、それはまったく管理できないので、エレガントなものではありません。私は作業を行うためにいくつかのキューイングシステムを考えています - おそらく、自己トリガーワーカーを使用してsidekiq?

いくつかの単純化されたコード:

# some kind of queueing logic, to fetch asins 
asin = AsinQueue.fetch 

# trigger first worker 
LookupWorker.perform_async(asin) 

# and the worker itself: 
class LookupWorker 
    include Sidekiq::Worker 

    def perform(asin) 
    item = Amazon::Ecs.item_lookup(asin, response_group: :Large) 
    # all the domain logic 

    # queue next lookup 
    next_asin = AsinQueue.fetch 
    LookupWorker.perform_in(1.second, next_asin) 
    end 
end 
0

ItemLookupでは、バッチ要求をサポートしています。一度に最大10個のアイテムを検索することができます。

関連する問題