Skip to content

feat: support concurrent runtime contexts - #2190

Open
binaryfire wants to merge 4 commits into
getsentry:masterfrom
binaryfire:feat/concurrent-runtime-contexts
Open

feat: support concurrent runtime contexts#2190
binaryfire wants to merge 4 commits into
getsentry:masterfrom
binaryfire:feat/concurrent-runtime-contexts

Conversation

@binaryfire

@binaryfire binaryfire commented Aug 29, 2026

Copy link
Copy Markdown

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 process key, 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\RuntimeContext for information attached to events. This PR exposes Sentry\State\RuntimeContext as the value stored for a running request, although its constructor and methods stay internal. I kept the existing name, but ExecutionContext might be clearer.

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.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread src/SentrySdk.php
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.
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.

1 participant