Class: Kotoshu::Cache::EvictionPolicy

Inherits:
Object
  • Object
show all
Defined in:
lib/kotoshu/cache/eviction_policy.rb

Overview

Pure value object: given a max total size and a list of cache entries, decide which entries to evict to fit under the cap.

The policy is LRU by cached_at timestamp (oldest evicted first). It performs no IO and has no concept of what an "entry" actually is on disk — it just sees a flat list of records each carrying :path, :size, :cached_at, and returns a plan. BaseCache#evict is responsible for collecting those records and executing the plan.

ISO8601 timestamps sort lexicographically because they are zero-padded, so the policy can compare them as plain strings without parsing. Entries with a nil cached_at sort oldest (treated as the epoch) so they are evicted first — a corrupt metadata.json should not strand an entry forever.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_size:) ⇒ EvictionPolicy

Returns a new instance of EvictionPolicy.

Parameters:

  • max_size (Integer, #to_i)

    maximum total size in bytes

Raises:

  • (ArgumentError)

    if max_size is negative



25
26
27
28
29
30
# File 'lib/kotoshu/cache/eviction_policy.rb', line 25

def initialize(max_size:)
  @max_size = max_size.to_i
  return unless @max_size.negative?

  raise ArgumentError, "max_size must be >= 0"
end

Instance Attribute Details

#max_sizeInteger (readonly)

Returns maximum total size in bytes.

Returns:

  • (Integer)

    maximum total size in bytes



21
22
23
# File 'lib/kotoshu/cache/eviction_policy.rb', line 21

def max_size
  @max_size
end

Instance Method Details

#plan(entries) ⇒ Hash

Decide which entries to evict.

Parameters:

  • entries (Array<Hash>)

    each hash has :path (String), :size (Integer), :cached_at (String, ISO8601, or nil)

Returns:

  • (Hash)

    { evict: Array, keep: Array, bytes_reclaimed: Integer }



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/kotoshu/cache/eviction_policy.rb', line 38

def plan(entries)
  sorted = entries.sort_by { |e| sort_key(e[:cached_at]) }
  total = sorted.sum { |e| e[:size].to_i }

  return { evict: [], keep: sorted, bytes_reclaimed: 0 } if total <= max_size

  evict = []
  reclaimed = 0
  sorted.each do |e|
    break if total - reclaimed <= max_size

    evict << e
    reclaimed += e[:size].to_i
  end

  { evict: evict, keep: sorted - evict, bytes_reclaimed: reclaimed }
end