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]
