Skip to content

Conversation

@leoromanovsky
Copy link
Member

Motivation

The precomputed client receives server-side computed flag assignments in an obfuscated wire format. This PR adds the data transfer objects (DTOs) and utilities needed to parse and work with this format.

Changes

Utilities:

  • ObfuscationUtils - MD5 hashing for flag key obfuscation lookups

DTOs:

  • PrecomputedFlag - Represents a precomputed flag assignment (allocation, variation, type, value, logging config)
  • PrecomputedBandit - Represents a precomputed bandit assignment (action, probability, attributes)
  • PrecomputedConfigurationResponse - Wire protocol response with flags, bandits, salt, and metadata
  • BanditResult - Simple container for bandit action lookup results

Exceptions:

  • MissingSubjectKeyException - Thrown when subject key is required but not provided

Tests:

  • ObfuscationUtilsTest - MD5 hash consistency and standard test vectors
  • PrecomputedConfigurationResponseTest - Serialization round-trips, null handling, environment parsing

Decisions

  • Used Jackson annotations for JSON parsing (consistent with rest of SDK)
  • Made DTOs immutable with @JsonCreator constructors
  • Added @JsonIgnoreProperties(ignoreUnknown = true) for forward compatibility
  • Environment field supports both string and object formats for flexibility
  • Base64-encoded fields are kept encoded in DTOs; decoding happens at usage site

PR Stack

This PR is part of the precomputed client feature, split for easier review:

main
├── precomputed/1-base-cache-file
│   └─┬─ precomputed/3-storage-layer
│     │   └── precomputed/4-client
│     │       └── precomputed/5-example-app
│     │
└── 👉 precomputed/2-dtos-and-utils (this PR) ─┘

Why this structure: DTOs and utilities have no dependencies on other new code, making them independently reviewable and testable. They form the "vocabulary" that the rest of the feature uses.

Add the foundational data structures and utilities for the precomputed
client feature:

- ObfuscationUtils: MD5 hashing for flag key obfuscation
- PrecomputedFlag: DTO for precomputed flag assignments
- PrecomputedBandit: DTO for precomputed bandit assignments
- PrecomputedConfigurationResponse: Wire protocol response parsing
- BanditResult: Result container for bandit action lookups
- MissingSubjectKeyException: Validation exception

Includes comprehensive unit tests for serialization round-trips and
MD5 hash consistency.
@leoromanovsky leoromanovsky marked this pull request as ready for review January 28, 2026 16:39
Replace Integer.toHexString() with a pre-computed hex character lookup
table for byte-to-hex conversion. This avoids creating intermediate
String objects for each byte, reducing allocations.

Mirrors optimization from iOS SDK PR #91/#93.
Add md5HexPrefix() method that only converts the bytes needed for a
given prefix length, avoiding unnecessary work when only a prefix is
required (e.g., cache file naming uses first 8 chars).

Includes unrolled loop for the common 4-byte (8 hex char) case to
help compiler optimization, following iOS SDK PR #93 approach.
@leoromanovsky leoromanovsky enabled auto-merge (squash) February 3, 2026 02:34
@leoromanovsky leoromanovsky merged commit 072014d into main Feb 3, 2026
4 of 12 checks passed
@leoromanovsky leoromanovsky deleted the precomputed/2-dtos-and-utils branch February 3, 2026 02:38
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