8
8
# query the Amazon record associated with the ASIN and make any required local
9
9
# updates.
10
10
#
11
- # Bang methods (ex. `#amazon_item !`) perform an HTTP request.
11
+ # Bang methods (ex. `#sync_batch !`) perform an HTTP request.
12
12
#
13
13
class ItemSyncJob < ApplicationJob
14
+ # Maximum number of ASINs in one request
15
+ BATCH_SIZE = AmazonProductAPI ::ItemLookupEndpoint ::ASIN_LIMIT
16
+
14
17
queue_as :default
15
18
16
19
def initialize
@@ -28,28 +31,52 @@ def perform(*_args)
28
31
29
32
attr_reader :client
30
33
34
+ # Syncs all database items with their Amazon sources
31
35
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 }
35
39
sleep 2 . seconds unless Rails . env . test?
36
40
end
37
41
end
38
42
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
+ )
42
73
item . assign_attributes ( update_hash )
43
74
return unless item . changed?
44
75
45
76
Rails . logger . info bold_green ( "Changed:\n " ) + item . changes . pretty_inspect
46
77
item . save!
47
78
end
48
79
49
- def amazon_item! ( item )
50
- client . item_lookup ( item . asin ) . response . first
51
- end
52
-
53
80
# Some styles for log text. This is so minor that it's not worth
54
81
# bringing in a full library.
55
82
0 commit comments