Class: WhittakerTech::Aeon::Projector
- Inherits:
-
Object
- Object
- WhittakerTech::Aeon::Projector
- Defined in:
- app/services/whittaker_tech/aeon/projector.rb
Overview
Stateless service that expands an Allocation into materialised Occurrence rows. Operates within a single +FOR UPDATE NOWAIT+ transaction to guarantee exclusive access.
Projection is: - Monotonic — +projected_until+ only moves forward. - Idempotent — +INSERT ON CONFLICT DO NOTHING+ prevents duplicates. - Bounded — capped by Configuration#max_projection_window and the allocation’s +valid_to+. - Batched — large result sets are sliced into UPSERT_BATCH_SIZE chunks to prevent unbounded SQL statements.
Constant Summary collapse
- UPSERT_BATCH_SIZE =
Maximum number of rows per +insert_all+ call.
5_000
Class Method Summary collapse
Instance Method Summary collapse
-
#call ⇒ void
Locks the allocation, expands occurrences from +projected_until+ to the capped horizon, upserts rows, and advances the frontier.
-
#initialize(allocation_id:, target_until:) ⇒ Projector
constructor
A new instance of Projector.
Constructor Details
#initialize(allocation_id:, target_until:) ⇒ Projector
Returns a new instance of Projector.
31 32 33 34 |
# File 'app/services/whittaker_tech/aeon/projector.rb', line 31 def initialize(allocation_id:, target_until:) @allocation_id = allocation_id @target_until = target_until end |
Class Method Details
.call(allocation_id:, target_until:) ⇒ void
This method returns an undefined value.
25 26 27 |
# File 'app/services/whittaker_tech/aeon/projector.rb', line 25 def self.call(allocation_id:, target_until:) new(allocation_id: allocation_id, target_until: target_until).call end |
Instance Method Details
#call ⇒ void
This method returns an undefined value.
Locks the allocation, expands occurrences from +projected_until+ to the capped horizon, upserts rows, and advances the frontier.
40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'app/services/whittaker_tech/aeon/projector.rb', line 40 def call Allocation.transaction do Allocation.connection.execute("SET LOCAL aeon.bypass_guard = 'true'") allocation = lock_allocation! return if already_projected?(allocation) cap_target!(allocation) rows = (allocation) upsert!(rows) if rows.any? advance_frontier!(allocation) end end |