Skip to content

Sync internal, 2026-10-16 - #1052

Merged
drcaramelsyrup merged 24 commits into
mainfrom
bleeper-ewang-a869adb8ccb3b5a7e559a25e21b23fb28a1153f5
Oct 19, 2026
Merged

drcaramelsyrup merged 24 commits into
mainfrom
bleeper-ewang-a869adb8ccb3b5a7e559a25e21b23fb28a1153f5

Conversation

@drcaramelsyrup

Copy link
Copy Markdown
Collaborator

No description provided.

areyia and others added 24 commits September 4, 2026 17:49
Synchronize request completion after processing upstream responses, preventing
completed upgraded sessions from being polled again. Preserve normal HTTP
post-body validation and cover both behaviors with regression tests.
HTTP/1 response parsing rejects spaces before header colons and obsolete line folding by default while retaining backend-defined malformed-line behavior. Callers can opt into legacy syntax or different field counts with ResponseParserConfig; connector, cache-put, and cached-header parsing are configured independently.
Keep reset watching active for custom sessions after an upgraded request
reaches EOF, while preserving completed-body suppression for HTTP/1 and
subrequest sessions.

Expose post-upgrade polling through the session abstraction and leave
idle-result validation to custom session implementations. Add regression
coverage proving a reset terminates the relay without finishing or writing
the request twice.
Expose an indexed-lookup with a callback so callers can validate stored
entries by key without a scan or cloning data.
Every test process that starts the mock origin stops the previous openresty and starts a new one. The old instance keeps its listen ports until it has exited, so the new one could fail to bind while the readiness probe was still answered by the old one, and later requests found no listener. Wait for the old process to exit and start again if the new one exits before listening. The downstream-bail cache test also now bounds the lock wait by the body time instead of a 100 ms window.

Advance the sync cursor past the reconciled revisions whose changes are already represented in this branch. The next source change is tracked by public PR #915.
The async `certificate_callback` only receives `&mut SslRef`, with no
handle to the underlying connection. Applications that select or forge a
leaf per connection sometimes need connection-level context that is only
reachable from the socket fd, which is unavailable at
certificate-selection time.

`handshake_with_callback` already holds the stream when it pauses the
handshake to invoke the callback, so capture the stream's fd and stash it
on the SSL via `ex_data` just before the call. Add `set_downstream_fd` /
`get_downstream_fd` helpers to the ext module of both openssl-derived
backends -- the shared `boringssl_openssl` server path compiles against
either, so both must carry the helper. The fd is stored as the same
platform-conditional type as pingora-core's `UniqueIDType` (`RawFd` on
unix, socket handle on Windows), so the call site passes `io.id()` through
with no cast or truncation. No public trait signatures change; the rustls
and s2n backends are untouched.

Includes-commit: 9371d2b
Replicated-from: #915
…opt-in

 Add an application opt-in for handling downstream disconnects during cache fills. Once enabled, the proxy reports abandonment only while a fill can produce an entry and before the response is complete, stops writing to the abandoned downstream, and lets the fill finish. Applications can release writer demand through the new hook.

Keep default behavior unchanged and retry only after a completely framed request body, while caching remains enabled and no writer is active. Include compatibility coverage and remove the unused HTTP/1 abandonment marker.
 Allow an opted-in application to cancel an abandoned cache fill once no readers remain. Add a cancellation watcher to miss handling, observe it across HTTP/1, HTTP/2, and custom upstream paths, process already accepted tasks, and classify cancellation for cache disablement and lock release.

Keep cancellation disabled unless the application opts in, preserve connected-request handling, and fail readers when MemCache writers are dropped. Install shared test certificates atomically.
 A streaming cache hit can wait on its storage indefinitely without
reading its client, so a client that left kept the hit and its storage
reader until a response write failed.

For a request that opts in through
ProxyHttp::should_handle_downstream_abandonment, a hit now watches its client
while its cached body read waits, until its response is complete: an
HTTP/2 client from the start, since waiting on its stream reads nothing,
and any other client if its request body is complete when the hit
starts. A client that closes or
resets its connection, or resets its HTTP/2 stream, ends the hit and
releases the reader. With abort_on_close disabled, a half-closed client
keeps its response. The pending storage read is kept across client
events, so a read that is not cancel-safe is not lost.

The watch is the regular idle read, read_body_or_idle, so an HTTP/1
next request sent during the hit follows the connection's pipelining
policy, as in the regular proxy loops. With pipelining disabled, it ends
the hit with ConnectError and the connection is closed, where without
the opt-in the hit never reads it and the connection is reused for it.
With pipelining enabled, its first byte is kept for the next session.

The watch stops once the response is complete, as
ServerSession::is_response_complete reports it, so a next request
sent after a complete Content-Length response stays unread even while
the cache reader has yet to return the end of the body, and the
connection is reused for it, as without the opt-in.

The hit never reads the request body. An HTTP/1 or custom client whose
request body is not complete when the hit starts is not watched, as
without the opt-in, since its idle read would take a byte of that body.
An HTTP/2 request whose END_STREAM arrives on a separate empty DATA frame
is watched, since its stream wait reads nothing.

The hit loop offers a hit to suppress_error_log before logging it only
when the watch ended it because its client left, judged by the same
error types as the miss loops: a closed connection, a read error or an
HTTP/2 error. A client that sent its next request early is still
connected, so that ConnectError, like any other failed hit, logs exactly
as without the opt-in. A stale-if-error hit keeps that path's logging.

Without the opt-in the hit loop is unchanged and never reads its client.
 Watch the downstream during subrequest pipe waits after its request body is complete, so client disconnects cancel the pipe. Respect HTTP/1 pipelining and half-close behavior, retain pending storage reads across client events, and stop watching once the response is delivered.

Make cancellation interrupt upstream pacing delays after abandonment while preserving accepted-task processing and the bounded cancellation drain, so a fully received response can still commit. Cover long body pauses, pending cancellation, normal pacing, and complete-response handling.
 Add LRU operations that check an entry and then update, admit, remove or
evict it under one shard lock, plus an atomic two-key mutation, so
callers can validate identity and move weight without racing. Add a
bounded selection of the least-recently-used eligible entry, and count
an eviction only when the selected entry is finally removed.
Co-authored-by: Song Hiếu Trần <songhieu2516@gmail.com>
…ht updates

 Storage that corrects cache weights out of band, for example from a
background size scan, needs a finished write's admission or weight
update to land before it measures that write. Both finish paths now
prepare a MissCompletion, which carries the entry, its freshness, the
eviction manager, the storage and trace handles, and the runtime that
purges evicted entries, before they consume the miss handler, and pass
it to HandleMiss::finish_with_eviction. The default calls finish(), then
completes the accounting with no await in between, so existing storage
is unaffected. Storage that overrides it can move the completion into
the worker that finishes the write and complete it there, so the
accounting has one owner even after the caller's future is dropped.
complete() returns a MissCompleted receipt that nothing else can create,
and a successful finish_with_eviction must return it, so an override
cannot report success without applying its completion. Failed writes
drop the completion and return their error. Wrapping miss handlers
forward the method.

pingora-lru gains set_weight_if_unchanged, which replaces an entry's
weight only while it still equals an expected value, without admitting,
promoting or evicting. Every update to an existing entry's weight now
applies one net delta to the global weight, so weight() never reports a
total that no entry state ever had.
 Atomic counter increments wrap on overflow, but the return-value calculation used ordinary addition and panicked with overflow checks enabled. Use wrapping_add to preserve the documented overflow behavior, and test both overflow directions.
---
style(cache): align block comment for nightly rustfmt

Includes-commit: 0ec7c48
Includes-commit: b50ea59
Replicated-from: #1041
 When an upstream backend returns response headers containing non-UTF-8
bytes (e.g. ISO-8859-1 encoding or binary residue), 'str::from_utf8().unwrap()'
in 'read_response_task' causes a panic.

Replace 'str::from_utf8(...).unwrap()' with 'String::from_utf8_lossy(...)'
so raw response header bytes are logged safely without risking process panics.

Closes #1023
---
style: fix block comment closing for nightly rustfmt

Includes-commit: 13ae58a
Includes-commit: 4047c4d
Replicated-from: #1039
 Unit tests only, no library change: conditional revalidation header,
Vary value in the variance key, inclusive serve-stale window end,
uncacheable responses releasing waiting readers, case-insensitive
request-target scheme, remove_header dropping the case-preserved name,
and repeated headers surviving header-serde round trips.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Includes-commit: 924b472
Replicated-from: #1036
RUSTSEC-2026-0346 and RUSTSEC-2026-0349 flag rustls 0.21.12, which
comes in through hyper-rustls 0.24 on the same legacy aws-sdk-s3 chain
as the rustls-webpki advisories already ignored here. There is no 0.21.x
backport (patched >= 0.23.46), and rustls 0.23 already resolves to
0.23.46.
Signed-off-by: Shane Utt <shaneutt@linux.com>
The action's master branch no longer exists, so the scheduled audit fails before it runs. v2.0.0 keeps the same token input.
pingora-runtime's dial9 feature depends on the metrique crates only to pin versions that Dial9 leaves open, so cargo machete reports them as unused. Add them to its ignore list in the CI checkout before it runs.
@drcaramelsyrup
drcaramelsyrup merged commit 623e163 into main Oct 19, 2026
7 checks passed
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.

10 participants