Module: PartitionGardener::Layout::OccupiedWindow

Defined in:
lib/partition_gardener/layout/occupied_window.rb

Class Method Summary collapse

Class Method Details

.covering(occupied_segments, bucket) ⇒ Object



46
47
48
49
50
51
52
# File 'lib/partition_gardener/layout/occupied_window.rb', line 46

def covering(occupied_segments, bucket)
  occupied_segments.find do |segment|
    next false if segment.range_start > bucket

    segment.range_end == :max || segment.range_end > bucket
  end
end

.finish_with_high_end(segments, occupied_segments:, table_name:, active_end:) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/partition_gardener/layout/occupied_window.rb', line 62

def finish_with_high_end(segments, occupied_segments:, table_name:, active_end:)
  leftover = occupied_segments.reject { |occupant| segments.any? { |segment| segment.name == occupant.name } }
  leftover.each { |occupant| segments << occupant }

  return segments if occupied_segments.any? { |segment| segment.range_end == :max }

  segments << Plan::Segment.new(
    name: Naming.future_partition_name(table_name),
    range_start: future_start(occupied_segments, active_end),
    range_end: :max,
    kind: :future
  )
  segments
end

.future_start(occupied_segments, active_end) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/partition_gardener/layout/occupied_window.rb', line 77

def future_start(occupied_segments, active_end)
  later_ends = occupied_segments.filter_map do |segment|
    segment.range_end if segment.range_end.is_a?(Date) && segment.range_end > active_end
  end

  [active_end, *later_ends].max
end

.next_bucket_index(buckets, bound, from:) ⇒ Object



54
55
56
57
58
59
60
# File 'lib/partition_gardener/layout/occupied_window.rb', line 54

def next_bucket_index(buckets, bound, from:)
  return buckets.length if bound == :max

  index = from
  index += 1 while index < buckets.length && buckets[index] < bound
  index
end

.overlap?(partition, window) ⇒ Boolean

Returns:

  • (Boolean)


37
38
39
40
41
42
43
44
# File 'lib/partition_gardener/layout/occupied_window.rb', line 37

def overlap?(partition, window)
  return false unless partition.range_start.is_a?(Date)
  return false if partition.range_end.nil?
  return true if partition.range_end == :max
  return true if partition.range_end > window[:end]

  partition.range_start < window[:end] && partition.range_end > window[:start]
end

.plan_segments(config:, window:, hot_buckets:, year_bucket:, tail_slot:) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/partition_gardener/layout/occupied_window.rb', line 6

def plan_segments(config:, window:, hot_buckets:, year_bucket:, tail_slot:)
  occupied_segments = segments(table_name: config[:table_name], window: window, tail_slot: tail_slot)
  layout_kwargs = {
    config: config,
    active_start: window[:start],
    active_end: window[:end],
    occupied_segments: occupied_segments
  }

  if year_bucket
    CalendarYear.build_segments(**layout_kwargs, hot_years: hot_buckets)
  else
    SlidingWindow.build_segments(**layout_kwargs, hot_months: hot_buckets)
  end
end

.segments(table_name:, window:, tail_slot:) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/partition_gardener/layout/occupied_window.rb', line 22

def segments(table_name:, window:, tail_slot:)
  Connection.attached_partitions(table_name).filter_map do |partition|
    next if partition.default
    next if tail_slot.call(partition.name)
    next unless overlap?(partition, window)

    Plan::Segment.new(
      name: partition.name,
      range_start: partition.range_start,
      range_end: partition.range_end,
      kind: :hot_bucket
    )
  end.sort_by(&:range_start)
end