Skip to content

[AI-FSSDK] [FSSDK-12760] add localHoldouts to datafile for backward compatibility#633

Merged
jaeopt merged 3 commits into
masterfrom
ai/jaeopt/FSSDK-12760-local-datafile
Jun 15, 2026
Merged

[AI-FSSDK] [FSSDK-12760] add localHoldouts to datafile for backward compatibility#633
jaeopt merged 3 commits into
masterfrom
ai/jaeopt/FSSDK-12760-local-datafile

Conversation

@jaeopt

@jaeopt jaeopt commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds support for the new top-level localHoldouts datafile section so older SDKs (Gen 1/Gen 2) that don't understand local holdouts safely ignore them while Gen 3 SDKs scope holdouts by section membership.

Changes

  • HoldoutConfig — section-aware constructor (globalHoldouts, localHoldouts). Entries in holdouts are global (any includedRules is stripped); entries in localHoldouts must carry includedRules (null/missing → log error + skip; empty list → valid but inert). Legacy single-list constructor preserved as deprecated.
  • DatafileProjectConfig — new 21-arg v4 constructor accepting localHoldouts separately. Legacy 20-arg constructor auto-partitions a mixed list by entity-level includedRules for backward compatibility with existing callers.
  • All 4 parsers (Gson, Jackson, org.json, json-simple) — read the optional top-level localHoldouts array and pass it through alongside holdouts.
  • Holdout — docstring updates clarifying that scope comes from the datafile section, not includedRules.
  • Tests — new section-aware tests in HoldoutConfigTest (8 added, 25 total) plus moved the existing local-holdout entry in holdouts-project-config.json into the new localHoldouts section. All existing parser/DecisionService/UserContext tests continue to pass unchanged.

Jira ticket

FSSDK-12760

Reference PRs

Test plan

  • ./gradlew :core-api:test — all suites pass (HoldoutConfigTest: 25/25; all 4 parser tests pass; DecisionServiceTest and OptimizelyUserContextTest pass)
  • ./gradlew test — all modules pass
  • CI green

@jaeopt

jaeopt commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

I reviewed and it looks good to me.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds backward-compatible support for a new top-level localHoldouts datafile section so Gen 3 SDKs can scope holdouts by datafile section, while older SDKs safely ignore the new section.

Changes:

  • Introduces a section-aware HoldoutConfig(List holdouts, List localHoldouts) constructor and keeps the legacy single-list constructor as deprecated.
  • Updates all parsers (Gson/Jackson/org.json/json-simple) to read optional localHoldouts and pass it through to DatafileProjectConfig.
  • Updates test fixtures and adds section-aware unit tests to validate global vs. local behavior.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
core-api/src/test/resources/config/holdouts-project-config.json Moves the local holdout entry into the new top-level localHoldouts section for parser/test coverage.
core-api/src/test/java/com/optimizely/ab/config/HoldoutConfigTest.java Adds tests covering section-aware routing, stripping includedRules for global-section entries, and local-section validation.
core-api/src/main/java/com/optimizely/ab/config/parser/JsonSimpleConfigParser.java Parses optional localHoldouts array and passes it into the v4 config constructor.
core-api/src/main/java/com/optimizely/ab/config/parser/JsonConfigParser.java Parses optional localHoldouts array and passes it into the v4 config constructor.
core-api/src/main/java/com/optimizely/ab/config/parser/DatafileJacksonDeserializer.java Deserializes optional localHoldouts and passes it through to DatafileProjectConfig.
core-api/src/main/java/com/optimizely/ab/config/parser/DatafileGsonDeserializer.java Deserializes optional localHoldouts and passes it through to DatafileProjectConfig.
core-api/src/main/java/com/optimizely/ab/config/HoldoutConfig.java Implements section-aware mapping and preserves legacy includedRules-based behavior via deprecated constructor.
core-api/src/main/java/com/optimizely/ab/config/Holdout.java Updates documentation to clarify that section membership controls scope (with includedRules used for local targeting).
core-api/src/main/java/com/optimizely/ab/config/DatafileProjectConfig.java Adds a 21-arg v4 constructor and partitions legacy mixed holdouts lists for backward compatibility.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread core-api/src/main/java/com/optimizely/ab/config/HoldoutConfig.java Outdated
Comment thread core-api/src/main/java/com/optimizely/ab/config/HoldoutConfig.java Outdated
Comment thread core-api/src/main/java/com/optimizely/ab/config/DatafileProjectConfig.java Outdated
jaeopt and others added 2 commits June 15, 2026 15:28
…Rules behavior

Copilot review flagged that the Javadoc/comments claimed empty includedRules
on localHoldouts was skipped with an error, but the implementation treats
empty as valid-but-inert (only null is skipped). Also clarified that
includedRules stripping for global entries happens while building the
mapping, not "at parse time".

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@Mat001 Mat001 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

@jaeopt jaeopt merged commit ecb136d into master Jun 15, 2026
16 of 17 checks passed
@jaeopt jaeopt deleted the ai/jaeopt/FSSDK-12760-local-datafile branch June 15, 2026 23:48
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.

3 participants