Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.15.0] - 2026-07-16

### Fixed
- Wake storms from blocked transactions with fallback-triggering continuations, and phantom analysis-only effect executions: the static-analysis walker had no arm for a terminal erratum — it walked **past** a `waitFor` retry or an `abort` into nodes the real run never reaches. Two defects flowed from that one behaviour. First, if any post-`waitFor` node threw during analysis (the ordinary read-your-own-write fallback shape), the footprint was marked under-approximated — and an under-approximated footprint is incompatible with *everything*, so the blocked transaction could not park quietly: it was woken by every commit in the system and woke every other parked transaction each time it resubmitted, deterministic system-wide churn for as long as it stayed blocked. Second, `delay`/`fromF` thunks positioned after the erratum ran once per attempt — in the analysis pass only — where the documented model says both passes or none. The walker now **stops at the first terminal erratum**, carrying the accumulated footprint out as complete (it is: the run terminates at the same node, and the commit-time coverage gate refines when the passes diverge). A retry-origin stop is re-raised past `handleErrorWith` containment during analysis, mirroring the runtime's retry-is-not-absorbable rule; an error-origin stop keeps the documented recovery-may-resume swallow. The park path additionally refines an under-approximated footprint from the actual log instead of parking on it, closing the storm in the remaining direction (predicate true at analysis, false at run). A parked transaction now parks on exactly its pre-`waitFor` read set — the predicate's dependency set. **The deliberate trade**: a woken transaction whose continuation writes pays one refinement lap before publishing (wakes fire from pre-publish submission sweeps, so no analysis timed before the woken run can see the satisfied predicate); `ErratumStopSpec` pins the lap count in both directions, and the soaks carry the cost within their existing ceilings. The stop also removes a silent Scala 3 hazard for a top-level `abort` followed by a value-binding continuation, which used to throw a `ClassCastException` *inside the analysis pass* and flag the footprint; the same shape inside a `handleErrorWith` can still flag (the error-origin stop is deliberately swallowed there), but the park-path refinement now keeps that bounded — one runs-alone lap — rather than permanent.
- Cancelled commits leaking and resurrecting: cancelling the `F` returned by `commit` (a `timeout`, a lost `race`, supervisor shutdown) interrupted only the caller's wait — the transaction itself ran on a detached fiber the cancellation never reached. A parked `waitFor` transaction survived its caller in the retry map indefinitely; a later commit that conflicted with its read set **woke it, re-ran it, and published its writes** into a completion signal nobody held — side effects at unbounded distance from a cancellation that had long since "succeeded" — and every cancelled blocked commit leaked its retry-map entry, wake closure, and bookkeeping. `commit` now installs an `onCancel` finalizer spanning submission and the wait: cancellation **abandons** the transaction — a shared-across-incarnations flag plus a sweep that removes any parked entry (under the retry semaphore) and demotes-and-deregisters a `Scheduled` registration (under the graph semaphore), draining its dependency cascade so queued peers proceed. The flag is re-checked *inside* every semaphore region that could re-enter the transaction — park, resubmission, wake-time fresh incarnations, and the admission gate — closing the race where an in-flight wake closure registers after abandonment completes. The atomic commit window remains uncancelable: a window already executing runs to completion (its writes may publish); cancellation prevents every future window, promptly, without waiting on the in-flight one. The scaladoc on `commit` and a README section state the contract. Pinned by `CancellationSpec` (resurrection, racing cancellation-vs-wake, dependent release, prompt cancel-while-running, timeout composition — three fail against the old runtime) and `AbandonProtocolSpec` (white-box bookkeeping and idempotency). The `execute` pipeline also gained an `onCancel` completing scheduler deregistration, closing the latent wedge where a cancelled execute fiber stranded its dependents forever.
Expand Down Expand Up @@ -206,7 +208,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Semantic blocking via `waitFor` / retry mechanism
- `handleErrorWith` for transaction-level error recovery

[Unreleased]: https://github.com/Entrolution/bengal-stm/compare/v0.13.0...HEAD
[Unreleased]: https://github.com/Entrolution/bengal-stm/compare/v0.15.0...HEAD
[0.15.0]: https://github.com/Entrolution/bengal-stm/compare/v0.14.0...v0.15.0
[0.14.0]: https://github.com/Entrolution/bengal-stm/compare/v0.13.0...v0.14.0
[0.13.0]: https://github.com/Entrolution/bengal-stm/compare/v0.12.0...v0.13.0
[0.12.0]: https://github.com/Entrolution/bengal-stm/compare/v0.11.0...v0.12.0
Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ Please include the following information in your report:

| Version | Supported |
| ------- | ------------------ |
| 0.14.x | Yes |
| < 0.14 | No |
| 0.15.x | Yes |
| < 0.15 | No |

## Security Updates

Expand Down
Loading