Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
* 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.
* <p>
* 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 {@link EvaluationExposureKey} a subclass reasons about, may
* change.
* <p>
* Deduplication is opt-in per hook: a hook is told about every evaluation until you wrap it in a
* {@link DedupingHook}, which is what consults a deduper.
*
Expand Down Expand Up @@ -112,12 +117,10 @@ public synchronized void reset() {
private static final class TrackedFlag {
private final String mobileKeyHash;
private final String flagKey;
private final int hashCode;

TrackedFlag(EvaluationExposureKey key) {
this.mobileKeyHash = key.getMobileKeyHash();
this.flagKey = key.getFlagKey();
this.hashCode = 31 * Objects.hashCode(mobileKeyHash) + Objects.hashCode(flagKey);
}

@Override
Expand All @@ -130,14 +133,13 @@ public boolean equals(Object other) {
}

TrackedFlag o = (TrackedFlag) other;
return hashCode == o.hashCode
&& Objects.equals(flagKey, o.flagKey)
return Objects.equals(flagKey, o.flagKey)
&& Objects.equals(mobileKeyHash, o.mobileKeyHash);
}

@Override
public int hashCode() {
return hashCode;
return 31 * Objects.hashCode(mobileKeyHash) + Objects.hashCode(flagKey);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
* Identifies the evaluation result a hook is about to be told about, so that an
* {@link EvaluationExposureDeduper} can recognize a repeat of it.
* <p>
* This class is not stable, and not subject to any backwards compatibility guarantees or semantic versioning.
* It is experimental. Which components make up the identity of an evaluation is the most likely part to be
* revised, so a deduper subclass that reasons about them may need to change with it.
* <p>
* Two evaluations are the same exposure when every component here matches. The value is included
* directly rather than inferred from the variation and version: those are the identity LaunchDarkly
* uses to bucket summary events, but neither by itself guarantees that the payload is unchanged.
Expand Down Expand Up @@ -38,7 +42,7 @@
* experiment does not depend on the window; a hook that reads the reason itself is what can miss such
* a change until the window elapses.
* <p>
* Instances are immutable, and their hash code is computed once, the first time one is asked for.
* Instances are immutable.
*/
public final class EvaluationExposureKey {
private final String mobileKeyHash;
Expand All @@ -48,12 +52,6 @@ public final class EvaluationExposureKey {
private final int flagVersion;
private final String fullyQualifiedContextKey;

// Computed on demand, because the SDK's own deduper recognizes a repeat by the flag a key belongs
// to and the result it describes, and so never hashes a whole key: only a deduper of your own
// that holds keys in a map or a set does. Races are benign, as every thread computes the same
// value from fields that cannot change.
private int hashCode;

/**
* Creates a key with a JSON null value. Prefer the overload accepting {@code value}, since the
* variation and version do not by themselves distinguish one result from another.
Expand Down Expand Up @@ -159,17 +157,12 @@ public boolean equals(Object other) {

@Override
public int hashCode() {
int hash = hashCode;
if (hash == 0) {
hash = Objects.hashCode(mobileKeyHash);
hash = 31 * hash + Objects.hashCode(flagKey);
hash = 31 * hash + Objects.hashCode(value);
hash = 31 * hash + variation;
hash = 31 * hash + flagVersion;
hash = 31 * hash + Objects.hashCode(fullyQualifiedContextKey);
hashCode = hash;
}
return hash;
int hash = Objects.hashCode(mobileKeyHash);
hash = 31 * hash + Objects.hashCode(flagKey);
hash = 31 * hash + Objects.hashCode(value);
hash = 31 * hash + variation;
hash = 31 * hash + flagVersion;
return 31 * hash + Objects.hashCode(fullyQualifiedContextKey);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
/**
* Builds the key identifying the result an evaluation is about to return.
* <p>
* This interface is not stable, and not subject to any backwards compatibility guarantees or semantic versioning.
* It is experimental.
* <p>
* The SDK gives one of these to each {@link EvaluationSeriesContext} it builds, so that a hook which
* needs the identity of an evaluation can ask for it without the SDK building one for hooks that do
* not. {@link DedupingHook} is the hook that needs it.
Expand Down
Loading