Skip to content

fix(flags): dedupe exposures by latest assignment#2987

Merged
leoromanovsky merged 4 commits into
developfrom
leo.romanovsky/ios-flags-exposure-cache-cycle
Jun 29, 2026
Merged

fix(flags): dedupe exposures by latest assignment#2987
leoromanovsky merged 4 commits into
developfrom
leo.romanovsky/ios-flags-exposure-cache-cycle

Conversation

@leoromanovsky

@leoromanovsky leoromanovsky commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Motivation

DatadogFlags exposure deduplication stored the full exposure tuple as already seen. That suppressed a valid exposure when a subject and flag cycled back to a previous assignment, for example A -> B -> A, because the final A had been seen before.

The cache also needs to protect mobile devices while supporting the expected client high-water mark of two subjects across 2,500 flags.

Related Android PR: DataDog/dd-sdk-android#3526 applies the same mobile exposure-cache contract.

Changes

  • Add a regression test proving A -> B -> A writes three exposure events.
  • Add focused exposure tracker tests covering repeated assignments, assignment cycles, and 2 subjects x 2,500 flags.
  • Change the exposure tracker cache to use targetingKey + flagKey as the key and allocationKey + variationKey as the latest cached value.
  • Keep duplicate suppression only for repeated evaluations of the current assignment.
  • Use platform NSCache with a 5,000-entry countLimit for the in-memory exposure assignment cache.

Decisions

  • Kept the change internal with no public API changes.
  • Used a count limit, not a byte limit, to avoid approximate object-size accounting while preserving a reviewer-friendly bound.
  • Sized the count limit around the expected two-subject, 2,500-flag high-water mark.
  • Used iOS's platform cache primitive instead of a custom deterministic LRU implementation; eviction order is intentionally not part of the correctness contract.
  • Matched the Android PR's count-based mobile policy while using iOS's platform cache primitive.
  • Matched dd-trace-go and openfeature-js-client semantics, where the dedupe key and assignment value are modeled separately so assignment changes re-emit exposures.

Validation:

  • xcodebuild -workspace Datadog.xcworkspace -scheme DatadogFlags -destination "platform=iOS Simulator,id=32AE07AE-F88E-4FF4-A384-F6A347AA3B98" -only-testing:DatadogFlagsTests/ExposureTrackerTests -only-testing:DatadogFlagsTests/ExposureLoggerTests/testLogExposureAssignmentCycle test
  • SKIP_LINT=1 xcodebuild -workspace Datadog.xcworkspace -scheme DatadogFlags -destination "platform=iOS Simulator,id=32AE07AE-F88E-4FF4-A384-F6A347AA3B98" test

@datadog-prod-us1-3

This comment has been minimized.

@leoromanovsky leoromanovsky force-pushed the leo.romanovsky/ios-flags-exposure-cache-cycle branch 2 times, most recently from 860f556 to fcc47a7 Compare June 10, 2026 19:16
@leoromanovsky leoromanovsky force-pushed the leo.romanovsky/ios-flags-exposure-cache-cycle branch from fcc47a7 to 0d2c045 Compare June 10, 2026 19:17
@dd-octo-sts-03ec73

dd-octo-sts-03ec73 Bot commented Jun 10, 2026

Copy link
Copy Markdown

🐑 PR Shepherd is maintaining this PR

I watch your PR and automatically fix CI failures, rebase your branch, handle flaky tests, and push it to the merge queue when it's ready.

More about what I do → Guide

To pause me on this PR, add the flow-skip label.

@barboraplasovska barboraplasovska left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! But you should add a CHANGELOG entry.

@barboraplasovska barboraplasovska left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@leoromanovsky leoromanovsky merged commit 8385dff into develop Jun 29, 2026
21 checks passed
@leoromanovsky leoromanovsky deleted the leo.romanovsky/ios-flags-exposure-cache-cycle branch June 29, 2026 11:38
@barboraplasovska barboraplasovska mentioned this pull request Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants