Skip to content

B-Prod-P8: async state API (Flink 2.x) — spec §6e#8

Open
jackylee-ch wants to merge 1 commit into
b-prod-p7-tuningfrom
b-prod-p8-async
Open

B-Prod-P8: async state API (Flink 2.x) — spec §6e#8
jackylee-ch wants to merge 1 commit into
b-prod-p7-tuningfrom
b-prod-p8-async

Conversation

@jackylee-ch

Copy link
Copy Markdown
Owner

Summary

Implements the async-stateful surface for the ForSt-RS keyed backend (spec §6e).

  • PerKeyFuturesChain — ConcurrentHashMap chain heads; per-key serialization, cross-key parallelism, chain-shrink-on-completion. Backed by a JDK 21+ virtual-thread executor.
  • ForStRsAsync{Value,List,Map,Reducing,Aggregating}State — thin wrappers around the sync state classes; each public op returns CompletableFuture.
  • ForStRsAsyncValueState also exposes an explicit-key API (value(K)/update(K,T)/clear(K)) for chained continuations that need a stable per-call key.
  • ForStRsAbstractKeyedStateBackend — 5 new public getAsync*State getters + lazily-initialised PerKeyFuturesChain.

Key design notes

  • Worker-thread safety: the L5 delegate is single-threaded by design (shared mutable currentKeyBytes/keyOutBuffer). The async wrappers therefore guard the worker-thread step (set-key + state-fetch + op) with synchronized(backend). Per-key chain still preserves ordering; the lock just scopes the shared-buffer mutation window. The longer-term path is to either make the delegate thread-safe or shard state objects per key — but neither is required for correctness today.
  • MapState iteration: returns CompletableFuture<List<...>> snapshots rather than CompletableFuture<Iterator<...>>. The underlying FFM iterator + Arena lifetime is owned by the worker thread; off-thread Iterator consumption would be unsafe.
  • Implicit vs explicit key: state.value() captures backend.getCurrentKey() at call time (caller responsible for no concurrent rebind); state.value(K) accepts the key directly (recommended for chained continuations).

Test plan

  • PerKeyFuturesChainTest — 14 unit tests (12 spec-mandated + 2 bonus): per-key ordering preserved, cross-key parallelism, chain shrinks on completion, exception propagation + chain advances, null/edge cases.
  • ForStRsAsyncValueStateTest — 4 tests including the spec-mandated 100k get-then-put stress on 1k distinct keys; per-key chain serialization is verified by asserting final value == 100 for every key (no lost updates).
  • Full module test suite: 122 / 122 passing (was 104 pre-P8; +18 new).

🤖 Generated with Claude Code

Per spec §6e: introduces an async-stateful surface for the ForSt-RS
keyed backend. Each public op returns a CompletableFuture<T> and runs
on a virtual-thread executor; per-key serialization is provided by a
shared PerKeyFuturesChain so concurrent ops on the same key are
totally-ordered while ops on distinct keys parallelise freely.

Key components:
 - PerKeyFuturesChain<K>: ConcurrentHashMap chain heads with
   atomic enqueue + cleanup-on-completion (chain shrinks back to empty).
 - ForStRsAsync{Value,List,Map,Reducing,Aggregating}State: thin
   wrappers around the sync ForStRsXState classes. The L5 delegate
   uses shared mutable buffers (currentKeyBytes / keyOutBuffer) that
   are not concurrency-safe; every worker-thread step
   (set-key + state-fetch + op) is therefore guarded by
   synchronized(backend) — per-key chain still preserves ordering;
   the lock just scopes the shared-buffer mutation window.
 - ForStRsAsyncValueState additionally exposes an explicit-key API
   (value(K) / update(K, T) / clear(K)) so chained continuations
   (state.value(k).thenCompose(v -> state.update(k, v + 1))) bind
   to the same key on every step without depending on the shared
   delegate's currentKey field.
 - ForStRsAbstractKeyedStateBackend: 5 new public getters
   (getAsyncValueState/ListState/MapState/ReducingState/AggregatingState)
   and a lazily-constructed PerKeyFuturesChain backed by
   Executors.newVirtualThreadPerTaskExecutor (JDK 21+).
 - MapState async iteration returns CompletableFuture<List<...>>
   snapshots rather than CompletableFuture<Iterator<...>> because
   the underlying FFM iterator + Arena lifetime is owned by the
   worker thread; off-thread iterator consumption would be unsafe.

Tests:
 - PerKeyFuturesChainTest: 14 unit tests covering ordering,
   cross-key parallelism, chain-shrinkage, exception-recovery,
   1k-key × 50-op stress.
 - ForStRsAsyncValueStateTest: 4 tests including the spec-mandated
   100k get-then-put stress on 1k distinct keys, chained per-key
   to assert no lost updates (final value per key == 100).

Module test totals: 122 (was 104).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant