Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SagaPersister has issues with SagaId when using global GuidSerializer #613

Open
rvriens opened this issue Mar 26, 2024 · 1 comment
Open
Labels
bug Something isn't working Triaged

Comments

@rvriens
Copy link

rvriens commented Mar 26, 2024

Describe the bug

Description

Combination of Guid Serializer as string with Saga does not work with Timeouts.

async Task<TSagaData> GetSagaData<TSagaData>(string elementName, object elementValue, SynchronizedStorageSession session)

Expected behavior

Start an Saga on receive.

Set timeout:
await RequestTimeout(context, TimeSpan.FromSeconds(30));

When timeout message is received the Saga is found (by SagaId) and can be resolved.

Using the global guid serializer should not change de behavior of the saga.

Actual behavior

Normal behavior without the guid serializer: SagaId/_id is saved in mongo as Binary like Binary.createFromBase64('peWT50SIxUOJcrDZAJixTg==', 3)

When using global guidserializer as string this is converted to string like "eaa845b0-da1b-4fb2-b263-b0d90098b0a7"

In this case the document is not found. BsonValue.Create does not use the registered serializers.
var document = await storageSession.Find<TSagaData>(new BsonDocument(elementName, BsonValue.Create(elementValue))).ConfigureAwait(false);

When receiving timeout we get the exception: "No saga found for timeout message {0}, ignoring since the saga has been marked as complete before the timeout fired"

Versions

NServicebus.Core 7.8.4.0
NServicebus.Storage.MongoDB 2.3.2.0
MongoDB.Driver 2.23.1.0

Steps to reproduce

Register global guid serializer.
BsonSerializer.RegisterSerializationProvider(new GuidSerializerProvider());

  public class GuidSerializerProvider : IBsonSerializationProvider
  {
      public IBsonSerializer GetSerializer(Type type)
      {
          if (type == typeof(Guid))
              return new GuidSerializer(BsonType.String);
          return null!;
      } 
}

Create Saga with DemoData

public class DemoSaga : Saga<DemoData>,
        IAmStartedByMessages<StartCommand>,
        IHandleTimeouts<DemoTimeoutState>
{
public async Task Handle(StartCommandmessage, IMessageHandlerContext context)
{
await RequestTimeout<DemoTimeoutState>(context, TimeSpan.FromSeconds(30));
}
public async Task Handle(DemoTimeoutState, IMessageHandlerContext context)
{
MarkAsComplete();
}
}

The saga will not be resolved and still exists after 30 seconds.

Relevant log output

No response

Additional Information

Workarounds

As work around do not use the RegisterSerializationProvider for guids.

Possible solutions

Replace:
https://github.com/Particular/NServiceBus.Storage.MongoDB/blob/04be6e3ef8a0565a3dcb1283198e41aab4c36ac1/src/NServiceBus.Storage.MongoDB/Sagas/SagaPersister.cs#L71C13-L72C1
var document = await storageSession.Find<TSagaData>(new BsonDocument(elementName, BsonValue.Create(elementValue))).ConfigureAwait(false);

With:

var bsonSerializer = BsonSerializer.LookupSerializer(elementValue.GetType());
var document = await storageSession.Find<TSagaData>(new BsonDocument(elementName, serializer.ToBsonValue(elementValue)).ConfigureAwait(false);

Or convert the Saga::Id to string.

Additional information

@helenktsai helenktsai added the bug Something isn't working label Apr 8, 2024
@helenktsai
Copy link
Member

Hi @rvriens,

Thanks for bringing this to our attention. We will add it to the backlog and fix it in a future release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Triaged
Projects
None yet
Development

No branches or pull requests

2 participants