Class: Familia::Features::Housekeeping::EnforceCollectionCaps
- Inherits:
-
Object
- Object
- Familia::Features::Housekeeping::EnforceCollectionCaps
- Defined in:
- lib/familia/features/housekeeping/enforce_collection_caps.rb
Overview
A reusable, idempotent chore that trims every capped collection on an instance down to its :max_length via +enforce_max_length!+.
Adding max_length: to a live collection caps future writes but leaves any existing overage in place until the next write. Register this chore and run it (once, or nightly until clean) to trim the backlog. A collection already within its cap trims zero members, so the chore returns the removed count on the first pass and nil on every clean pass after -- the truthy-modified / nil-no-op convention run_chores! aggregates on.
The class itself responds to +call+, so it registers directly:
class Customer < Familia::Horreum feature :housekeeping
sorted_set :events, max_length: 100
list :activity_log, max_length: 50
chore :enforce_collection_caps, Familia::Features::Housekeeping::EnforceCollectionCaps
end
It is also a base class. Capped lists have per-end semantics the sweep cannot infer (push-fed lists keep the tail, unshift-fed ones the head), so subclass and override +keep_for+ when a list is unshift-fed; override +collection_names+ to scope the sweep:
class InboxCaps < Familia::Features::Housekeeping::EnforceCollectionCaps def keep_for(name) name == :inbox ? :head : :tail end end
Class Method Summary collapse
-
.call(obj) ⇒ Integer?
Entry point when the class itself is registered as the chore.
Instance Method Summary collapse
-
#call(obj) ⇒ Integer?
Members removed, or nil when nothing trimmed.
-
#capped_collections(obj) ⇒ Object
protected
The (name, collection) pairs the sweep trims: every candidate from +collection_names+ that carries a :max_length.
-
#collection_names(obj) ⇒ Object
protected
Candidate collection names; override to scope the sweep.
- #enforce(name, collection) ⇒ Object protected
-
#keep_for(_name) ⇒ Object
protected
Which end of a capped list survives; override per list name for unshift-fed lists.
Class Method Details
.call(obj) ⇒ Integer?
Entry point when the class itself is registered as the chore.
46 47 48 |
# File 'lib/familia/features/housekeeping/enforce_collection_caps.rb', line 46 def self.call(obj) new.call(obj) end |
Instance Method Details
#call(obj) ⇒ Integer?
Returns members removed, or nil when nothing trimmed.
52 53 54 55 56 57 |
# File 'lib/familia/features/housekeeping/enforce_collection_caps.rb', line 52 def call(obj) removed = capped_collections(obj).sum do |name, collection| enforce(name, collection) end removed if removed.positive? end |
#capped_collections(obj) ⇒ Object (protected)
The (name, collection) pairs the sweep trims: every candidate from +collection_names+ that carries a :max_length. Uncapped collections and non-capping types report a nil max_length and drop out here, so the sweep never trips enforce_max_length!'s uncapped guard.
65 66 67 68 69 70 |
# File 'lib/familia/features/housekeeping/enforce_collection_caps.rb', line 65 def capped_collections(obj) collection_names(obj).filter_map do |name| collection = obj.send(name) [name, collection] if collection.max_length end end |
#collection_names(obj) ⇒ Object (protected)
Candidate collection names; override to scope the sweep.
73 74 75 |
# File 'lib/familia/features/housekeeping/enforce_collection_caps.rb', line 73 def collection_names(obj) obj.class..keys end |
#enforce(name, collection) ⇒ Object (protected)
77 78 79 80 81 82 83 84 |
# File 'lib/familia/features/housekeeping/enforce_collection_caps.rb', line 77 def enforce(name, collection) case collection when Familia::ListKey collection.enforce_max_length!(keep: keep_for(name)) else collection.enforce_max_length! end end |
#keep_for(_name) ⇒ Object (protected)
Which end of a capped list survives; override per list name for unshift-fed lists. The default matches push-fed lists.
88 89 90 |
# File 'lib/familia/features/housekeeping/enforce_collection_caps.rb', line 88 def keep_for(_name) :tail end |