Skip to content

fix: keep route descriptors when routing feedback can't rebuild them - #1497

Merged
ndorin merged 1 commit into
releasefrom
fix/1496-feedback-keeps-route-descriptors
Oct 1, 2026
Merged

ndorin merged 1 commit into
releasefrom
fix/1496-feedback-keeps-route-descriptors

Conversation

@ndorin

@ndorin ndorin commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Fixes #1496. This is a regression in rc.10.

Problem

RoutingFeedbackManager.UpdateDestinationImmediate removed every route descriptor for a destination's input port before re-deriving them from routing feedback. Both re-add paths were conditional, and both were skipped when the walk couldn't resolve a source or resolved to no source. ReleaseRouteInternal depends on those descriptors to know what to switch off, so clearing the destination afterwards found nothing to release, and the route stayed up.

Only port-keyed destinations were affected. The removal matched on the input port key, so descriptors for destinations routed without a destinationPortKey (auto, null InputPort) never matched. #1494 made the removal take every descriptor rather than one, which made the damage larger.

This leaves sinks that don't report CurrentInputPort (e.g. MockVC) with no working configuration. Without a port key their feedback can't resolve, and with one their teardown breaks.

Fix

  • RouteDescriptorCollection.ReplaceRouteDescriptor(replacement) (new) replaces the descriptor recorded for one destination, input port and signal type, and only when a replacement exists. If the existing descriptor already names the same source, nothing changes: that's the descriptor that was executed, and it holds the output ports' in-use registrations.
  • RoutingFeedbackManager no longer removes anything up front. A rebuilt route goes through ReplaceRouteDescriptor. A walk with no source still sets the destination's current source to none, but leaves the descriptors for the release.

This follows the issue's first suggestion: derive the replacement first, and replace only when one exists.

Tests

  • RouteDescriptorCollectionTests: ReplaceRouteDescriptor swaps only the matching port and signal, keeps the executed descriptor when the source is unchanged, ignores null, and a release still finds both descriptors after a feedback pass that offers no replacement.
  • RoutingFeedbackManagerTests (new): drives UpdateDestinationImmediate with a sink that never reports CurrentInputPort and a matrix that reports nothing routed. Both descriptors survive. Against the rc.10 code this fails with the issue's symptom (an empty collection).

All 59 tests pass, 8 out of 8 runs. This hasn't been run on a processor.

Note for anyone extending these tests: the feedback-manager tests deliberately avoid the paths that reach Extensions.GetRouteToSource. Its static constructor creates a GenericQueue, which subscribes to the real Crestron SDK's CrestronEnvironment.ProgramStatusEventHandler, and off a processor that call intermittently spins forever and hangs the test host.

Not in this PR

  • In the reporter's system, the walk through the NVX virtual matrix resolves no source about 600 ms after the route executes, so feedback briefly reports "none" while the route is up. That's probably in how the NVX plugin reports CurrentRoutes, and is worth a separate look.
  • MockVC.CurrentInputPort is never assigned, which is why MockVC destinations need destinationPortKey at all.

🤖 Generated with Claude Code

RoutingFeedbackManager removed every route descriptor for a destination's
input port before re-deriving them from routing feedback, and didn't put
them back when the walk found no source. ReleaseRouteInternal depends on
those descriptors to know what to switch off, so clearing a port-keyed
destination found nothing to release and left the route up. Destinations
routed with no port key ('auto') escaped because the removal matched on
the port key.

- Add RouteDescriptorCollection.ReplaceRouteDescriptor: replaces the
  descriptor for one destination, input port and signal type, only when
  there is a replacement, and keeps the executed descriptor when the
  source is unchanged
- RoutingFeedbackManager no longer removes descriptors up front; a
  rebuilt route goes through ReplaceRouteDescriptor, and a walk with no
  source only updates the current source

Fixes #1496

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ndorin
ndorin merged commit 5d5c4c1 into release Oct 1, 2026
3 checks passed
@ndorin
ndorin deleted the fix/1496-feedback-keeps-route-descriptors branch October 1, 2026 19:07
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