Package org.mockserver.mock.action.http
Class PreemptionSimulator
java.lang.Object
org.mockserver.mock.action.http.PreemptionSimulator
Process-wide state machine for a simulated server preemption (node drain / Spot
reclamation / pre-SIGTERM): when
start(PreemptionRequest) is called the server becomes
cordoned — new data-plane exchanges are turned away (503 + Connection: close on HTTP/1.1,
GOAWAY on HTTP/2, per PreemptionRequest.Mode) while in-flight requests are allowed to drain
for a bounded window. It is a simulation only: it never calls stop() /
stopAsync() and never tears down the event loops. The cordon clears on an explicit
uncordon() or automatically after ttlMillis (a dead-man's switch so a forgotten
simulation self-heals).
The design mirrors ServiceChaosRegistry's singleton + controllable-clock + TTL pattern,
but is server-scoped (a single cordon, no host keying). It holds no Netty references: the in-flight
count is read through an injected IntSupplier (wired from LifeCycle.getRequestsInFlight()),
keeping mockserver-core free of a netty dependency. GOAWAY emission is performed lazily on the netty
side when an HTTP/2 client hits a cordoned connection (see HttpRequestHandler); this class is
the authoritative cordon state.
State is cleared on server reset (see HttpState.reset()).
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionbooleantrueonce the drain window has elapsed while still cordoned (stragglers may remain).longMilliseconds remaining in the drain window (untildrainDeadlineMillis), floored at 0.booleantruewhen the active simulation signals HTTP/2 clients to drain via a GOAWAY frame (modesgoawayandboth).static PreemptionSimulatorgetMode()The active mode, or null when not cordoned.The active preemption request (effective, post-clamp), or null when not cordoned.longThelastStreamIdto advertise on a preemption GOAWAY, or-1when not cordoned or unset (-1tellsHttp2GoAwayEmitterto use the connection's current last stream).intinFlight()The current in-flight data-plane request count, via the wired supplier.booleanWhether the server is currently cordoned.booleantruewhen the active simulation rejects new data-plane exchanges with a 503 (modesreject503andboth).voidreset()Reset all state.voidsetInFlightSupplier(IntSupplier inFlightSupplier) Wire the supplier used to read the current in-flight data-plane request count (fromLifeCycle.getRequestsInFlight()).start(PreemptionRequest req) Begin (or replace) a preemption simulation.state()A human-readable state string for the status endpoint:"inactive"when not cordoned,"draining"while within the drain window, or"drained"once the drain deadline has passed (the server stays cordoned until TTL/uncordon).voiduncordon()Clear the cordon explicitly (idempotent).
-
Constructor Details
-
PreemptionSimulator
-
-
Method Details
-
getInstance
-
setInFlightSupplier
Wire the supplier used to read the current in-flight data-plane request count (fromLifeCycle.getRequestsInFlight()). Null is ignored. -
start
Begin (or replace) a preemption simulation. ThedrainMillisandttlMillisare each clamped topreemptionSimulationMaxDrainMillis. WhendrainMillisis null it defaults tostopDrainMillis(the same drain budget a real graceful shutdown uses). Whenmodeis null it defaults toPreemptionRequest.Mode.both.- Returns:
- the effective request actually applied (with defaults and clamping resolved)
-
isCordoned
public boolean isCordoned()Whether the server is currently cordoned. Auto-uncordons (lazily, here) once the TTL has elapsed, so a forgotten simulation self-heals without an explicit uncordon. -
inFlight
public int inFlight()The current in-flight data-plane request count, via the wired supplier. -
getRequest
The active preemption request (effective, post-clamp), or null when not cordoned. -
getMode
The active mode, or null when not cordoned. -
rejectsNewExchanges
public boolean rejectsNewExchanges()truewhen the active simulation rejects new data-plane exchanges with a 503 (modesreject503andboth). When the mode isgoawayonly, new exchanges are not rejected with a 503 — the HTTP/2 GOAWAY alone signals clients to drain — so this returns false. Returns false when not cordoned. -
emitsGoAway
public boolean emitsGoAway()truewhen the active simulation signals HTTP/2 clients to drain via a GOAWAY frame (modesgoawayandboth). Returns false when not cordoned. Read by the netty runtime to decide whether to emit a lazy GOAWAY on a cordoned HTTP/2 connection. Thread-safe: reads the active request through the same path asisCordoned(). -
goAwayLastStreamId
public long goAwayLastStreamId()ThelastStreamIdto advertise on a preemption GOAWAY, or-1when not cordoned or unset (-1tellsHttp2GoAwayEmitterto use the connection's current last stream). -
drainRemainingMillis
public long drainRemainingMillis()Milliseconds remaining in the drain window (untildrainDeadlineMillis), floored at 0. Returns 0 when not cordoned. This reflects the drain budget, not the TTL. -
drainDeadlinePassed
public boolean drainDeadlinePassed()trueonce the drain window has elapsed while still cordoned (stragglers may remain). -
state
A human-readable state string for the status endpoint:"inactive"when not cordoned,"draining"while within the drain window, or"drained"once the drain deadline has passed (the server stays cordoned until TTL/uncordon). -
uncordon
public void uncordon()Clear the cordon explicitly (idempotent). -
reset
public void reset()Reset all state. Called on server reset and for test isolation. Does not clear the wired supplier.
-