Class: RivetCms::RevisionPruner
- Inherits:
-
Object
- Object
- RivetCms::RevisionPruner
- Defined in:
- app/services/rivet_cms/revision_pruner.rb
Overview
Enforces retention for one document: keeps the newest N superseded published snapshots per locale and destroys the rest. Candidates exclude the document's live pointers, re-read from the database so a stale in-memory copy cannot target a revision another request just published, and pruning is skipped entirely unless a live published revision exists.
Instance Method Summary collapse
-
#initialize(document, keep_ids: []) ⇒ RevisionPruner
constructor
A new instance of RevisionPruner.
- #prune! ⇒ Object
Constructor Details
#initialize(document, keep_ids: []) ⇒ RevisionPruner
Returns a new instance of RevisionPruner.
8 9 10 11 12 |
# File 'app/services/rivet_cms/revision_pruner.rb', line 8 def initialize(document, keep_ids: []) @document = document @keep_ids = Array(keep_ids).compact @destroyed = 0 end |
Instance Method Details
#prune! ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'app/services/rivet_cms/revision_pruner.rb', line 14 def prune! @destroyed = 0 # defensive: report this run, not a previous one retention = RivetCms.normalized_retention_for(@document) return 0 if retention == :all published_id, draft_id = live_pointers return 0 if published_id.nil? # nothing is live: never guess what to keep protected_ids = ([ published_id, draft_id ] + @keep_ids).compact live_locale = DocumentRevision.where(id: published_id).pick(:locale) # Retention applies per locale so one locale's publishes cannot destroy # another's, and no locale's snapshots become unreachable. A locale with # no live pointer keeps its newest snapshot as that locale's live one. locales.each do |locale| allowance = locale == live_locale ? retention : retention + 1 doomed = candidates(protected_ids, locale).order(created_at: :desc, id: :desc).offset(allowance) doomed.each do |revision| Hooks.run(:prune, revision) # destroy returns false when a callback halts it; count what actually # went, so the count and log cannot overstate the work. if revision.destroy @destroyed += 1 else Rails.logger&.warn("[RivetCms] could not prune revision #{revision.id}: destroy was halted") end end end Rails.logger&.info("[RivetCms] pruned #{@destroyed} superseded revision(s) for document #{@document.id}") if @destroyed.positive? @destroyed end |