Class: Retailer::SiblingPriceRefresher
- Inherits:
-
Object
- Object
- Retailer::SiblingPriceRefresher
- Includes:
- CatalogConstants
- Defined in:
- app/services/retailer/sibling_price_refresher.rb
Overview
Service to synchronously refresh retailer prices for sibling catalog items.
Used by the repricer to ensure fresh external price data before deciding
whether to raise Amazon prices.
This uses the REALTIME (synchronous) Oxylabs API, not the batch webhook system.
It should only be called for items that are candidates for price increases
to minimize API calls.
Defined Under Namespace
Classes: Result
Constant Summary collapse
- MAX_SIBLINGS_TO_PROBE =
Maximum sibling items to probe in one call (to limit API costs)
10- FRESHNESS_THRESHOLD =
Only refresh probes that are older than this threshold.
Set to 6h so the nightly batch checker (~7am UTC) is still considered fresh
when the automation runs at ~11:15am UTC (4h15m gap), preventing every Buy
Box winner from triggering a blocking synchronous Oxylabs probe each run. 6.hours
Constants included from CatalogConstants
CatalogConstants::ALL_MAIN_CATALOG_IDS, CatalogConstants::AMAZON_CATALOG_IDS, CatalogConstants::AMAZON_CA_CATALOG_IDS, CatalogConstants::AMAZON_EU_CATALOG_IDS, CatalogConstants::AMAZON_NA_SELLER_IDS, CatalogConstants::AMAZON_SC_BE_CATALOG_ID, CatalogConstants::AMAZON_SC_CATALOG_IDS, CatalogConstants::AMAZON_SC_CA_CATALOG_ID, CatalogConstants::AMAZON_SC_DE_CATALOG_ID, CatalogConstants::AMAZON_SC_ES_CATALOG_ID, CatalogConstants::AMAZON_SC_FR_CATALOG_ID, CatalogConstants::AMAZON_SC_IT_CATALOG_ID, CatalogConstants::AMAZON_SC_NL_CATALOG_ID, CatalogConstants::AMAZON_SC_PL_CATALOG_ID, CatalogConstants::AMAZON_SC_SE_CATALOG_ID, CatalogConstants::AMAZON_SC_UK_CATALOG_ID, CatalogConstants::AMAZON_SC_US_CATALOG_ID, CatalogConstants::AMAZON_SELLER_IDS, CatalogConstants::AMAZON_US_CATALOG_IDS, CatalogConstants::AMAZON_VC_CATALOG_IDS, CatalogConstants::AMAZON_VC_CA_CATALOG_ID, CatalogConstants::AMAZON_VC_CA_CATALOG_IDS, CatalogConstants::AMAZON_VC_DIRECT_FULFILLMENT_CATALOG_IDS, CatalogConstants::AMAZON_VC_US_CATALOG_IDS, CatalogConstants::AMAZON_VC_US_WASN4_CATALOG_ID, CatalogConstants::AMAZON_VC_US_WAX7V_CATALOG_ID, CatalogConstants::AMAZON_VC_WAT0F_CA_CATALOG_ID, CatalogConstants::AMAZON_VC_WAT4D_CA_CATALOG_ID, CatalogConstants::AMAZON_VENDOR_CODE_TO_CATALOG_ID, CatalogConstants::BESTBUY_CANADA, CatalogConstants::BUILD_COM, CatalogConstants::CANADIAN_TIRE, CatalogConstants::CA_CATALOG_ID, CatalogConstants::COSTCO_CANADA, CatalogConstants::COSTCO_CATALOGS, CatalogConstants::COSTCO_USA, CatalogConstants::EU_CATALOG_ID, CatalogConstants::HOME_DEPOT_CANADA, CatalogConstants::HOME_DEPOT_CATALOGS, CatalogConstants::HOME_DEPOT_USA, CatalogConstants::HOUZZ, CatalogConstants::LOCALE_TO_CATALOG, CatalogConstants::LOWES_CANADA, CatalogConstants::LOWES_USA, CatalogConstants::MARKETPLACE_CATALOGS, CatalogConstants::PRICE_CHECK_ENABLED_CATALOGS, CatalogConstants::RONA_CANADA, CatalogConstants::US_CATALOG_ID, CatalogConstants::VENDOR_CATALOGS, CatalogConstants::WALMART_CATALOGS, CatalogConstants::WALMART_SELLER_CANADA, CatalogConstants::WALMART_SELLER_USA, CatalogConstants::WAYFAIR_CANADA, CatalogConstants::WAYFAIR_CATALOGS, CatalogConstants::WAYFAIR_GERMANY, CatalogConstants::WAYFAIR_USA
Instance Attribute Summary collapse
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#price_checker ⇒ Object
readonly
Returns the value of attribute price_checker.
Instance Method Summary collapse
-
#initialize(options = {}) ⇒ SiblingPriceRefresher
constructor
A new instance of SiblingPriceRefresher.
-
#refresh_for(catalog_item, force: false) ⇒ Result
Refresh sibling retailer prices for a given catalog item.
Methods included from CatalogConstants
amazon_catalog?, amazon_seller_catalog?, costco_catalog?, home_depot_catalog?, marketplace_catalog?, price_check_enabled?, vendor_catalog?, walmart_catalog?, wayfair_catalog?
Constructor Details
#initialize(options = {}) ⇒ SiblingPriceRefresher
Returns a new instance of SiblingPriceRefresher.
37 38 39 40 |
# File 'app/services/retailer/sibling_price_refresher.rb', line 37 def initialize( = {}) @price_checker = [:price_checker] || Retailer::PriceChecker.new @logger = [:logger] || Rails.logger end |
Instance Attribute Details
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
35 36 37 |
# File 'app/services/retailer/sibling_price_refresher.rb', line 35 def logger @logger end |
#price_checker ⇒ Object (readonly)
Returns the value of attribute price_checker.
35 36 37 |
# File 'app/services/retailer/sibling_price_refresher.rb', line 35 def price_checker @price_checker end |
Instance Method Details
#refresh_for(catalog_item, force: false) ⇒ Result
Refresh sibling retailer prices for a given catalog item.
Only refreshes items from catalogs with external_price_check_enabled.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'app/services/retailer/sibling_price_refresher.rb', line 48 def refresh_for(catalog_item, force: false) item_id = catalog_item.item_id store_id = catalog_item.catalog.store_id unless item_id @logger.warn "[SiblingPriceRefresher] No item_id for catalog_item #{catalog_item.id}" return Result.new(refreshed_count: 0, lowest_price: nil, prices: [], errors: ['No item_id']) end # Find sibling catalog items in non-Amazon catalogs with price checking enabled siblings = find_sibling_catalog_items(item_id, store_id, catalog_item.catalog_id) if siblings.empty? @logger.info "[SiblingPriceRefresher] No sibling catalog items found for item #{item_id}" return Result.new(refreshed_count: 0, lowest_price: nil, prices: [], errors: []) end # Filter to only items that need refresh (stale data) to_refresh = force ? siblings : siblings.select { |s| needs_refresh?(s) } @logger.info "[SiblingPriceRefresher] Found #{siblings.size} siblings, #{to_refresh.size} need refresh" # Limit to MAX_SIBLINGS_TO_PROBE to control costs to_refresh = to_refresh.first(MAX_SIBLINGS_TO_PROBE) # Synchronously probe each sibling refreshed_count = 0 prices = [] errors = [] to_refresh.each do |sibling| begin probe = @price_checker.check(sibling) if probe&.price_captured? refreshed_count += 1 prices << { catalog_item_id: sibling.id, catalog_name: sibling.catalog.name, price: probe.price, currency: probe.currency } @logger.info "[SiblingPriceRefresher] Refreshed #{sibling.catalog.name}: $#{probe.price}" elsif probe @logger.debug "[SiblingPriceRefresher] Probe completed but no price: #{probe.status}" end rescue StandardError => e @logger.error "[SiblingPriceRefresher] Error probing #{sibling.id}: #{e.}" errors << "#{sibling.catalog.name}: #{e.}" end end # Get the lowest price from refreshed items + existing fresh data all_prices = collect_all_sibling_prices(item_id, store_id, catalog_item.catalog_id) lowest_price = all_prices.min Result.new( refreshed_count: refreshed_count, lowest_price: lowest_price, prices: prices, errors: errors ) end |