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#
1313class 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
0 commit comments