feat: support concurrent runtime contexts - #2190
Open
binaryfire wants to merge 4 commits into
Open
Conversation
Allow hosts to provide execution-local runtime context storage during SDK initialization while keeping the existing process-local behavior as the default. Replace the fixed process key and two lookup maps with a direct nullable context for the normal path. Concurrent hosts delegate selection and release through one small storage contract, and withContext performs only one storage lookup when entering an execution. Expose RuntimeContext only as the opaque value required by the public interface; its constructor and members remain internal. Preserve native Hub cloning, independent best-effort resource flushing, and the shared client transport contract.
Add a runtime-neutral storage stub with independently selectable execution slots so the isolation contract can be tested without an async extension. Cover distinct contexts, Hubs, scopes, log and metric aggregators, switching between overlapping executions, abandoned execution release, repeated teardown, and failure-isolated resource settlement. Also verify that the global init helper forwards the configured storage to the SDK.
Avoid reallocating the process-wide fatal error memory reservation whenever a new runtime context starts. Re-arm the buffer only after the previous reservation has actually been released while continuing to reset the fatal-handler flags on every call. Extend the existing PHPT to cover both released and live reservations, and remove the PHPStan and Mago suppressions made obsolete by reading the reservation state.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit db21a63. Configure here.
Remove any context held for the current execution before replacing the runtime context manager. This prevents reinitialization with the same storage from selecting a context owned by the previous manager and binding the new client to a Hub that will be discarded. Document that initialization discards the current stored context without flushing and that concurrent runtimes must not reinitialize while other executions are active. Add a regression covering the end/start transition that previously left the fresh baseline without a client.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Hi! I’m the co-creator of Hypervel and a contributor to Swoole. I’d like to include a first-party Sentry integration as part of the framework, but the SDK currently makes that difficult to do safely.
Sentry currently keeps one active runtime context for the whole PHP process. That works when requests are handled one at a time. In a server where several requests or tasks can overlap, a second request can reuse the first request’s context. The requests can then share Sentry state, logs, and metrics, and one request can flush or remove data that belongs to another.
This PR lets a runtime provide the storage used for the current request’s context. Sentry still creates the context and handles flushing; the runtime only stores and returns the context for whichever request or task is currently running.
The storage is passed when Sentry is initialized because it controls how work inside the process is kept separate. It isn’t client configuration and shouldn’t change when the client is replaced.
Nothing changes for applications that don’t provide custom storage. Their context stays process-local, and the default implementation becomes simpler: one nullable property replaces the fixed
processkey, two lookup maps, and their cleanup logic.When custom storage is used, the SDK manager doesn’t retain active contexts itself. If a request ends unexpectedly, its runtime can release that context without leaving its Hub, logs, and metrics in memory for the rest of the worker’s lifetime.
I ran into this while working on Hypervel, but the problem isn’t specific to Swoole. The same change can be used by any async PHP runtime, including Amp and ReactPHP.
One thing I wasn’t sure about was the naming for the new public type. The SDK already has
Sentry\Context\RuntimeContextfor information attached to events. This PR exposesSentry\State\RuntimeContextas the value stored for a running request, although its constructor and methods stay internal. I kept the existing name, butExecutionContextmight be clearer.