Class: Feed::Openai::ListGenerator
- Inherits:
-
BaseService
- Object
- BaseService
- Feed::Openai::ListGenerator
- Defined in:
- app/services/feed/openai/list_generator.rb
Overview
Pre-generates the OpenAI product feed and stores it in the database for fast retrieval
Constant Summary collapse
- BATCH_SIZE =
200
Instance Method Summary collapse
- #load_products(catalog, limit: nil, catalog_item_ids: nil) ⇒ Object
-
#process(catalogs: nil, catalog_item_ids: nil, limit: nil, delete_all: nil) ⇒ Object
Main method.
Instance Method Details
#load_products(catalog, limit: nil, catalog_item_ids: nil) ⇒ Object
67 68 69 70 71 |
# File 'app/services/feed/openai/list_generator.rb', line 67 def load_products(catalog, limit: nil, catalog_item_ids: nil) scope = product_scope(catalog, catalog_item_ids: catalog_item_ids) scope = scope.limit(limit) if limit.present? scope.map { |ci| Feed::Openai::OpenaiProductPresenter.new(ci) }.select(&:valid_for_openai?) end |
#process(catalogs: nil, catalog_item_ids: nil, limit: nil, delete_all: nil) ⇒ Object
Main method.
- catalogs: specify catalogs otherwise will be main catalogs (US and CA)
- catalog_item_ids: filter by specific catalog_item_ids, e.g you want to update only one product
- limit: optional limit to number of records to process
- delete_all: truncate all openai feed records in the catalog, useful for periodic cleanups
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'app/services/feed/openai/list_generator.rb', line 10 def process(catalogs: nil, catalog_item_ids: nil, limit: nil, delete_all: nil) require 'activerecord-import/base' require 'activerecord-import/active_record/adapters/postgresql_adapter' res = { products: 0 } catalogs ||= Catalog.for_google_feed if delete_all.nil? delete_all = catalog_item_ids.present? ? false : catalogs.present? end # Targeted update: delete specific items and narrow catalog scope before looping if catalog_item_ids.present? OpenaiFeed.where(catalog_item_id: catalog_item_ids).delete_all catalogs = catalogs.joins(:catalog_items).where(catalog_items: { id: catalog_item_ids }) end catalogs.each do |catalog| I18n.with_locale catalog.locale_for_catalog do logger.info "Processing OpenaiFeed items for catalog #{catalog.id}" if delete_all logger.info 'Purging OpenaiFeed' OpenaiFeed.where(catalog_id: catalog.id).delete_all end if limit.present? # Small scoped query (dev/debug) — simple path, no batching needed inserts = load_products(catalog, limit: limit, catalog_item_ids: catalog_item_ids).map do |p| logger.info "Generating json data for product #{p.id} mpn:#{p.mpn} upc:#{p.upc}" res[:products] += 1 build_insert(p) end import_inserts(inserts) if inserts.any? else # Full catalog run — stream via find_each + flush every BATCH_SIZE to cap RSS inserts = [] product_scope(catalog, catalog_item_ids: catalog_item_ids).find_each(batch_size: BATCH_SIZE) do |ci| p = Feed::Openai::OpenaiProductPresenter.new(ci) next unless p.valid_for_openai? logger.info "Generating json data for product #{p.id} mpn:#{p.mpn} upc:#{p.upc}" res[:products] += 1 inserts << build_insert(p) if inserts.size >= BATCH_SIZE import_inserts(inserts) inserts = [] end end import_inserts(inserts) if inserts.any? end end end res end |