NServiceBus icon indicating copy to clipboard operation
NServiceBus copied to clipboard

Persistence: Synchronized storage adapter removal

Open danielmarbach opened this issue 3 years ago • 0 comments

The synchronized storage session adapter has been removed and the persistence seam simplified to enable first-class dependency injection support for the storage session. Persisters can simply register the concrete storage session and the rest of the mechanics will be taken care by Core automatically.

Feature Dependencies

  • Make sure the outbox and saga features have a dependency to the storage specific synchronized storage feature
  • Make sure the storage specific synchronized storage feature has a dependency on the core SynchronizedStorage feature

Example from SQL Persistence:

class SqlSagaFeature : Feature
{
    SqlSagaFeature()
    {
        Defaults(s =>
        {
            s.EnableFeatureByDefault<SqlStorageSessionFeature>();
        });
        DependsOn<Sagas>();
        DependsOn<SqlStorageSessionFeature>();
    }
}

class SqlStorageSessionFeature : Feature
{
    public SqlStorageSessionFeature()
    {
        DependsOn<SynchronizedStorage>();
    }
}

ICompletableSynchronizedStorageSession

  • Implement the new methods on the ICompletableSynchronizedStorageSession interface
  • Move the implementations of ISynchronizedStorage.OpenSession into ICompletableSynchronizedStorageSession.OpenSession
  • Move the implementations of ISynchronizedStorageAdapter.TryAdapt into the corresponding TryOpen methods of ICompletableSynchronizedStorageSession

Depending on the needs of the persistence it might make sense to split the completable synchronized storage implementation into two independent session concept. One session concept representing the needs of the core and one session object representing the session state that is shared between the outbox and the completable storage session similar to the spike in CosmosDB.

DI Registration

In the storage session feature make sure to:

  • Register a scoped implementation of ICompletableSynchronizedStorageSession to the concrete storage session
  • Add a scoped implementation that maps the persistence specific synchronized storage session implementation to provider.GetService<ISynchronizedStorageSession>().PersistenceSpecificExtension()

Example from SQL Persistence:

class SqlStorageSessionFeature : Feature
{
    protected override void Setup(FeatureConfigurationContext context)
    {
       services.AddScoped<ICompletableSynchronizedStorageSession>(provider => new StorageSession(connectionManager, provider.GetService<SagaInfoCache>(), sqlDialect));
       services.AddScoped(provider => provider.GetService<ISynchronizedStorageSession>().SqlPersistenceSession());
    }
}

Persistence Tests

Delete on the PersistenceTestConfiguration partial class the no longer required properties:

 public ISynchronizedStorage SynchronizedStorage { get; private set; }

 public ISynchronizedStorageAdapter SynchronizedStorageAdapter { get; private set; }

implement the CreateStorageSession factory delegate to return a new StorageSession object every time it is called. Example:

public Func<ICompletableSynchronizedStorageSession> CreateStorageSession { get; private set; }

CreateStorageSession = () => new StorageSession(connectionManager, infoCache, dialect);

Custom pipeline state holder infrastructure

Delete existing behaviors, associated class and DI registrations that managed storage session context for the incoming pipeline. That part is no longer needed since the scope is now managed by the core.

danielmarbach avatar May 05 '22 06:05 danielmarbach