Class: OnlineMigrations::DataMigrations::BackfillShipLabeledAt
- Inherits:
-
OnlineMigrations::DataMigration
- Object
- OnlineMigrations::DataMigration
- OnlineMigrations::DataMigrations::BackfillShipLabeledAt
- Defined in:
- lib/online_migrations/data_migrations/backfill_ship_labeled_at.rb
Overview
Backfill ship_labeled_at on deliveries that reached pending_ship_confirm
(or downstream states) with a NULL timestamp. This happened because the
legacy set_ship_labeled_at used update_attribute in an after_transition
callback — the second save could be silently aborted by Delivery's heavy
before_save :set_proper_shipping_cost callback chain. Going forward,
ship_labeled_at is set in-memory in a before_transition callback so it
persists atomically with the state change. This backfill closes the gap
for ~77k pre-fix rows.
Backfill value: max(shipments.updated_at) for the delivery, falling back
to delivery.updated_at when the delivery has no shipments (e.g. fully
service-only or RMA-empty deliveries). For long-shipped invoiced rows
the proxy is approximate, but those rows never appear as warehouse
candidates anyway — accuracy matters most for pending_ship_confirm
rows where the carrier-pickup-time gate uses this column.
See app/models/delivery.rb (state machine before_transition for
pending_ship_confirm) for the forward-going write path.
Constant Summary collapse
- BATCH_SIZE =
Batch size.
5_000- ELIGIBLE_STATES =
Recognised eligible states.
%w[ pending_carrier_confirm pending_ship_confirm pending_manifest_completion return_labels_complete shipped invoiced ].freeze
Instance Method Summary collapse
Instance Method Details
#collection ⇒ Object
39 40 41 |
# File 'lib/online_migrations/data_migrations/backfill_ship_labeled_at.rb', line 39 def collection Delivery.where(state: ELIGIBLE_STATES, ship_labeled_at: nil).in_batches(of: BATCH_SIZE) end |
#count ⇒ Object
60 61 62 |
# File 'lib/online_migrations/data_migrations/backfill_ship_labeled_at.rb', line 60 def count Delivery.where(state: ELIGIBLE_STATES, ship_labeled_at: nil).count end |
#process(deliveries) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/online_migrations/data_migrations/backfill_ship_labeled_at.rb', line 43 def process(deliveries) delivery_ids = deliveries.pluck(:id) return if delivery_ids.empty? # Single correlated UPDATE per batch — bypasses every Delivery callback # (no validation re-run, no set_proper_shipping_cost recompute, no # paper_trail version row) and avoids 2N Rails round-trips. Filtered # to ship_labeled_at IS NULL to make the migration idempotent and # safe to re-run after partial completion. Delivery.where(id: delivery_ids, ship_labeled_at: nil).update_all(<<~SQL.squish) ship_labeled_at = COALESCE( (SELECT MAX(s.updated_at) FROM shipments s WHERE s.delivery_id = deliveries.id), deliveries.updated_at ) SQL end |