flyingImer opened a new pull request, #4061:
URL: https://github.com/apache/polaris/pull/4061

   This PR introduces `AsyncContextPropagator`, a pluggable SPI for propagating 
request-scoped context across async task boundaries in `TaskExecutorImpl`. 
Fixes #3444
   
   ### Problem
   
   When `TaskExecutorImpl` schedules async work, the task runs on a different 
thread with a fresh CDI request scope. Request-scoped context (realm, 
principal, request ID) was previously propagated via ad-hoc hardcoded logic — 
and request IDs were not propagated at all, since the only way to read them was 
through RESTEasy's internal `CurrentRequestManager` API, which is unavailable 
on task threads. 
   
   ### Solution
   
   **`AsyncContextPropagator` SPI** — two-method interface: `capture()` 
snapshots context on the request thread, `restore()` re-establishes it on the 
task thread and returns an `AutoCloseable` for cleanup (e.g. MDC restoration). 
Each propagator is responsible only for its own lifecycle — capture its own 
piece of context, restore it, and clean up after itself. The propagator does 
not need to know about other propagators, about TaskExecutorImpl's retry logic, 
or about CDI
   scope activation. `TaskExecutorImpl` discovers all implementations via CDI 
`Instance` injection — adding new context propagation requires only a new 
`@ApplicationScoped` bean, no existing code changes.
   
   Three implementations replace the hardcoded logic in `TaskExecutorImpl`:
   - `RealmContextPropagator` — propagates the full `RealmContext` object (not 
just the identifier string), preserving vendor-specific routing information.
   - `PrincipalContextPropagator` — clones the principal into an immutable 
snapshot.
   - `RequestIdPropagator` — propagates the request ID to both 
`RequestIdHolder` and SLF4J MDC, with LIFO MDC cleanup.
   
   **`RequestIdHolder`** — new `@RequestScoped` CDI bean replacing the removed 
`ServiceProducers.requestIdSupplier()` that depended on RESTEasy internals. 
Produces `RequestIdSupplier` via CDI so any component can inject it without 
depending on JAX-RS types.
   
   `CurrentRequestManager` is no longer referenced anywhere in the codebase.
   
   ### Out of scope (follow-up candidates)
   
   - **X-Request-ID header validation** — client-supplied header is used 
verbatim (no length limit, no character allowlist). Pre-existing behavior in 
`RequestIdFilter`, not introduced by this PR.
   - **Propagator ordering** — CDI `Instance` iteration order is unspecified. 
Current propagators are independent so ordering doesn't matter. A `@Priority` 
mechanism may be needed if future propagators have ordering dependencies.
   
   ## Checklist
   - [x] 🛡️ Don't disclose security issues! (contact [email protected])
   - [x] 🔗 Clearly explained why the changes are needed, or linked related 
issues: Fixes #3444
   - [x] 🧪 Added/updated tests with good coverage, or manually tested (and 
explained how)
     - Unit tests for all three propagators (capture, restore, cleanup 
lifecycle)
     - Unit tests for `PolarisEventMetadataFactory` request ID resolution
     - `TaskExecutorImplTest` updated for new constructor signature
     - 19,363 tests pass (2 pre-existing OTLP exporter failures unrelated to 
this change)
   - [x] 💡 Added comments for complex logic
   - [x] 🧾 Updated `CHANGELOG.md` (if needed)
   - [ ] 📚 Updated documentation in `site/content/in-dev/unreleased` (if needed)
   
   ## Disclaimer
   Javadoc is mainly assisted by coding agent.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to