Class EntityIdempotency

java.lang.Object
org.apache.polaris.service.idempotency.EntityIdempotency

public final class EntityIdempotency extends Object
Helper for the entity-property idempotency model (single-transaction / "embedded key" approach).

Instead of persisting idempotency records in a dedicated store, this model stamps the idempotency key directly onto the internalProperties of the entity produced by the originating operation. Because the key is part of the same writeEntity call that creates (or updates) the entity, the key and the operation commit atomically in a single transaction — there is no "record-after-success" gap where the entity is committed but a separate idempotency write is lost.

The keys are stored under a single reserved internal-properties key (IDEMPOTENCY_KEYS_PROPERTY), encoded as the IS1 version marker followed by a base64url SMILE array of (key, expiryMillis) entries. Entries use single-character property names (k, e) to keep the serialized window small. The version prefix leaves room to evolve the encoding later without ambiguity.

For createTable this window holds a single entry, but the shape generalizes to a per-entity window for repeated mutations (e.g. updateTable). The window is bounded only by expiry (TTL): expired keys are dropped inline whenever the entity is rewritten (recordKey(java.util.Map<java.lang.String, java.lang.String>, java.util.UUID, java.time.Instant, java.time.Instant)), and expiry is also honored at read time (hasLiveKey(java.util.Map<java.lang.String, java.lang.String>, java.util.UUID, java.time.Instant)) so a stale-but-not-yet-purged key is treated as absent. Live keys are never evicted by count; a large safety ceiling (MAX_LIVE_KEYS) bounds the window by failing the write rather than dropping a still-live key.

  • Field Details

    • IDEMPOTENCY_KEYS_PROPERTY

      public static final String IDEMPOTENCY_KEYS_PROPERTY
      Internal-properties key under which the per-entity idempotency key window is stored.
      See Also:
  • Method Details

    • hasLiveKey

      public static boolean hasLiveKey(Map<String,String> internalProperties, UUID key, Instant now)
      Returns true if key is recorded on the given internal properties and has not yet expired as of now.
    • recordKey

      public static Map<String,String> recordKey(Map<String,String> internalProperties, UUID key, Instant expiry, Instant now)
      Returns a copy of internalProperties with key recorded (expiring at expiry) and any keys already expired as of now dropped. This is the inline purge-on-write step: it runs within the same transaction that persists the entity, so no separate maintenance pass is required.

      The window is bounded only by expiry (TTL), never by a count-based eviction: a live key is never evicted to make room. Evicting a still-live key would silently disable idempotency for it and reintroduce the corruption failure mode (a retry would re-run and could 409), so under a high write rate we accept a larger window rather than dropping keys that could still be retried. A large safety ceiling (MAX_LIVE_KEYS) still bounds the window: when it is reached the write fails with a retryable PolarisServiceUnavailableException (HTTP 503 with a Retry-After) instead of dropping a key.