Ошибка Masstransit при настройке саги с внедрением зависимостей - PullRequest
0 голосов
/ 23 января 2019

У меня есть сага, которую я пытаюсь запустить с помощью masstransit, для которой требуется клиент refit, и я хочу, чтобы зависимость от клиента была введена в сагу.

Я использую MassTransit 5.2.3 с MassTransit.Extensions.DependencyInjection 5.2.3 для настройки следующим образом:

...
var serviceCollection = new ServiceCollection();
serviceCollection.AddRefitClient<IClient>(...).ConfigureHttpClient(...);
serviceCollection.AddMassTransit(c =>
{
    c.AddSaga<MySaga>();
});    
serviceCollection.AddScoped<MySaga>();
serviceCollection.AddSingleton<ISagaRepository<MySaga>, MessageSessionSagaRepository<MySaga>>(x => new MessageSessionSagaRepository<MySaga>());

var serviceProvider = serviceCollection.BuildServiceProvider();
var bus = Bus.Factory.CreateUsingAzureServiceBus(cfg =>
{
    var host = ...;
    ...
    cfg.ReceiveEndpoint(host, "MyQueue", e =>
    {   
        ... 
        e.Saga<MySaga>(serviceProvider);
    });
});

bus.Start();
...

код саги:

class MySaga :
    ISaga,
    InitiatedBy<IStep1>,
    Orchestrates<IStep2>
{
    private readonly IClient _client;

    public Guid CorrelationId { get; set; }

    public MySaga(IClient client)
    {
        _client = client;
    }

    public async Task Consume(ConsumeContext<IStep1> context) {...}
    public async Task Consume(ConsumeContext<IStep2> context) {...}
}

Это приводит к исключению «Не удалось создать соединитель саги для MyNamespace.MySaga», с внутренним исключением «ConfigurationException: у саги MyNamespace.MySaga должен быть либо конструктор по умолчанию, и свойство CorrelationId с возможностью записи или конструктор с одним аргументом Guid. назначить CorrelationId "

1 Ответ

0 голосов
/ 23 января 2019

Фокус MassTransit для саг был перенесен в саги о конечных автоматах, поэтому в целом автоматные саги предпочтительнее.Для «классических» саг вам дается требование в сообщении об ошибке.Вы можете использовать код из Injection_Specs.cs

var refitClient = ...;

var serviceCollection = new ServiceCollection();
serviceCollection.AddMassTransit(c =>
{
    c.AddSaga<MySaga>();
});    
serviceCollection.AddScoped<MySaga>();
serviceCollection.AddSingleton<ISagaRepository<MySaga>, MessageSessionSagaRepository<MySaga>>(x => new MessageSessionSagaRepository<MySaga>());

var serviceProvider = serviceCollection.BuildServiceProvider();
var bus = Bus.Factory.CreateUsingAzureServiceBus(cfg =>
{
    var host = ...;
    ...
    cfg.ReceiveEndpoint(host, "MyQueue", e =>
    {   
        ... 
        e.Saga<MySaga>(serviceProvider, 
            x => x.UseExecute(ctx => ctx.Saga.Client = refitClient));
    });
});

bus.Start();

Конечно, вам понадобится публичное свойство Client в классе саги, и вы не будете использоватьконструктор инъекций.Вам также понадобятся те два конструктора, о которых сообщается в сообщении об ошибке:

class MySaga :
    ISaga,
    InitiatedBy<IStep1>,
    Orchestrates<IStep2>
{
    public IClient Client { get; set; }

    public Guid CorrelationId { get; set; }

    public MySaga()
    {
    }

    public MySaga(Guid correlationId)
    {
        CorrelationId = correlationId;
    }

    public async Task Consume(ConsumeContext<IStep1> context) {...}
    public async Task Consume(ConsumeContext<IStep2> context) {...}
}

Рассмотрение проекта

Одна вещь, которую я должен добавить, заключается в том, что Sagaв MassTransit близок к шаблону диспетчера процессов.Это означает, что саги не должны иметь никакой логики, кроме логики оркестровки, и не должны делать ничего другого, кроме обработки сообщений.Поэтому я не буду рекомендовать использовать такие вещи, как REST API-клиенты внутри саг.Если сага должна получить какие-то данные, чтобы принять решение о маршрутизации сообщений, она должна использовать сообщения для получения этих данных.

...