Extract SessionState: testable concurrency contract for Session#236
Merged
Conversation
The vmlens profile + plugin + com.vmlens:api were already present, but no CI job ever invoked them (only -P jcstress ran), so interleaving analysis ran nowhere. Mirror streambuffer's dedicated vmlens job: - New VmlensInterleavingSmokeTest: two threads increment a shared AtomicLong inside an AllInterleavings loop, asserting the sum is always 2. - pom: move com.vmlens:api into the main test <dependencies> (transitive-dep- free, dependencyConvergence-safe) so the test compiles in every build; add a managed surefire <exclude> so the ordinary suite skips it (vacuous without the agent); narrow the vmlens profile to an <includes> of just the smoke test. - publish.yml: add a lightweight pure-Java `vmlens` job (no native lib/models) running `mvn -Pvmlens test -Dtest=VmlensInterleavingSmokeTest -DfailIfNoTests=false` and uploading target/vmlens-report/. Scope is staged to one class for now; widen the profile <includes> as more concurrency tests are added (streambuffer runs vmlens over its whole suite). https://claude.ai/code/session_01HzCYFLjZZGFs4BsuUty35N
Extract the lock-guarded streaming-flag + transcript state machine out of Session into a new model-free SessionState (mirrors the testability-driven extraction of ChatTranscript). The native model call is injected as a callback that SessionState runs under its lock, between the streaming guard and the transcript commit, so Session keeps exactly its previous serialization semantics, exception types, and messages — behaviour-preserving refactor. Why: SessionState is the repo's real vmlens target — a multi-variable check-then-act (streamingActive + two-phase transcript commit), a different and untested interleaving class from the single-volatile CancellationToken Lincheck/jcstress coverage. Session itself isn't vmlens-testable (native calls); the extracted helper is. - New SessionState (public, root package) + Session delegates to it. - New vmlens SessionStateInterleavingTest: a send round races a beginStream + commitStreamedReply; asserts strict user/assistant alternation and a non-stuck streaming flag under every interleaving. - New model-free SessionStateTest (7 tests) pinning the extracted contract in the ordinary suite (the model-gated SessionConcurrencyTest can't run without a GGUF). - pom: vmlens profile <includes> + managed surefire <excludes> widened to the **/vmlens/*.java package glob. - publish.yml: vmlens job runs both vmlens tests via an explicit -Dtest list. Verified: compile (Error Prone/NullAway/Checker), javadoc, spotbugs:check (0 bugs), SessionStateTest, and both vmlens tests under the agent all green. https://claude.ai/code/session_01HzCYFLjZZGFs4BsuUty35N
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
Sessioninto a newSessionStateclass, making the concurrency contract testable without the native model library.SessionStateTest) pinning the streaming guard and transcript atomicity.SessionStateInterleavingTest,VmlensInterleavingSmokeTest) to verify strict user/assistant alternation under all thread interleavings.vmlensMaven profile.Rationale
Sessionpreviously owned both the concurrency logic (streaming guard, two-phase commit) and the model integration. This made the concurrency contract hard to test independently—any test required the native library and a model.SessionStateextracts the pure-Java state machine, accepting the model call as a callback that runs under the lock. This enables:SessionStateTest): Verify the streaming guard and transcript atomicity with plain lambdas, no native code.SessionStateInterleavingTest): Use vmlens to explore every possible thread interleaving and confirm the invariant (strict user/assistant alternation, non-stuck streaming flag) holds under all orderings.Sessionnow only orchestrates model calls;SessionStateowns the concurrency contract.Test plan
SessionStateTest(11 tests) covers send/stream/commit paths, error cases, and the streaming guard.SessionStateInterleavingTestdrives a send racing a stream through every interleaving under vmlens and asserts strict alternation.VmlensInterleavingSmokeTestvalidates the vmlens setup with a minimal atomic-increment example.SessionConcurrencyTestand model-gated integration tests remain unchanged and pass..github/workflows/publish.yml, default surefire run excludes vmlens tests (re-included only under thevmlensprofile).Related issues / PRs
Closes the concurrency-testing gap identified in the
SessionStateJavadoc: the compound atomicity of the streaming guard and two-phase commit is now pinned under vmlens.Checklist
CONTRIBUTING.mdandCODE_OF_CONDUCT.mdhttps://claude.ai/code/session_01HzCYFLjZZGFs4BsuUty35N