EvaluationExposureDeduper
open class EvaluationExposureDeduper
Decides whether a hook should be told about an evaluation, so that repeated evaluations resolving to the same result do not invoke the hook again within a time window.
This class is not stable, and not subject to any backwards compatibility guarantees or semantic versioning. It is
experimental. Subclassing it to change which evaluations are deduplicated is supported, but the shape it is subclassed
through, and the components of EvaluationExposureKey a subclass reasons about, may change.
Deduplication is opt-in per hook: a hook is told about every evaluation until you wrap it in a DedupingHook, which is
what consults a deduper.
config.hooks = [
MetricsHook(), // told about every evaluation
DedupingHook(ObservabilityHook()), // default window
DedupingHook(TelemetryHook(), window: 30),
DedupingHook(ExperimentHook(), deduper: sharedDeduper)
]
This class is the SDK’s implementation: it remembers the result each flag last reported, and tells the hook about the flag again as soon as that result changes, or once the window elapses while it stays the same. Tracking one result per flag rather than every result seen keeps a flag that flips back and forth from hiding the flips, and holds one record per flag the application evaluates, so the window is the only thing there is to configure.
A deduper is consulted once per evaluation, before the series opens, so a suppressed evaluation invokes neither
beforeEvaluation nor afterEvaluation. Implementations must be thread-safe, because evaluations may be made from any
thread. Give each hook its own instance unless you intend hooks to share a window: the first hook to be told about an
exposure starts the window that suppresses the rest.
-
The dedupe window used by a deduper built without a window of its own. (10 minutes)
Declaration
Swift
public static let defaultWindow: TimeInterval -
Reads the clock a window is measured against, in seconds. This is what
shouldRecord(key:now:)reads when it is not given a time.CLOCK_MONOTONICcounts from an arbitrary point rather than from the epoch, so that correcting the device clock cannot stretch a window: were thisDate(), a correction that moved the clock backwards would leave every recorded time in the future and suppress those flags until real time caught up. It is POSIX rather than one of Darwin’s own clocks, so the same reading is available on every platform Swift builds for.On Apple platforms it keeps advancing while the device sleeps, unlike
mach_absolute_timeand everything built on it, such asDispatchTime.now()andProcessInfo.systemUptime, so a window is an interval of real time rather than of awake time. Where a platform’s monotonic clock instead stops while the host is suspended, a window outlasts the suspension, which holds a repeat back for longer rather than reporting one too often.Declaration
Swift
public static func monotonicNow() -> TimeInterval -
Declaration
Swift
public init(window: TimeInterval = EvaluationExposureDeduper.defaultWindow)Parameters
windowThe dedupe window, in seconds. Defaults to
defaultWindow. A value of zero or less disables deduplication, so every evaluation reaches the hook. -
Returns whether the hook should be told about the evaluation identified by the given key, and if so starts a new dedupe window for the flag.
DedupingHookcalls this once per evaluation. This implementation answers true when the flag is reporting a different result than it last did, and when the window has elapsed on the result it is repeating. SeeEvaluationExposureKeyfor what makes two evaluations the same result.The check and the update are performed together so that concurrent evaluations of the same flag cannot both be told to record.
Declaration
Swift
open func shouldRecord(key: EvaluationExposureKey, now: TimeInterval = EvaluationExposureDeduper.monotonicNow()) -> BoolParameters
keyThe key identifying the evaluation result.
nowA reading of a clock that counts from an arbitrary point, in seconds. Defaults to
monotonicNow(), which is not a time of day; see it for why a window is not measured againstDate(). -
Clears all recorded exposures, so the next evaluation of each is reported again.
DedupingHookcalls this when the evaluation context changes.Declaration
Swift
open func reset()
View on GitHub