backpressure
backpressure
¶
Backpressure — adaptive load management.
Monitors system resource pressure (memory, rate limits) and throttles
sheet dispatch to prevent overload. Implements the BackpressureChecker
protocol defined in scheduler.py so the GlobalSheetScheduler can
consult backpressure before dispatching each sheet.
Also exposes should_accept_job() for the JobManager to reject
new submissions when the system is critically stressed.
Lock ordering (daemon-wide): 1. GlobalSheetScheduler._lock 2. RateLimitCoordinator._lock 3. BackpressureController (no internal lock — reads are atomic) 4. CentralLearningStore._lock (future — Stage 5)
Classes¶
PressureLevel
¶
Bases: Enum
Graduated pressure levels for adaptive load management.
BackpressureController
¶
Manages system load through adaptive backpressure.
Assesses memory usage (as a fraction of the configured limit) and
active rate limits to determine a PressureLevel. The scheduler
calls can_start_sheet() before dispatching each sheet and gets
back a (allowed, delay) tuple.
No internal lock is needed because:
- ResourceMonitor methods are thread/coroutine-safe.
- RateLimitCoordinator.active_limits is a property that
reads a dict snapshot.
- PressureLevel assessment is a pure function of those reads.
Source code in src/marianne/daemon/backpressure.py
Functions¶
current_level
¶
Assess current pressure level from resource metrics.
Thresholds (memory as % of ResourceLimitConfig.max_memory_mb):
- probe failure or monitor degraded → CRITICAL (fail-closed)
- >95% or monitor not accepting work → CRITICAL
- >85% or any active rate limit → HIGH
- >70% → MEDIUM
- >50% → LOW
- otherwise → NONE
Note: is_accepting_work() also checks child process count
against ResourceLimitConfig.max_processes. When process
count exceeds 80% of the configured limit, is_accepting_work()
returns False, which triggers the CRITICAL path here. This
means high process counts indirectly escalate backpressure to
CRITICAL even when memory usage is low.
TOCTOU fix (P007): memory is read once and reused for all
threshold checks. is_accepting_work() is still called for
its process-count check, but the memory percentage used in
threshold comparisons comes from the single snapshot above.
Source code in src/marianne/daemon/backpressure.py
can_start_sheet
async
¶
Whether the scheduler may dispatch a sheet, and any delay.
Satisfies the BackpressureChecker protocol used by
GlobalSheetScheduler.next_sheet().
Returns:
| Type | Description |
|---|---|
bool
|
|
float
|
is rejected ( |
tuple[bool, float]
|
delay is returned to slow dispatch. |
Source code in src/marianne/daemon/backpressure.py
should_accept_job
¶
Whether to accept new job submissions.
Returns False only under high resource pressure (memory
or process count). Rate limits do NOT cause job rejection —
they are per-instrument and handled at the sheet dispatch level
by the baton and scheduler (F-149).
This prevents a rate limit on instrument A from blocking jobs that target instrument B.
Source code in src/marianne/daemon/backpressure.py
rejection_reason
¶
Why would a job be rejected right now?
Returns:
| Type | Description |
|---|---|
str | None
|
|
str | None
|
|
Rate limits alone no longer cause rejection (F-149). They are per-instrument concerns handled at the sheet dispatch level. This prevents a rate limit on one instrument from blocking jobs targeting different instruments.
Source code in src/marianne/daemon/backpressure.py
estimate_job_resource_needs
async
¶
Query learned resource patterns for similar job types.
Looks up RESOURCE_CORRELATION patterns from the learning store
that match the given job config hash. Returns a ResourceEstimate
if sufficient historical data exists, otherwise None.
This is advisory — the caller uses it to adjust thresholds, not to block jobs outright.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
job_config_hash
|
str
|
Stable hash identifying the job type/config. |
required |
Returns:
| Type | Description |
|---|---|
ResourceEstimate | None
|
|
ResourceEstimate | None
|
and confidence, or |
Source code in src/marianne/daemon/backpressure.py
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | |