Skip to content

Commit 3da732f

Browse files
committed
Batch the item sync job
This commit takes advantage of the multi-asin item lookup requests and performs the item sync job in batches of 10.
1 parent 1229548 commit 3da732f

File tree

2 files changed

+38
-12
lines changed

2 files changed

+38
-12
lines changed

app/jobs/item_sync_job.rb

+38-11
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
# query the Amazon record associated with the ASIN and make any required local
99
# updates.
1010
#
11-
# Bang methods (ex. `#amazon_item!`) perform an HTTP request.
11+
# Bang methods (ex. `#sync_batch!`) perform an HTTP request.
1212
#
1313
class ItemSyncJob < ApplicationJob
14+
# Maximum number of ASINs in one request
15+
BATCH_SIZE = AmazonProductAPI::ItemLookupEndpoint::ASIN_LIMIT
16+
1417
queue_as :default
1518

1619
def initialize
@@ -28,28 +31,52 @@ def perform(*_args)
2831

2932
attr_reader :client
3033

34+
# Syncs all database items with their Amazon sources
3135
def sync_all!
32-
# This is done in slices to avoid Amazon rate limits
33-
Item.all.each_slice(3) do |items|
34-
items.each { |item| sync! item }
36+
# This is done in slices and batches to avoid Amazon rate limits
37+
Item.all.each_slice(BATCH_SIZE * 3) do |batches|
38+
batches.each_slice(BATCH_SIZE) { |batch| sync_batch! batch }
3539
sleep 2.seconds unless Rails.env.test?
3640
end
3741
end
3842

39-
def sync!(item)
40-
Rails.logger.info green("Syncing item #{item.id}: #{item.name}")
41-
update_hash = amazon_item!(item).update_hash
43+
# Syncs one batch of items with Amazon (up to the batch size limit)
44+
def sync_batch!(items)
45+
count = items.count
46+
validate_batch_size(count)
47+
48+
Rails.logger.info "Fetching #{count} items: #{items.map(&:asin).join(',')}"
49+
50+
items_updates = get_updates_for! items
51+
items_updates.map { |item, updates| update_item(item, updates) }
52+
end
53+
54+
# Returns pairs of items and their corresponding update hashes
55+
def get_updates_for!(items)
56+
query = client.item_lookup(*items.map(&:asin))
57+
amazon_items = query.response
58+
updates = amazon_items.map(&:update_hash)
59+
60+
items.zip(updates)
61+
end
62+
63+
def validate_batch_size(count)
64+
return unless count > BATCH_SIZE
65+
raise ArgumentError,
66+
"Batch size too large: #{count}/#{BATCH_SIZE}"
67+
end
68+
69+
def update_item(item, update_hash)
70+
Rails.logger.info green(
71+
"Syncing item #{item.id}: (#{item.asin}) #{item.name.truncate(64)}"
72+
)
4273
item.assign_attributes(update_hash)
4374
return unless item.changed?
4475

4576
Rails.logger.info bold_green("Changed:\n") + item.changes.pretty_inspect
4677
item.save!
4778
end
4879

49-
def amazon_item!(item)
50-
client.item_lookup(item.asin).response.first
51-
end
52-
5380
# Some styles for log text. This is so minor that it's not worth
5481
# bringing in a full library.
5582

lib/amazon_product_api/endpoint.rb

-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ def get(http: HTTParty)
3838
# Performs the search query and returns the processed response
3939
def response(http: HTTParty, logger: Rails.logger)
4040
response = parse_response get(http: http)
41-
logger.debug response
4241
process_response(response)
4342
end
4443

0 commit comments

Comments
 (0)