Record Class ServerQuirkSummary.Retention

java.lang.Object
java.lang.Record
org.exoplatform.caldav.utils.ServerQuirkSummary.Retention
Record Components:
supersededNow - properties whose records a case observed in this pass replaces, at once
supersededWhenSettled - properties whose records a case excused on this server replaces, once they have gone quiet
settledGraceDays - how long a record survives after the case that replaces it was excused
retentionDays - how long any behaviour is kept after it was last seen
today - the current epoch day
Enclosing class:
ServerQuirkSummary

public static record ServerQuirkSummary.Retention(Set<String> supersededNow, Set<String> supersededWhenSettled, long settledGraceDays, long retentionDays, long today) extends Record
What a summary is allowed to forget on one write.

Built by the service, which knows the deployment's windows and the catalogue, and applied by the storage, which knows the row. The rules live here, together, because reading them apart is how the gap below went unnoticed.

Two strengths of supersession, and they are not interchangeable. A case observed in this very pass replaces the older record of the same property at once: that is contemporaneous evidence, and the property is demonstrably not being reported under its own name in the same breath. A case merely excused on the server is a permanent statement rather than an observation — somebody decided it, and it stays decided — so it cannot be allowed to erase a record on sight. It replaces the older record only once that record has itself gone quiet for settledGraceDays.

Why the second strength had to exist at all. Supersession originally fired only from observation, and an excusal is precisely what stops the case being observed: eXo acts on it, the copies converge, and the case falls silent. So the older record could only ever be cleaned up while the problem still existed — fix the problem and the stale entry outlived the fix by the whole retention window, all the while offering an administrator a broader, more dangerous excusal for something already solved. Every reclassification shipped from now on would have had the same shape.

Why the grace period is what keeps that safe. An excusal never expires, so without it a genuine, current record of the superseded property would be wiped on the first pass that did not happen to see it — and on a server excused for dropping the organizer of an appointment, that record is exactly the organizer vanishing from a real meeting, which EXO-89775 went out of its way to keep visible. With it, a behaviour that is still happening refreshes its stamp and stays; one frozen since before the reclassification does not.

  • Constructor Details

    • Retention

      public Retention(Set<String> supersededNow, Set<String> supersededWhenSettled, long settledGraceDays, long retentionDays, long today)
      Creates an instance of a Retention record class.
      Parameters:
      supersededNow - the value for the supersededNow record component
      supersededWhenSettled - the value for the supersededWhenSettled record component
      settledGraceDays - the value for the settledGraceDays record component
      retentionDays - the value for the retentionDays record component
      today - the value for the today record component
  • Method Details

    • forgets

      public boolean forgets(ServerQuirkSummary.Observation observation, ServerQuirkSummary.Tally tally)
      Whether one stored observation no longer belongs in the summary.

      Says nothing about an excusal in force: that exemption is the row's, and the caller applies it before asking — see the storage's own merge.

      Parameters:
      observation - what was seen
      tally - how often, and when last
      Returns:
      true when the record should go
    • toString

      public final String toString()
      Returns a string representation of this record class. The representation contains the name of the class, followed by the name and value of each of the record components.
      Specified by:
      toString in class Record
      Returns:
      a string representation of this object
    • hashCode

      public final int hashCode()
      Returns a hash code value for this object. The value is derived from the hash code of each of the record components.
      Specified by:
      hashCode in class Record
      Returns:
      a hash code value for this object
    • equals

      public final boolean equals(Object o)
      Indicates whether some other object is "equal to" this one. The objects are equal if the other object is of the same class and if all the record components are equal. Reference components are compared with Objects::equals(Object,Object); primitive components are compared with '=='.
      Specified by:
      equals in class Record
      Parameters:
      o - the object with which to compare
      Returns:
      true if this object is the same as the o argument; false otherwise.
    • supersededNow

      public Set<String> supersededNow()
      Returns the value of the supersededNow record component.
      Returns:
      the value of the supersededNow record component
    • supersededWhenSettled

      public Set<String> supersededWhenSettled()
      Returns the value of the supersededWhenSettled record component.
      Returns:
      the value of the supersededWhenSettled record component
    • settledGraceDays

      public long settledGraceDays()
      Returns the value of the settledGraceDays record component.
      Returns:
      the value of the settledGraceDays record component
    • retentionDays

      public long retentionDays()
      Returns the value of the retentionDays record component.
      Returns:
      the value of the retentionDays record component
    • today

      public long today()
      Returns the value of the today record component.
      Returns:
      the value of the today record component