Skip to content

Commit b42e7bb

Browse files
committed
Release v0.2.3
1 parent 7c781d2 commit b42e7bb

4 files changed

Lines changed: 168 additions & 32 deletions

File tree

CHANGELOG.md

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Changelog
22

3-
All notable, user-visible changes to runtime behavior and public APIs
4-
are documented in this file.
3+
All notable, user-visible changes to runtime behavior and public APIs are documented in this file.
54

6-
Until version `1.0.0`, all releases are **pre-stable** and may introduce
7-
breaking changes. Any such changes will be explicitly documented.
5+
This changelog documents only **user-visible changes** to runtime behavior, public APIs, and operational guarantees; internal refactors and implementation details are omitted unless they affect those guarantees.
6+
7+
Until version `1.0.0`, all releases are **pre-stable** and may introduce breaking changes. Any such changes will be explicitly documented.
88

99
---
1010

@@ -24,14 +24,24 @@ breaking changes. Any such changes will be explicitly documented.
2424

2525
## Publication note
2626

27-
Some early 0.1.x versions were affected by cancelled or incomplete Maven Central publication attempts.
28-
Because Maven Central does not allow reuse of version numbers once a deployment is cancelled or rejected,
27+
Some early 0.1.x versions were affected by cancelled or incomplete Maven Central publication attempts. Because Maven Central does not allow reuse of version numbers once a deployment is cancelled or rejected,
2928
those versions should be considered **non-canonical**.
3029

3130
The first fully published and supported release series begins with 0.1.7.
3231

3332
---
3433

34+
## [0.2.3] - 2026-01-05
35+
### Documentation
36+
- Rewrote README.md to align strictly with DESIGN.md semantics.
37+
- Clarified the core invariant: in-flight means admitted until terminal.
38+
- Explicitly documented fail-fast, unordered admission and terminal-based capacity release.
39+
- Added a concise comparison section explaining differences from framework-based and reactive bulkheads.
40+
- Tightened wording around cancellation, rejection, and capacity lifetime.
41+
- No runtime, API, or behavioral changes.
42+
43+
---
44+
3545
## [0.2.2] - 2026-01-05
3646

3747
### Fixed
@@ -54,12 +64,9 @@ The first fully published and supported release series begins with 0.1.7.
5464

5565
### Changed
5666
- Defined **cancellation** of the returned `CompletionStage` as a **terminal outcome** that releases capacity.
57-
- Defined **permit lifetime** strictly from successful admission until the returned `CompletionStage` reaches a
58-
terminal state (success, exceptional completion, or cancellation).
59-
- Guaranteed **exactly-once permit release** across all races between completion, exceptional completion, and
60-
cancellation.
61-
- Tightened admission semantics: capacity is acquired **only at the moment of submission**; there is no deferred,
62-
waiting, or speculative admission.
67+
- Defined **permit lifetime** strictly from successful admission until the returned `CompletionStage` reaches a terminal state (success, exceptional completion, or cancellation).
68+
- Guaranteed **exactly-once permit release** across all races between completion, exceptional completion, and cancellation.
69+
- Tightened admission semantics: capacity is acquired **only at the moment of submission**; there is no deferred, waiting, or speculative admission.
6370

6471
### Clarified
6572
- Formalized the core invariant: *in-flight means admitted until terminal*.
@@ -68,8 +75,7 @@ The first fully published and supported release series begins with 0.1.7.
6875
- Clarified that `BulkheadRejectedException` indicates **capacity exhausted and no work started**.
6976

7077
### Documentation
71-
- Significantly expanded and refined **DESIGN.md** to explicitly define semantics, invariants, races, cancellation
72-
behavior, and non-goals.
78+
- Significantly expanded and refined **DESIGN.md** to explicitly define semantics, invariants, races, cancellation behavior, and non-goals.
7379
- Pruned and refocused **README.md** to serve as a high-level entry point aligned with v0.2 semantics.
7480
- Added explicit **production guidance and failure modes** documentation.
7581

@@ -105,10 +111,8 @@ The first fully published and supported release series begins with 0.1.7.
105111
- **Yanked / not published** (Maven Central deploy was cancelled; version cannot be reused).
106112

107113
### Fixed
108-
- Release workflow: corrected `GPG_PRIVATE_KEY` environment scoping so the key imports correctly in CI and signatures
109-
(`.asc`) are produced.
110-
- Release signing: ensured `.asc` signature artifacts are generated as part of the release build (via the `release`
111-
profile).
114+
- Release workflow: corrected `GPG_PRIVATE_KEY` environment scoping so the key imports correctly in CI and signatures (`.asc`) are produced.
115+
- Release signing: ensured `.asc` signature artifacts are generated as part of the release build (via the `release` profile).
112116

113117
### Build
114118
- Minor CI/release reliability improvements around non-interactive GPG usage.
@@ -132,9 +136,7 @@ The first fully published and supported release series begins with 0.1.7.
132136
## [0.1.3] – 2025-12-30
133137

134138
### Fixed
135-
- Corrected Maven Central publishing configuration (release deployment no longer depends on
136-
`distributionManagement`;
137-
no API or semantic changes).
139+
- Corrected Maven Central publishing configuration (release deployment no longer depends on `distributionManagement`; no API or semantic changes).
138140

139141
### Build
140142
- Added a tag-gated release workflow suitable for CI publishing.

README.md

Lines changed: 143 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,29 @@
22

33
⚠️ **Early-stage, design-first project (pre-1.0)**
44

5-
This repository provides a small, opinionated **async bulkhead** for Java with
6-
explicit, test-backed semantics around overload behavior.
5+
This repository provides a small, opinionated **async bulkhead** for Java with explicit, test-backed semantics around overload behavior.
76

87
The goal is to make overload **bounded, visible, and predictable**.
98

109
---
1110

1211
## Why another bulkhead?
1312

14-
Most Java bulkhead implementations are part of **larger resilience frameworks** and make
15-
reasonable tradeoffs at that scale, but undesirable ones when you want a **single,
16-
well-defined primitive**.
13+
Most Java bulkhead implementations are part of **larger resilience frameworks** and make reasonable tradeoffs at that scale, but undesirable ones when you want a **single, well-defined primitive**.
1714

1815
This project exists because many existing bulkheads:
1916
- mix **admission control** with execution concerns (thread pools, schedulers)
2017
- introduce **queues**, **timeouts**, or **retries** that hide overload instead of surfacing it
2118
- provide unclear semantics around when capacity is consumed and released
2219
- couple behavior to specific frameworks or reactive abstractions
2320

24-
This bulkhead is intentionally different.
25-
2621
It focuses on **one thing only**:
2722
- bounding the number of **in-flight async operations**
2823
- **failing fast** when saturated
2924
- never starting work it cannot admit
3025
- making rejection an **explicit, composable signal**
3126

3227
There is no queue.
33-
There is no waiting.
3428
There is no internal execution model.
3529

3630
---
@@ -39,7 +33,7 @@ There is no internal execution model.
3933

4034
- Admission is **fail-fast** and **non-blocking**
4135
- Admission is **unordered** (no FIFO, no fairness guarantees)
42-
- A operation is considered *in-flight* from successful admission until its
36+
- An operation is considered *in-flight* from successful admission until its
4337
returned `CompletionStage` reaches a **terminal state**
4438
(success, failure, or cancellation)
4539
- Capacity is released **only** at terminal completion
@@ -68,6 +62,146 @@ Out of scope for v0.x:
6862

6963
---
7064

65+
## Comparison with other bulkheads
66+
67+
This bulkhead is intentionally **narrower and more explicit** than most existing Java bulkhead implementations.
68+
69+
Its behavior follows a single design invariant defined in **DESIGN.md**:
70+
71+
> In-flight means admitted until terminal.
72+
73+
All other semantics derive from this invariant.
74+
75+
---
76+
77+
### High-level comparison
78+
79+
Dimension | This bulkhead | Resilience4j bulkhead | Hystrix (legacy) | Reactive bulkheads (e.g. Project Reactor)
80+
-----------------------|--------------------------|-----------------------|---------------------|------------------------------------------
81+
Primary concern | Admission control | Execution isolation | Execution isolation | Stream backpressure
82+
Queuing | None | Optional | Internal | Implicit
83+
Waiting for capacity | Never | Sometimes | Often | Framework-defined
84+
Async-first | Yes | Mixed | Mostly sync | Yes
85+
In-flight definition | Explicit, terminal-based | Implicit | Thread-based | Subscription-based
86+
Cancellation semantics | Terminal & defined | Often implicit | Weak / unclear | Framework-specific
87+
Ordering/fairness | None | Limited | Limited | Often ordered
88+
Scope | Single primitive | Resilience suite | Full framework | Reactive pipelines
89+
90+
---
91+
92+
### Core design differences
93+
94+
#### Admission control, not execution control
95+
96+
Most bulkheads control **how work executes**:
97+
* thread pools
98+
* schedulers
99+
* executor queues
100+
101+
This bulkhead controls **whether work may start**.
102+
103+
It does **not**:
104+
* execute tasks
105+
* manage threads
106+
* delay, buffer, or retry submissions
107+
108+
Admission is atomic and has exactly two outcomes:
109+
* **admitted** (permit acquired, supplier invoked)
110+
* **rejected** (no permit, supplier not invoked)
111+
112+
There is no intermediate state.
113+
114+
---
115+
116+
#### Fail fast, never wait
117+
118+
This bulkhead **never waits for capacity**.
119+
120+
If capacity is unavailable at submission time:
121+
* the operation is rejected immediately
122+
* no work is started
123+
* rejection is surfaced synchronously as a failed `CompletionStage`
124+
125+
There is:
126+
* no queue
127+
* no reservation
128+
* no deferred admission
129+
130+
This is a deliberate design choice to make overload **explicit and visible**.
131+
132+
---
133+
134+
#### Explicit in-flight semantics
135+
136+
This bulkhead defines *in-flight* precisely:
137+
> An operation is **in-flight** from successful admission until the returned `CompletionStage` reaches a **terminal state**.
138+
139+
Terminal states are strictly defined as:
140+
* successful completion
141+
* exceptional completion
142+
* cancellation
143+
144+
Capacity is released **only** when one of these states is observed.
145+
146+
This definition is documented, test-backed, and invariant under concurrency races.
147+
148+
---
149+
150+
#### Cancellation is a first-class terminal outcome
151+
152+
If the returned `CompletionStage` is cancelled:
153+
* capacity is released exactly once
154+
* no retries or restarts occur
155+
* admission semantics remain unchanged
156+
157+
The bulkhead does **not** propagate cancellation downstream; it only observes it to maintain correct admission accounting.
158+
159+
---
160+
161+
#### Unordered, opportunistic admission
162+
163+
Admission is **not ordered**.
164+
165+
The bulkhead does not guarantee:
166+
* FIFO behavior
167+
* fairness
168+
* eventual admission after rejection
169+
170+
Concurrent submissions race for available capacity.
171+
Rejection under contention is expected and correct behavior.
172+
173+
---
174+
175+
#### Small by design, composable by intent
176+
177+
This library is **not** a resilience framework.
178+
179+
It intentionally excludes:
180+
* queues or blocking admission
181+
* retries or fallbacks
182+
* circuit breakers
183+
* adaptive or auto-tuned limits
184+
* reactive framework integrations
185+
186+
Those concerns are meant to be composed *around* this primitive.
187+
188+
---
189+
190+
### When this bulkhead fits
191+
* You want **explicit, bounded admission control**
192+
* You need to reason clearly about **what is actually in-flight**
193+
* You want overload to be **visible, not hidden**
194+
* You already own execution, retries, and timeouts
195+
196+
197+
### When it does not
198+
* You need queuing or load smoothing
199+
* You want framework-managed execution
200+
* You require fairness or ordering
201+
* You want a full resilience toolkit
202+
203+
---
204+
71205
## Design & production guidance
72206

73207
This README intentionally stays high level.

bulkhead-core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<parent>
1111
<groupId>io.github.janbalangue</groupId>
1212
<artifactId>async-bulkhead</artifactId>
13-
<version>0.2.2</version>
13+
<version>0.2.3</version>
1414
</parent>
1515

1616

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
<groupId>io.github.janbalangue</groupId>
1111
<artifactId>async-bulkhead</artifactId>
12-
<version>0.2.2</version>
12+
<version>0.2.3</version>
1313
<packaging>pom</packaging>
1414

1515
<name>Async Bulkhead</name>

0 commit comments

Comments
 (0)