Skip to content

chore(core): obsolete GenericInboundMessage protocol leftovers - #792

Closed
tylerkron wants to merge 1 commit into
mainfrom
cursor/obsolete-inbound-routing-8379
Closed

tylerkron wants to merge 1 commit into
mainfrom
cursor/obsolete-inbound-routing-8379

Conversation

@tylerkron

Copy link
Copy Markdown
Contributor

Summary

Production routing is DaqifiDevice → ProtobufProtocolHandler.Handle(DaqifiOutMessage), the path added so streaming frames are not wrapped in GenericInboundMessage<object> (issue #490). The library never calls the older inbound-routing surface. This marks it obsolete and leaves the types in place for a later major.

Obsolete, with a message pointing at ProtobufProtocolHandler.Handle(DaqifiOutMessage):

  • GenericInboundMessage<T>
  • IProtocolHandler.CanHandle / HandleAsync
  • ProtobufProtocolHandler.CanHandle / HandleAsync

Handle(DaqifiOutMessage) is unchanged. IUdpTransport, UdpTransport, CompositeMessageParser, WiFi/PostUsbTransparentModeExitDelay, StopMessagePumps, ContinuousDeviceFinder, and SafeLog are untouched.

Public API

Non-breaking. Nothing is removed, so PublicAPI.Shipped.txt / PublicAPI.Unshipped.txt stay as they are.

Microsoft.CodeAnalysis.PublicApiAnalyzers does not record [Obsolete] (same as the IntelHexParser forwarders: the shipped entries stay, and RS0016/RS0017 stay quiet). Deleting an entry here would be the breaking-change signal, which this PR does not want. A reflection test covers the attribute and the replacement message, because the API files cannot.

Tests

ProtobufProtocolHandler tests that only wrapped a DaqifiOutMessage in GenericInboundMessage<object> to call CanHandle / HandleAsync now call Handle(DaqifiOutMessage). Facts that existed only for the obsolete surface (CanHandle true/false, HandleAsync ignoring a non-protobuf payload, the Handle-vs-HandleAsync parity check) are gone.

Open in Web Open in Cursor 

Mark the unused #490 inbound-routing surface obsolete and point callers at
ProtobufProtocolHandler.Handle(DaqifiOutMessage). The types stay until a
future major.

Co-authored-by: Tyler Kron <tylerkron@gmail.com>
@tylerkron
tylerkron requested a review from a team as a code owner September 25, 2026 10:37
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Deprecate legacy generic inbound protocol routing

✨ Enhancement 🧪 Tests 🕐 10-20 Minutes

Grey Divider

AI Description

• Marks legacy generic inbound routing APIs obsolete without removing public surface.
• Directs consumers to synchronous typed protobuf routing for allocation-free streaming.
• Migrates routing tests and verifies deprecation guidance through reflection.
Diagram

graph TD
  D["DaqifiDevice"] --> M["DaqifiOutMessage"] --> H["Typed Handle"] --> C{"Message Type"} --> R["Route Handler"]
  L["Legacy APIs"] -. "obsolete guidance" .-> H
Loading
High-Level Assessment

The staged deprecation is the appropriate approach: it guides consumers to the allocation-free typed API while preserving binary and source compatibility until a future major release. Immediate removal would be breaking, while leaving the old surface unmarked would prolong use of an inactive routing abstraction.

Files changed (4) +71 / -84

Tests (1) +55 / -80
ProtobufProtocolHandlerTests.csTest typed routing and obsolete API guidance +55/-80

Test typed routing and obsolete API guidance

• Migrates handler tests from GenericInboundMessage and HandleAsync to the typed synchronous Handle method. Removes tests specific to the obsolete wrapper path, strengthens direct routing assertions, and adds reflection coverage for ObsoleteAttribute messages.

src/Daqifi.Core.Tests/Device/Protocol/ProtobufProtocolHandlerTests.cs

Other (3) +16 / -4
GenericInboundMessage.csDeprecate the generic inbound message wrapper +5/-0

Deprecate the generic inbound message wrapper

• Marks GenericInboundMessage<T> obsolete and directs consumers to ProtobufProtocolHandler.Handle(DaqifiOutMessage). Documentation explains that production device routing no longer allocates this wrapper per frame.

src/Daqifi.Core/Communication/Messages/GenericInboundMessage.cs

IProtocolHandler.csDeprecate legacy protocol interface methods +2/-0

Deprecate legacy protocol interface methods

• Marks CanHandle and HandleAsync obsolete on IProtocolHandler while retaining both members for compatibility. Each warning identifies the typed synchronous replacement and future-major removal plan.

src/Daqifi.Core/Device/Protocol/IProtocolHandler.cs

ProtobufProtocolHandler.csGuide callers from wrapper routing to typed Handle +9/-4

Guide callers from wrapper routing to typed Handle

• Marks the concrete CanHandle and HandleAsync implementations obsolete and documents HandleAsync as a compatibility wrapper around Handle. Clarifies that DaqifiDevice already uses the synchronous typed entry point directly.

src/Daqifi.Core/Device/Protocol/ProtobufProtocolHandler.cs

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 🔗 Cross-repo conflicts (1) 📜 Skill insights (0)

Grey Divider


Action required

1. Avalonia tests stop compiling 🔗 Cross-repo conflict ≡ Correctness
Description
Marking GenericInboundMessage<T> obsolete emits CS0618 where daqifi-avalonia's
NonFiniteStreamedReadingTests still constructs that type. The test project treats every warning as
an error, so upgrading it to this Core release causes dotnet test to fail during compilation.
Code

src/Daqifi.Core/Communication/Messages/GenericInboundMessage.cs[12]

+[Obsolete($"Use {nameof(Daqifi.Core.Device.Protocol.ProtobufProtocolHandler)}.{nameof(Daqifi.Core.Device.Protocol.ProtobufProtocolHandler.Handle)}({nameof(DaqifiOutMessage)}) instead. This type will be removed in a future major version.")]
Relevance

●●● Strong

Downstream TreatWarningsAsErrors failures are concrete compatibility regressions; similar
warning-induced build failures were accepted.

PR-#423

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR adds ObsoleteAttribute directly to GenericInboundMessage<T>. Avalonia constructs that
exact type in a test project configured with TreatWarningsAsErrors, proving the resulting obsolete
warning becomes a compilation failure after the package upgrade.

daqifi-core -> daqifi-avalonia
src/Daqifi.Core/Communication/Messages/GenericInboundMessage.cs[7-13]
External repo: daqifi/daqifi-avalonia, Daqifi.Avalonia.Tests/Device/NonFiniteStreamedReadingTests.cs [102-112]
External repo: daqifi/daqifi-avalonia, Daqifi.Avalonia.Tests/Daqifi.Avalonia.Tests.csproj [23-32]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new `Obsolete` attribute on `GenericInboundMessage<T>` produces CS0618 in daqifi-avalonia, whose test project treats warnings as errors. Avoid publishing this deprecation until the consumer no longer constructs the wrapper, or coordinate the consumer migration with this release.

## Fix Focus Areas
- src/Daqifi.Core/Communication/Messages/GenericInboundMessage.cs[7-13]
- Daqifi.Avalonia.Tests/Device/NonFiniteStreamedReadingTests.cs[102-112]
- Daqifi.Avalonia.Tests/Daqifi.Avalonia.Tests.csproj[23-32]

## Recommended Fix
First update daqifi-avalonia's test seam to route the `DaqifiOutMessage` through the typed handler without constructing `GenericInboundMessage<object>`, then publish this obsolete annotation. If coordinated consumer changes cannot land first, defer the annotation rather than requiring a warning suppression for an API the consumer still needs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Non-protobuf callers cannot migrate 🐞 Bug ⚙ Maintainability
Description
The new ObsoleteAttribute messages on GenericInboundMessage<T> and IProtocolHandler name
ProtobufProtocolHandler.Handle(DaqifiOutMessage) as their replacement even though those public
contracts accept arbitrary payloads and implementations. Consumers using a non-protobuf payload or
custom protocol handler therefore receive migration guidance to a method that cannot accept their
data or preserve their abstraction.
Code

src/Daqifi.Core/Communication/Messages/GenericInboundMessage.cs[12]

+[Obsolete($"Use {nameof(Daqifi.Core.Device.Protocol.ProtobufProtocolHandler)}.{nameof(Daqifi.Core.Device.Protocol.ProtobufProtocolHandler.Handle)}({nameof(DaqifiOutMessage)}) instead. This type will be removed in a future major version.")]
Relevance

●● Moderate

Generic migration guidance is semantically mismatched, but no close precedent confirms rejecting
this intentional protobuf-focused deprecation.

PR-#508

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The deprecated class is documented and implemented as a wrapper for arbitrary T, while the
deprecated interface operates on generic inbound messages; the recommended concrete method accepts
only DaqifiOutMessage. The newly added test enforces that same protobuf-only recommendation across
all five APIs, preventing the guidance from being tailored to the generic contracts.

src/Daqifi.Core/Communication/Messages/GenericInboundMessage.cs[4-24]
src/Daqifi.Core/Communication/Messages/IInboundMessage.cs[7-12]
src/Daqifi.Core/Device/Protocol/IProtocolHandler.cs[6-25]
src/Daqifi.Core/Device/Protocol/ProtobufProtocolHandler.cs[76-84]
src/Daqifi.Core.Tests/Device/Protocol/ProtobufProtocolHandlerTests.cs[211-234]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The generic inbound-message type and protocol-handler interface direct every consumer to a protobuf-specific method, although their contracts also support non-protobuf payloads and implementations.

## Fix Focus Areas
- src/Daqifi.Core/Communication/Messages/GenericInboundMessage.cs[7-13]
- src/Daqifi.Core/Device/Protocol/IProtocolHandler.cs[13-25]
- src/Daqifi.Core.Tests/Device/Protocol/ProtobufProtocolHandlerTests.cs[206-235]

## Recommended Fix
Give the generic type and interface members migration messages applicable to their full contracts, such as removal-only guidance when no general replacement exists. Keep the typed `Handle` recommendation on the protobuf-specific implementation methods, and update the reflection test to verify the appropriate message for each API rather than requiring the protobuf replacement for all of them.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 13 rules
✅ Cross-repo context — repo relationships
  Explored: repo: daqifi/daqifi-avalonia (sha: 574f117d) — View relationship
  Explored: repo: daqifi/daqifi-desktop (sha: 36995fed) — View relationship
  Explored: repo: daqifi/daqifi-core-example-app (sha: f04ae237) — View relationship
  Explored: repo: daqifi/calibration (sha: 4b09bde0) — View relationship
Review mode: ⚖️ Balanced: This changes multiple public runtime APIs by adding obsolescence attributes and rewrites protocol-handler tests, so a careful review is warranted despite the localized scope.

Grey Divider

Tip of the day
💡 Did you know, you can enable the Remediation agent and Qodo fixes findings in a dedicated fix PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

/// wrap frames in this type (issue #490).
/// </remarks>
/// <typeparam name="T">The type of the data payload.</typeparam>
[Obsolete($"Use {nameof(Daqifi.Core.Device.Protocol.ProtobufProtocolHandler)}.{nameof(Daqifi.Core.Device.Protocol.ProtobufProtocolHandler.Handle)}({nameof(DaqifiOutMessage)}) instead. This type will be removed in a future major version.")]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

2. Non-protobuf callers cannot migrate 🐞 Bug ⚙ Maintainability

The new ObsoleteAttribute messages on GenericInboundMessage<T> and IProtocolHandler name
ProtobufProtocolHandler.Handle(DaqifiOutMessage) as their replacement even though those public
contracts accept arbitrary payloads and implementations. Consumers using a non-protobuf payload or
custom protocol handler therefore receive migration guidance to a method that cannot accept their
data or preserve their abstraction.
Agent Prompt
## Issue description
The generic inbound-message type and protocol-handler interface direct every consumer to a protobuf-specific method, although their contracts also support non-protobuf payloads and implementations.

## Fix Focus Areas
- src/Daqifi.Core/Communication/Messages/GenericInboundMessage.cs[7-13]
- src/Daqifi.Core/Device/Protocol/IProtocolHandler.cs[13-25]
- src/Daqifi.Core.Tests/Device/Protocol/ProtobufProtocolHandlerTests.cs[206-235]

## Recommended Fix
Give the generic type and interface members migration messages applicable to their full contracts, such as removal-only guidance when no general replacement exists. Keep the typed `Handle` recommendation on the protobuf-specific implementation methods, and update the reflection test to verify the appropriate message for each API rather than requiring the protobuf replacement for all of them.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

/// wrap frames in this type (issue #490).
/// </remarks>
/// <typeparam name="T">The type of the data payload.</typeparam>
[Obsolete($"Use {nameof(Daqifi.Core.Device.Protocol.ProtobufProtocolHandler)}.{nameof(Daqifi.Core.Device.Protocol.ProtobufProtocolHandler.Handle)}({nameof(DaqifiOutMessage)}) instead. This type will be removed in a future major version.")]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Avalonia tests stop compiling 🔗 Cross-repo conflict ≡ Correctness

Marking GenericInboundMessage<T> obsolete emits CS0618 where daqifi-avalonia's
NonFiniteStreamedReadingTests still constructs that type. The test project treats every warning as
an error, so upgrading it to this Core release causes dotnet test to fail during compilation.
Agent Prompt
## Issue description
The new `Obsolete` attribute on `GenericInboundMessage<T>` produces CS0618 in daqifi-avalonia, whose test project treats warnings as errors. Avoid publishing this deprecation until the consumer no longer constructs the wrapper, or coordinate the consumer migration with this release.

## Fix Focus Areas
- src/Daqifi.Core/Communication/Messages/GenericInboundMessage.cs[7-13]
- Daqifi.Avalonia.Tests/Device/NonFiniteStreamedReadingTests.cs[102-112]
- Daqifi.Avalonia.Tests/Daqifi.Avalonia.Tests.csproj[23-32]

## Recommended Fix
First update daqifi-avalonia's test seam to route the `DaqifiOutMessage` through the typed handler without constructing `GenericInboundMessage<object>`, then publish this obsolete annotation. If coordinated consumer changes cannot land first, defer the annotation rather than requiring a warning suppression for an API the consumer still needs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@tylerkron

Copy link
Copy Markdown
Contributor Author

Closing — not worth merging right now.

Deprecating public API is a release-planning call, and this one has downstream fallout with little upside:

  • It breaks a consumer's build. daqifi-avalonia's NonFiniteStreamedReadingTests still constructs GenericInboundMessage<T>, and that project treats warnings as errors, so taking this Core release turns CS0618 into a compile failure (Qodo's high-severity finding).
  • The migration advice doesn't fit the contract. GenericInboundMessage<T>/IProtocolHandler accept arbitrary payloads and custom handlers; pointing everyone at ProtobufProtocolHandler.Handle(DaqifiOutMessage) gives a non-protobuf consumer a replacement that can't take their data.
  • The library already doesn't route through these types (perf(streaming): steady-state decode allocates per frame what it could cache — channel snapshot+sort, double buffer copy, unconditional wrappers #490), so the [Obsolete] only adds warnings for consumers; it doesn't fix anything.

If you want these gone, it's better to plan the removal for the next major alongside the Avalonia migration.

🤖 Generated with Claude Code

@tylerkron tylerkron closed this Sep 27, 2026
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.

2 participants