I have been testing the backfills a bit over the last couple months on production and I have some thoughts on efficiency. Lets take a look at the code for the backfill batch job:
def perform(transaction_sync_batch)
complete_orders = ::Spree::Order.complete.where(shipment_state: 'shipped')
if transaction_sync_batch.start_date
complete_orders = complete_orders.where("completed_at >= ?", transaction_sync_batch.start_date.beginning_of_day)
end
if transaction_sync_batch.end_date
complete_orders = complete_orders.where("completed_at <= ?", transaction_sync_batch.end_date.end_of_day)
end
complete_orders.find_each do |order|
next if order.taxjar_order_transactions.any?
SuperGood::SolidusTaxjar::ReportTransactionJob.perform_later(order, transaction_sync_batch)
end
end
The first line:
complete_orders = ::Spree::Order.complete.where(shipment_state: 'shipped')
By itself, that's an extremely expensive sql query. If a store has hundreds of thousands, or millions of orders, this could take a VERY long time, or freeze the thread. This has happened to me. There needs to be some lower bound to the date. Either require the start_date or have a date in the admin for when Taxjar started. For instance, we've been using spree / solidus since Dec 2010, but started using Taxjar April 2021. We backfilled to Feb 2021 when we started. A good default date would be Feb 2021 for the taxjar_start_date. That would prevent 10+ years of orders from getting queried.
next if order.taxjar_order_transactions.any?
this is an N+1 query since it fetches taxjar_order_transactions for each order in the loop. This can be resolved with an includes and where
what I propose:
# put a lower bound on the start_date calendar select = to SuperGood::SolidusTaxjar.configuration.taxjar_start_date
start_date = if transaction_sync_batch.start_date
transaction_sync_batch.start_date.beginning_of_day
else
SuperGood::SolidusTaxjar.configuration.taxjar_start_date
end
complete_orders = ::Spree::Order.complete.
includes(:taxjar_order_transactions).
where("taxjar_order_transactions.order_id": nil).
where(shipment_state: 'shipped').
where("completed_at >= ?", start_date)
if transaction_sync_batch.end_date
complete_orders = complete_orders.where("completed_at <= ?", transaction_sync_batch.end_date.end_of_day)
end
complete_orders.each do |order|
SuperGood::SolidusTaxjar::ReportTransactionJob.perform_later(order, transaction_sync_batch)
end
thoughts?
I have been testing the backfills a bit over the last couple months on production and I have some thoughts on efficiency. Lets take a look at the code for the backfill batch job:
The first line:
complete_orders = ::Spree::Order.complete.where(shipment_state: 'shipped')By itself, that's an extremely expensive sql query. If a store has hundreds of thousands, or millions of orders, this could take a VERY long time, or freeze the thread. This has happened to me. There needs to be some lower bound to the date. Either require the
start_dateor have a date in the admin for when Taxjar started. For instance, we've been using spree / solidus since Dec 2010, but started using Taxjar April 2021. We backfilled to Feb 2021 when we started. A good default date would be Feb 2021 for thetaxjar_start_date. That would prevent 10+ years of orders from getting queried.next if order.taxjar_order_transactions.any?this is an N+1 query since it fetches
taxjar_order_transactionsfor each order in the loop. This can be resolved with anincludesandwherewhat I propose:
thoughts?