Use ISagaFinder with IAmStartedByMessages in NServiceBus 8

I have also asked this question on StackOverflow.

My code worked fine before NSB 8. My problem is that IAmStartedByMessages demands that I implement ConfigureHowToFindSaga. If I do that NSB will break with an error when it discover the ISagaFinder implementation.

I have a TradeSagaFinder class with all my ISagaFinder’s. Here is a snippet:

public class TradeSagaFinder :
        ISagaFinder<InTradeData, StartPendingTradeSaga>,
        ISagaFinder<InTradeData, ApproveCertificateTrade>,
        ISagaFinder<InTradeData, PriceAccepted>,
        ISagaFinder<OutTradeData, StartSendTradeSaga>,
        ISagaFinder<OutTradeData, StatusFromMarketMaker>,
        ISagaFinder<OutTradeData, AuditTrailIdReceived>
    {
        public async Task<InTradeData> FindBy(StartPendingTradeSaga message, ISynchronizedStorageSession storageSession, IReadOnlyContextBag context, CancellationToken cancellationToken = default)
        {
            var session = storageSession.Session();
            var sagaData = await session.Query<InTradeData>().FirstOrDefaultAsync(x => x.TradeId == message.TradeId.Id && x.TradeType == message.TradeId.TradeType, cancellationToken);
            return sagaData;
        }

        public async Task<InTradeData> FindBy(ApproveCertificateTrade message, ISynchronizedStorageSession storageSession, IReadOnlyContextBag context, CancellationToken cancellationToken = default)
        {
            var session = storageSession.Session();
            var sagaData = await session.Query<InTradeData>().FirstOrDefaultAsync(x => x.TradeId == message.CertificateTradeRequestId && x.TradeType == message.TradeType, cancellationToken);
            return sagaData;
        }

The code can’t compile without the MapSaga in ConfigureHowToFindSaga

public class IncomingTradeSaga : Saga<InTradeData>,
    IAmStartedByMessages<StartPendingTradeSaga>,
    IHandleTimeouts<StartPendingTradeSaga>,
    IHandleMessages<ApproveCertificateTrade>,
    IHandleTimeouts<ApproveCertificateTrade>,
    IHandleMessages<PriceAccepted>
{
    private readonly IApproveRequestService _approveMessageService;
    private readonly IConfigurationService _configurationService;
    private readonly IMarketMakerWebService _marketMakerWebService;

    protected override void ConfigureHowToFindSaga(SagaPropertyMapper<InTradeData> mapper)
    {
        mapper.MapSaga(saga => saga.TradeId)
            .ToMessage<StartPendingTradeSaga>(msg => msg.TradeId.Id);
    }

I am really stocked on this one. Hope somebody can help me.

That sounds like a bug in our analyzer, what is the exact compile error you are getting?

As a workaround you should be able to disable it, see NServiceBus Analyzer • NServiceBus • Particular Docs

Let me know if that works for you!

Cheers,

Andreas

This is the error I am getting at startup

System.Exception: A custom ISagaFinder and an existing mapping where found for message 'TradingService.InternalMessages.StartPendingTradeSaga'. Either remove the message mapping or remove the finder. Finder name 'DomainModel.NServiceBusMessageHandlers.TradeSaga.TradeSagaFinder'.
   at NServiceBus.Sagas.SagaMetadata.ApplyScannedFinders(SagaMapper mapper, Type sagaEntityType, IEnumerable`1 availableTypes, Conventions conventions) in /_/src/NServiceBus.Core/Sagas/SagaMetadata.cs:line 257
   at NServiceBus.Sagas.SagaMetadata.Create(Type sagaType, IEnumerable`1 availableTypes, Conventions conventions) in /_/src/NServiceBus.Core/Sagas/SagaMetadata.cs:line 176
   at NServiceBus.Sagas.SagaMetadataCollection.<>c__DisplayClass3_0.<Initialize>b__0(Type t) in /_/src/NServiceBus.Core/Sagas/SagaMetadataCollection.cs:line 48
   at System.Linq.Enumerable.WhereSelectListIterator`2.ToList()
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at NServiceBus.Sagas.SagaMetadataCollection.Initialize(IEnumerable`1 availableTypes, Conventions conventions) in /_/src/NServiceBus.Core/Sagas/SagaMetadataCollection.cs:line 47
   at NServiceBus.Features.Sagas.Setup(FeatureConfigurationContext context) in /_/src/NServiceBus.Core/Sagas/Sagas.cs:line 52
   at NServiceBus.Features.Feature.SetupFeature(FeatureConfigurationContext config) in /_/src/NServiceBus.Core/Features/Feature.cs:line 204
   at NServiceBus.Features.FeatureActivator.FeatureInfo.InitializeFrom(FeatureConfigurationContext featureConfigurationContext) in /_/src/NServiceBus.Core/Features/FeatureActivator.cs:line 240
   at NServiceBus.Features.FeatureActivator.ActivateFeature(FeatureInfo featureInfo, List`1 featuresToActivate, FeatureConfigurationContext featureConfigurationContext) in /_/src/NServiceBus.Core/Features/FeatureActivator.cs:line 203
   at NServiceBus.Features.FeatureActivator.SetupFeatures(FeatureConfigurationContext featureConfigurationContext) in /_/src/NServiceBus.Core/Features/FeatureActivator.cs:line 54
   at NServiceBus.FeatureComponent.Initalize(FeatureConfigurationContext featureConfigurationContext) in /_/src/NServiceBus.Core/Features/FeatureComponent.cs:line 29
   at NServiceBus.EndpointCreator.Configure() in /_/src/NServiceBus.Core/EndpointCreator.cs:line 61
   at NServiceBus.EndpointCreator.Create(SettingsHolder settings, Configuration hostingConfiguration) in /_/src/NServiceBus.Core/EndpointCreator.cs:line 26
   at NServiceBus.HostCreator.CreateWithExternallyManagedContainer(EndpointConfiguration endpointConfiguration, IServiceCollection serviceCollection) in /_/src/NServiceBus.Core/Hosting/HostCreator.cs:line 30
   at NServiceBus.EndpointWithExternallyManagedContainer.Create(EndpointConfiguration configuration, IServiceCollection serviceCollection) in /_/src/NServiceBus.Core/EndpointWithExternallyManagedContainer.cs:line 18
   at NServiceBus.HostBuilderExtensions.<>c__DisplayClass0_0.<UseNServiceBus>b__0(HostBuilderContext ctx, IServiceCollection serviceCollection) in /_/src/NServiceBus.Extensions.Hosting/HostBuilderExtensions.cs:line 34
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at TradingService.Host.HostMain.Main(String[] args) in C:\Projects\TradingService\Code\TradingService\TradingService.Host\HostMain.cs:line 32
   at TradingService.Host.HostMain.<Main>(String[] args)

Could you provide a work-around?
The link you provide can’t help me, because I can only disable warnings about missing Awaits

Try to:

  1. Remove the call to mapper.MapSaga(saga => saga.TradeId).ToMessage<StartPendingTradeSaga>(msg => msg.TradeId.Id); but keep the empty ConfigureHowToFindSaga method
  2. Disable the warning with:
public class IncomingTradeSaga : Saga<InTradeData>,
#pragma warning disable NSB0006 // Message that starts the saga does not have a message mapping
    IAmStartedByMessages<StartPendingTradeSaga>,
#pragma warning restore NSB0006 // Message that starts the saga does not have a message mapping
    IHandleTimeouts<StartPendingTradeSaga>,
    IHandleMessages<ApproveCertificateTrade>,
    IHandleTimeouts<ApproveCertificateTrade>,
    IHandleMessages<PriceAccepted>

Let me know if that works

Cheers,

Andreas

Tried your suggestion. But getting the following error

  OutgoingTradeSaga.cs(13, 14): [CS0534] 'OutgoingTradeSaga' does not implement inherited abstract member 'Saga<OutTradeData>.ConfigureHowToFindSaga(SagaPropertyMapper<OutTradeData>)'

Did you leave the empty ConfigureHowToFindSaga method as I mentioned in #1?(that should remove that error)

No I deleted the method.

Works now, but need some testing.

Thanks

1 Like