Class: WhittakerTech::Aeon::Forker

Inherits:
Object
  • Object
show all
Defined in:
app/services/whittaker_tech/aeon/forker.rb

Overview

Stateless service that performs forward-only timeline forking. Closes the current Allocation at a pivot point, creates a successor with lineage, set-based invalidates future Occurrence rows, and inline-projects the new allocation.

Two modes: - Fork future — +pivot > valid_from+: past occurrences are preserved, only future ones are invalidated. - Fork all — +pivot == valid_from+: every occurrence is invalidated and the allocation is fully replaced.

Examples:

Fork at a future point

Forker.call(allocation_id: alloc.id, pivot: 1.week.from_now, rrule: new_rule)

Replace entirely (fork all)

Forker.call(allocation_id: alloc.id, pivot: alloc.valid_from, rrule: new_rule)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(allocation_id:, pivot:, new_attrs:) ⇒ Forker

Returns a new instance of Forker.

Parameters:

  • allocation_id (String)

    UUID of the allocation to fork

  • pivot (Time)

    the point at which to split the timeline

  • new_attrs (Hash)

    attribute overrides for the successor



33
34
35
36
37
# File 'app/services/whittaker_tech/aeon/forker.rb', line 33

def initialize(allocation_id:, pivot:, new_attrs:)
  @allocation_id = allocation_id
  @pivot = pivot
  @new_attrs = new_attrs
end

Class Method Details

.call(allocation_id:, pivot:, **new_attrs) ⇒ Allocation

Returns the newly created successor.

Parameters:

  • allocation_id (String)

    UUID of the allocation to fork

  • pivot (Time)

    the point at which to split the timeline

  • new_attrs (Hash)

    attribute overrides for the successor allocation

Returns:



26
27
28
# File 'app/services/whittaker_tech/aeon/forker.rb', line 26

def self.call(allocation_id:, pivot:, **new_attrs)
  new(allocation_id: allocation_id, pivot: pivot, new_attrs: new_attrs).call
end

Instance Method Details

#callAllocation

Executes the fork within a serialised transaction.

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
# File 'app/services/whittaker_tech/aeon/forker.rb', line 42

def call
  Allocation.transaction do
    Allocation.connection.execute("SET LOCAL aeon.bypass_guard = 'true'")
    old_allocation = lock_allocation!
    validate_pivot!(old_allocation)
    close_allocation!(old_allocation)
    new_allocation = create_successor!(old_allocation)
    invalidate_future_occurrences!(old_allocation, new_allocation)
    project_successor!(new_allocation)
    new_allocation
  end
end