Skip to content

Conversation

@carcer
Copy link
Contributor

@carcer carcer commented Jan 19, 2026

  • Fixes UseDurableOutboxOnAllSendingEndpoints() and UseDurableInboxOnAllListeners() throwing InvalidOperationException when SignalR transport is configured
  • Public API Additions:
    • Adds SupportsMode(EndpointMode mode) method to Endpoint class
    • Adds Endpoint property to ISubscriberConfiguration interface
  • Adds unit tests for SignalR transport mode support

Notes

I realize this might need a major version bump, so I want to confirm we are not blocked, we adjusted so we don't need to call them. Not precious if the current behavior is fine, I can close and raise a docs adjustment PR instead.

Public API Additions

1. Endpoint.SupportsMode(EndpointMode mode) method

/// <summary>
/// Check if this endpoint supports the specified mode
/// </summary>
public bool SupportsMode(EndpointMode mode)

This exposes the existing protected supportsMode() method, allowing users and policies to check endpoint mode compatibility before attempting to set a mode. This is useful for building custom policies that need to gracefully handle transports with limited mode support.

2. ISubscriberConfiguration.Endpoint property

public Endpoint Endpoint { get; }

Exposes the underlying Endpoint on the subscriber configuration interface, enabling policies to access endpoint properties (like SupportsMode()) when configuring senders via AllSenders().

Problem

When UseDurableOutboxOnAllSendingEndpoints() or UseDurableInboxOnAllListeners() is called and SignalR transport is configured, the application throws an InvalidOperationException because SignalR doesn't support durable mode.

Solution

Modified the two durability policy methods to check if the endpoint supports durable mode before attempting to set it. Endpoints that don't support durable mode are silently skipped.

Changes

Endpoint.cs

  • Added public SupportsMode(EndpointMode mode) method that exposes the protected supportsMode() for policy checks

ISubscriberConfiguration.cs

  • Added Endpoint property to the interface to expose the underlying endpoint for policy checks

WolverineOptions.Policies.cs

  • Modified UseDurableInboxOnAllListeners() to check SupportsMode(EndpointMode.Durable) before calling UseDurableInbox()
  • Modified UseDurableOutboxOnAllSendingEndpoints() to check SupportsMode(EndpointMode.Durable) before calling UseDurableOutbox()

SignalRTransportModeTests.cs (new)

  • Tests verifying SignalR doesn't support durable mode
  • Tests verifying SignalR supports inline and buffered modes
  • Test verifying explicit durable mode setting throws an exception

Test plan

  • New SignalR transport mode tests pass
  • Existing configuration tests pass
  • Manual verification with mixed transport configuration (SignalR + durable transport)

Design Rationale

  • Targeted fix: Only the "apply to all" methods are modified. Explicit calls to UseDurableInbox() or UseDurableOutbox() on a SignalR endpoint will still throw an exception (correct behavior - users should know unsupported functionality was requested)
  • Backward compatible: Existing behavior for all other endpoints is unchanged
  • Simple implementation: Uses existing AllListeners/AllSenders infrastructure with an added mode check

Feedback Requested

Silent skipping behavior

This PR silently skips endpoints that don't support durable mode. This affects:

Transport Durable Support Behavior
SignalR Never Always skipped
NATS (without JetStream) Conditional Skipped when UseJetStream is false
All other transports Yes Applied normally

Question: Should we log a warning when endpoints are skipped? For example:

void IPolicies.UseDurableInboxOnAllListeners()
{
    this.As<IPolicies>().AllListeners(x =>
    {
        if (x.Endpoint.SupportsMode(EndpointMode.Durable))
        {
            x.UseDurableInbox();
        }
        else
        {
            // Option: Log warning
            // logger.LogWarning("Endpoint {Uri} does not support durable mode, skipping", x.Endpoint.Uri);
        }
    });
}

Considerations:

  • Pro (silent): Less noise for expected scenarios (e.g., SignalR is inherently non-durable)
  • Pro (warning): Helps users discover misconfiguration (e.g., NATS without JetStream expecting durability)
  • Alternative: Add an optional bool warnOnSkip = false parameter to the policy methods

@jeremydmiller jeremydmiller merged commit f22f98f into JasperFx:main Jan 19, 2026
1 check passed
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