[SDK-568] Add stable cross-SDK identifiers to IterableDataRegion - #1081
[SDK-568] Add stable cross-SDK identifiers to IterableDataRegion#1081franco-zalamena-iterable wants to merge 2 commits into
Conversation
Phase 1 of the cross-platform data region parity effort (iOS SDK-609, RN SDK-610, Flutter SDK-611). Android already exposed a typed enum, so this hardens it into the shared reference shape rather than redesigning it. All changes are additive. Source compatibility was verified by compiling the pre-existing public call patterns (getEndpoint, valueOf, values, ordinal, enum switch, the deprecated constants) against the new classes. - Add getRegionCode() and getCode() as stable cross-SDK identifiers. Numeric codes are declared explicitly rather than derived from ordinal(), so adding a region cannot renumber the existing ones. - Add from(String) and from(int) factories for wrapper bridges. from(String) also accepts a full endpoint URL, so the iOS SDK's string-based region values resolve without translation. - Log and fall back to US on unrecognised, empty or null input instead of resolving silently, so a misconfigured region surfaces in the logs rather than quietly routing EU-destined data to the US data center. - setDataRegion(null) falls back to US with a warning instead of leaving the region unset. - Deprecate IterableConstants.BASE_URL_API and BASE_URL_LINKS: both are hardcoded to the US region and unused by the SDK, which resolves its endpoint from the configured region. - Drop a duplicated overrideUrl application in IterableRequestTask; getBaseUrl() already applies it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…URL constants An unnamed removal target is how BASE_URL_API survived as dead public API in the first place, so commit to a version clients can plan against.
| * To resolve a region from a string or numeric identifier (for example when bridging from a | ||
| * cross-platform wrapper), use {@link IterableDataRegion#from(String)} or | ||
| * {@link IterableDataRegion#from(int)}, which fall back to | ||
| * {@link IterableDataRegion#US} and log on unrecognised values. |
There was a problem hiding this comment.
Minor grammatical nitpick: this javadoc documents the from() helpers, but doesn't mention that setDataRegion(null) itself falls back to US with a warning.
Since the parameter is non-null, this can be easy to miss on a quick read, and even more so when using plain Java which doesn't actually enforce this at compile-time.
Probably worth a sentence on the javadoc.
| @NonNull | ||
| public String getRegionCode() { | ||
| return this.regionCode; | ||
| } |
There was a problem hiding this comment.
IterableDataRegion.US.name() already returns "US" (and the same for EU), so this regionCode is an independently-maintained copy of the same string.
The newly-added javadoc for getCode() explains why code is deliberately decoupled from .ordinal() - is regionCode meant to be decoupled from .name() for a similar reason? If so, worth a line on the javadoc.
📝 Summary
Add stable cross-SDK identifiers and lookup factories to
IterableDataRegion, and log instead of silently falling back when a region is unrecognised.🎟️ Jira Ticket: SDK-568
📖 Description
SDK-568 asks for a typed data region across the SDKs. Android already had it —
IterableDataRegionhas been a Java enum withUS/EUsince 3.6.0 (MOB-6309),IterableConfigdefaults toUS, and the builder setter is@NonNull-typed. The divergence the epic describes lives on iOS (config.dataRegionis a rawString, so a typo compiles and misroutes data) and Web (isEuIterableServiceboolean).So this PR hardens Android into the shared reference shape rather than redesigning it. Everything is additive — no breaking change, and no action required from clients.
Deprecated
IterableConstants.BASE_URL_APIandBASE_URL_LINKS. Both are hardcoded to the US data region, are unused by the SDK (verified: zero references outside their own declarations), and contradict the configuredIterableDataRegion. They still resolve to the same values, so nothing breaks. Named 3.12.0 as the removal version in both the javadoc and the CHANGELOG — assuming this ships in 3.11.0, that's one minor of runway. Deliberately named rather than left as "a future major": the last Android major was 3.0.0 (2018), while public API does get removed in minors (3.5.5 droppedsetEncryptionEnforced, 3.8.0 dropped CBC encryption). An unnamed target is exactly howBASE_URL_APIsurvived this long as dead public API. If 3.11.0 isn't the release this lands in, the named version needs adjusting to keep the window intact.Reviewer notes
Not done deliberately:
setDataRegion(String)/setDataRegion(int)builder overloads. Adding them would make an existingsetDataRegion(null)call an ambiguous-overload compile error, sinceIterableDataRegionandStringare unrelated reference types — source-breaking. The staticfrom(...)factories give wrappers the same capability with no ambiguity.getEndpoint()stays public. Narrowing it is the one breaking change available here and it isn't worth it.Follow-up not in this PR: nothing in the repo will remind anyone to actually remove the constants at 3.12.0. That needs tracking in the 3.12.0 release scope, or it repeats the pattern it's meant to fix.
🧪 How to test?
Unit tests:
./gradlew :iterableapi:testDebugUnitTestNew coverage in
IterableDataRegionTest.kt(9 tests) — endpoints match the data centers, identifiers match the other SDKs,from()by region code / iOS-style endpoint URL / numeric code, case- and whitespace-insensitivity, unsupported-value fallback for both overloads, and identifier round-tripping.IterableConfigTest.ktaddsnullDataRegionFallsBackToUs(via reflection, since the null is only reachable from Java).Manual check of the logging path:
Expect a warning tagged
IterableDataRegionnaming the supported values (US (0), EU (1)) and a fallback toUS. Then confirmIterableDataRegion.from("EU")andfrom(1)both resolve toEUand that requests go tohttps://api.eu.iterable.com/api/.📚 Docs PR if applicable
TODO — the new identifiers/factories and the 3.12.0 deprecation are customer-facing and should be documented before release.