Skip to content

Run a pipeline under a rasuvaeff/context budget; release 0.3.0 - #12

Merged
rasuvaeff merged 2 commits into
masterfrom
feat/context
Oct 15, 2026
Merged

rasuvaeff merged 2 commits into
masterfrom
feat/context

Conversation

@rasuvaeff

Copy link
Copy Markdown
Owner

Fixes #11

Summary

CompiledPipeline::call(callable $callback, ?callable $fallback = null, ?Context $context = null):

Layer Under a context
Start assertActive() — a terminated context runs nothing
Retry withContext() per call (Retry is immutable — the compiled pipeline stays reusable)
Bulkhead a ContextAwareBulkhead (bulkhead 1.4.0) waits ≤ budget, ends with the context's exception
Callback receives the context only when one is given — internal-function callbacks keep working
fallback skipped only when this context is cancelled; expiry and everything without a context still reach it (the catch-all contract is unchanged)
  • Circuit breaker: the pipeline cannot change the user's isFailure. A context terminated before the call never reaches the breaker; one terminating mid-call does. New ContextOutcome::ignoring(callable $isFailure) returns false for any ContextException (which extends RuntimeException, so broad classifiers count it). The pipeline never turns a context exception into a success — a half-open probe out of the caller's budget would close the circuit.
  • Rejection::is() stays false for context exceptions; onRejected never maps them.
  • Requires rasuvaeff/bulkhead ^1.4, rasuvaeff/context ^0.3; infection/infection → ^0.35 (lazy rule).
  • README (EN + RU), llms.txt, AGENTS.md invariants; CHANGELOG 0.3.0 — 2026-10-15.
  • CI: experimental PHP 8.6 job.

Verification

composer build, rector green; release-check: no BC break vs v0.2.1; mutation MSI 100% (gate 96). Tests: callback argument only with a context, terminated context runs nothing, fallback for cancelled-this / expired / no-context / inner-context cancellation, retry stopped by the budget (3 attempts in 250 ms with 100 ms backoff), bulkhead wait capped (120 ms slept, Rejection::is false, onRejected not applied), plain Bulkhead stub still works, no breaker outcome for a terminated context in either order, ContextOutcome.

CompiledPipeline::call() takes an optional context: checked before anything
starts, retry runs withContext(), a ContextAwareBulkhead caps its slot wait
by the budget, and the callback receives the context only when one is given
(an extra argument would break internal-function callbacks). The fallback is
skipped only when this call's context is cancelled.

ContextOutcome::ignoring() wraps a breaker classifier so a context exception
is never a failure: the pipeline cannot change the breaker's isFailure, and a
context exception must never become a success (a half-open probe out of the
caller's budget would close the circuit).

Requires bulkhead ^1.4 and context ^0.3; infection ^0.35; CI gains the
experimental PHP 8.6 job.

Fixes #11
@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f51c5916-aa8e-47f6-99fa-de5decb5a328
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

prefer-lowest installed retry 1.3, which has no Retry::withContext(); 1.6.2
is the first retry that both has it and installs next to context 0.3.
@rasuvaeff
rasuvaeff merged commit 754fa06 into master Oct 15, 2026
11 checks passed
@rasuvaeff
rasuvaeff deleted the feat/context branch October 15, 2026 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Run a pipeline under a rasuvaeff/context budget: call(..., context:)

1 participant