[OpAMP] Refactor OpAMP communication pipe - #4930
Conversation
Pull request dashboard statusWaiting on reviewers · refreshed 2026-08-14 16:20 UTC Review the latest changes. Status above doesn't look right?
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4930 +/- ##
==========================================
+ Coverage 77.56% 77.70% +0.13%
==========================================
Files 468 469 +1
Lines 19913 19885 -28
==========================================
+ Hits 15445 15451 +6
+ Misses 4468 4434 -34
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
…metry-dotnet-contrib into opamp-com-reworks
…metry-dotnet-contrib into opamp-com-reworks
stevejgordon
left a comment
There was a problem hiding this comment.
The overall direction looks reasonable and the pipe model is the right approach to satisfy the HTTP transport spec requirement.
A few initial code comments to consider. I will do another pass soon.
| this.TryFlush(); | ||
| } | ||
|
|
||
| public Task FlushAsync() |
There was a problem hiding this comment.
Should this accept a CancellationToken passed through from StopAsync?
There was a problem hiding this comment.
Correct, we discovered this as well in the internal overhaul to prevent hangs in the pipe. Using cancellation token here gives the control to user.
| { | ||
| lock (this.frameLock) | ||
| { | ||
| this.isBusy = false; |
There was a problem hiding this comment.
This is correct for the "happy path", but what if the the web socket connection is closed or dropped? I think we'd need a mechanism for WsReciever to notify through when that happens so isBusy can be reset?
There was a problem hiding this comment.
Correct, retry / reconnect paths are missing currently intentionally. Seems a larger scope to focus on separately.
| public async Task StopAsync(CancellationToken token = default) | ||
| { | ||
| // Drain queued data. | ||
| await this.FlushAsync() |
There was a problem hiding this comment.
Pass the CancellationToken here?
| this.AppendMessage(MessageBuilderHelper.AppendAgentDisconnect); | ||
|
|
||
| // Send disconnect. | ||
| await this.FlushAsync() |
| IFrameBuilder AddCustomMessage(string capability, string type, ReadOnlyMemory<byte> data); | ||
|
|
||
| AgentToServer Build(); | ||
| IFrameBuilder Clear(); |
There was a problem hiding this comment.
Does this belong on this interface? It's beyond the concern of this abstraction. It seems to only be used from a test and could still existing on the FrameBuilder directly for that call site.
There was a problem hiding this comment.
Seems it became a leftover, removed.
| .ConfigureAwait(false); | ||
| } | ||
|
|
||
| this.AppendMessage(MessageBuilderHelper.AppendIdentification); |
There was a problem hiding this comment.
Should we flush here to ensure identification is sent before heartbeats (and other services) are started? Otherwise, a lost identification message will cause heartbeats to be sent to a server it had never seen.
There was a problem hiding this comment.
TryFlush should send it instantly since the pipe is initially free. I added Flush just in case, so nothing weird should not happen.
| internal sealed class FrameProcessor | ||
| { | ||
| private readonly ConcurrentDictionary<Type, IReadOnlyList<object>> listeners = []; | ||
| private readonly ConcurrentBag<Action<ServerToAgent>> internalListeners = []; |
There was a problem hiding this comment.
Does this need to be ConcurrentBag? One one internal listener is accepted in the ctor, can we just store that?
There was a problem hiding this comment.
The only issue today is that the pipe does not have a control over the processor (it does not construct it). Pipe itself is a user, like any internal services could be.
What
Design discussion issue open-telemetry/opamp-spec#366
This is about ensuring that communication is according to spec.
Since spec is currently not clear that messages can be accepted in sync or async manner. This PR is a basis to support both options via configuration. If it's decided that the client must block the pipe until a full response is constructed, a follow up is needed.
Changes
Breaking changes ❗
Notes
❗ This PR is a preview and a discussion object how to proceed to support corner cases in the spec.Since there seems to be a consensus with this PR, we can move forward
Merge requirement checklist
CHANGELOG.mdfiles updated for non-trivial changes < TODO until the final form is decided