Менеджер тайм-аута немедленно перенастраивается

У меня есть очень простая сага планировщика, которая должна отправлять определенное сообщение каждый день. Это реализовано как сага, которая запрашивает тайм-аут. по истечении времени ожидания выполняется действие (отправляется сообщение), и на следующий день запрашивается новое время ожидания.

Раньше я делал то же самое с успехом, но теперь кажется, что тайм-аут срабатывает немедленно, поэтому независимо от того, какой DateTime запрашивается.

Конечная точка является хостингом и настроена для использования InMemoryPersistence. Версия NServiceBus - 6.4.3.

Сага реализована следующим образом. Я удалил всю логику, но сообщения о тайм-ауте по-прежнему поступают немедленно и бесконечно.

public class SchedulerSaga: Saga<SchedulerState>,
    IAmStartedByMessages<StartSchedulerSagaCommand>,
    IHandleTimeouts<SchedulerTimeout>
{
    private readonly IConfigurationProvider _config;

    public SchedulerSaga(IConfigurationProvider config)
    {
        _config = config;
    }

    protected override void ConfigureHowToFindSaga(SagaPropertyMapper<SchedulerState> mapper)
    {
        mapper.ConfigureMapping<StartSchedulerSagaCommand>(_ => _.SchedulerName).ToSaga(_ => _.SchedulerName);
    }

    public async Task Handle(StartSchedulerSagaCommand message, IMessageHandlerContext context)
    {
        Data.SchedulerName = message.SchedulerName;
        await StartProcessAndScheduleNewTimeout(context);
    }

    public async Task Timeout(SchedulerTimeout state, IMessageHandlerContext context)
    {
        Data.Counter++;
        await StartProcessAndScheduleNewTimeout(context);
    }

    private async Task StartProcessAndScheduleNewTimeout(IMessageHandlerContext context)
    {
        await RequestTimeout(context, new DateTime(2018, 9, 16, 0, 0, 0, DateTimeKind.Utc), new SchedulerTimeout { Counter = Data.Counter });
    }
}

Конечная точка настроена следующим образом:

    public static EndpointConfiguration ConfigureMsmqEndpoint(IWindsorContainer container)
    {
        var endpointConfiguration = new EndpointConfiguration(MsmqEndpointName);

        ConfigureRouting(endpointConfiguration);

        endpointConfiguration.UsePersistence<InMemoryPersistence>();

        endpointConfiguration.SendFailedMessagesTo($"{MsmqEndpointName}.error");
        endpointConfiguration.AssemblyScanner().ExcludeAssemblies("tools");
        endpointConfiguration.EnableInstallers();

        ConfigureUnobtrusiveMessageConvention(endpointConfiguration);

        endpointConfiguration.Recoverability().Delayed(DelayedSettings);

        endpointConfiguration.UseContainer<WindsorBuilder>(c => c.ExistingContainer(container));

        return endpointConfiguration;
    }

Я также попытался использовать встроенный механизм планирования, и то же самое происходит, сотни тайм-аутов запускаются каждую секунду.

await endpointInstance.ScheduleEvery(
        timeSpan: TimeSpan.FromMinutes(5),
        task: context=> context.SendLocal(new SomeMessage())
    )
.ConfigureAwait(false);

Обновление: добавьте репо с кодом, воспроизводящим проблему.

https://github.com/spinakr/nsb-scheduling-msmq

Проблема возникает только тогда, когда пакет "NServiceBus.Azure.Transports.WindowsAzureStorageQueues" является ссылками в проекте, даже если он не используется!

У рассматриваемого приложения есть две конечные точки, размещенные в одном процессе. Использование сообщений из очередей хранилищ MSMQ и Azure. В репозитории проблема возникает только при добавлении транспортного пакета очередей хранения Azure.

2 ответа

Решение

Я предполагаю, что конечная точка, которую вы описываете, использует MSMQ в качестве транспорта (на основе имен методов и полей) и что сага работает на этой конечной точке.

MSMQ полагается на Timeout Manager для поддержки отложенной доставки. С другой стороны, транспорт Azure Storage Queues, похоже, решает задержку доставки другим способом. На самом деле он имеет функцию, включенную по умолчанию, которая предотвращает перенаправление отложенных сообщений в диспетчер времени ожидания. Если ваша конечная точка MSMQ сканирует сборку NServiceBus.Azure.Transports.WindowsAzureStorageQueues, ваши отложенные сообщения не достигают диспетчера времени ожидания.

Одним из решений этой проблемы будет настройка сканера сборки в конечной точке MSMQ для исключения этой сборки:

endpointConfiguration.AssemblyScanner().ExcludeAssemblies(
    "NServiceBus.Azure.Transports.WindowsAzureStorageQueues.dll");

Еще одно соображение при совместном размещении нескольких конечных точек в одном процессе - совместное использование ваших обработчиков. Возможно, вы захотите взглянуть на пример мультихостинга Endpoints, в котором упоминалось, как избежать нежелательной загрузки сборок с помощью сканирования сборок с черным списком.

Другие вопросы по тегам