[ROBO-5857] .NET: IpcContext ambient context - write callback-capable contracts without a Message parameter - #127
Merged
Conversation
eduard-dumitru
force-pushed
the
feature/ipc-context
branch
from
July 1, 2026 12:01
a12533f to
c549985
Compare
eduard-dumitru
force-pushed
the
feature/ipc-context
branch
from
July 29, 2026 12:51
45976a5 to
1314844
Compare
Introduce `IpcContext` with a static `IpcContext? Current` backed by AsyncLocal, published for the duration of a server-side handler (and callback) invocation in `Server.MethodCall`. It exposes the peer (`Client`) + the call's `CancellationToken` and a `GetCallback<T>()` that mirrors `Message.Client.GetCallback<T>()` — so a service-contract implementation can reach callbacks WITHOUT a `Message` parameter, letting the contract-defining assembly stay free of a UiPath.Ipc reference. Additive and non-breaking: `Message` injection is unchanged; `Current` is null outside a call and composes across nested calls (a callback serviced mid-call). Tests (xUnit, self-contained POCO contract with no `Message` param): `Current` is null outside a call and after it completes, set while honoring a call, and a Message-free contract reaches its callback purely via `IpcContext.Current.GetCallback<T>()`. Builds on net461/net6.0/net6.0-windows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
eduard-dumitru
requested review from
bogdanStan92,
danutboanta,
mihainradu and
mihaipetrisor82uip
July 29, 2026 13:17
eduard-dumitru
force-pushed
the
feature/ipc-context
branch
from
July 29, 2026 13:20
1314844 to
d935954
Compare
|
|
||
| /// <summary>Ambient context of the IPC call being honored, letting a POCO contract reach | ||
| /// the peer without a <see cref="Message"/> parameter. Coexists with <see cref="Message"/>.</summary> | ||
| public sealed class IpcContext |
There was a problem hiding this comment.
Where is IpcContext consumed?
Collaborator
Author
There was a problem hiding this comment.
eduard-dumitru
commented
Jul 29, 2026
|
|
||
| // No Message parameter anywhere: the peer is reached through the ambient context. | ||
| public Task<string> ReachCallbackViaContext() | ||
| => IpcContext.Current!.GetCallback<IContextProbeCallback>().Pong(); |
Collaborator
Author
There was a problem hiding this comment.
@mihaipetrisor82uip:
https://github.com/UiPath/coreipc/pull/127/changes#r3675063208
In the Ipc codebase itself, it's only consumed in unit tests.
mihainradu
approved these changes
Jul 29, 2026
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.
Jira: ROBO-5857
What & why
A strongly-typed contract that wants to service callbacks is today forced to reference
UiPath.Ipc, because reaching the peer requires aMessageparameter on the contract method. That leaks the transport into the contract-defining assembly and makes bidirectional contracts non-agnostic.This PR adds an ambient per-operation context,
IpcContext, whose staticIpcContext.Currentis non-null exactly while a call is being honored. A contract implementation reaches the peer viaIpcContext.Current.GetCallback<T>()— noMessageparameter — so the contract-defining assembly can stay free of aUiPath.Ipcreference and a bidirectional contract can be written agnostically.Everything is additive and non-breaking:
Message,CancellationToken, and the wire format are unchanged.Changes
IpcContext(public sealed class) with a staticIpcContext? Currentbacked byAsyncLocal. ExposesClient, the call'sCancellationToken, andGetCallback<T>()(the same machinery behindMessage.Client.GetCallback<T>()).Server.MethodCall, so it covers inbound calls and callbacks, composes across nested calls (a callback serviced mid-call), and is null outside a call.Tests
4 xUnit tests driven by a self-contained POCO contract with no
Messageparameter:Currentis null outside a call and after it completes, set while honoring a call, and aMessage-free contract reaches its callback purely viaIpcContext.Current.GetCallback<T>().Scope
This PR is .NET only. The Python and TypeScript work that previously rode along in this branch has been split out to #148 (ROBO-5858) — Python
IpcContext, plus TypeScriptAbortSignalacceptance and caller/callee cancellation propagation — so each runtime's concerns can be reviewed on their own. The two PRs are independent and can merge in either order.🤖 Generated with Claude Code