public static async Task Retry <T>(this IRetryPolicy retryPolicy, ConsumeContext <T> context, Func <ConsumeContext <T>, Task> retryMethod) where T : class { using (RetryPolicyContext <ConsumeContext <T> > policyContext = retryPolicy.CreatePolicyContext(context)) { try { await retryMethod(policyContext.Context).ConfigureAwait(false); } catch (Exception exception) { RetryContext <ConsumeContext <T> > retryContext; if (context.TryGetPayload(out retryContext)) { throw; } if (!policyContext.CanRetry(exception, out retryContext)) { context.GetOrAddPayload(() => retryContext); throw; } await Attempt(retryContext, retryMethod).ConfigureAwait(false); } } }
public void SetContext(ConsumeContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } lock (this) { if (_context == null) { _context = context; _marker = new ScopedConsumeContext(); context.GetOrAddPayload(() => _marker); } else if (ReferenceEquals(_context, context)) { } else if (!context.TryGetPayload <ScopedConsumeContext>(out _)) { throw new InvalidOperationException("The ConsumeContext was already set."); } } }
Task Send <T>(ConsumeContext <T> context, Func <ConsumeContext <T>, ISagaRepositoryContextFactory <TSaga>, Task> send) where T : class { if (context.TryGetPayload <ILifetimeScope>(out var existingScope)) { context.GetOrAddPayload(() => existingScope.ResolveOptional <IStateMachineActivityFactory>() ?? AutofacStateMachineActivityFactory.Instance); var factory = existingScope.Resolve <ISagaRepositoryContextFactory <TSaga> >(); return(send(context, factory)); } var parentLifetimeScope = _scopeProvider.GetLifetimeScope(context); async Task CreateScope() { await using var scope = parentLifetimeScope.BeginLifetimeScope(_name, builder => { builder.ConfigureScope(context); _configureScope?.Invoke(builder, context); }); var activityFactory = scope.ResolveOptional <IStateMachineActivityFactory>() ?? AutofacStateMachineActivityFactory.Instance; var consumeContext = scope.Resolve <ConsumeContext <T> >(); var consumeContextScope = new ConsumeContextScope <T>(consumeContext, activityFactory); var factory = scope.Resolve <ISagaRepositoryContextFactory <TSaga> >(); await send(consumeContextScope, factory).ConfigureAwait(false); } return(CreateScope()); }
Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next) { var schedulerContext = context.GetPayload <MessageSchedulerContext>(); context.GetOrAddPayload <MessageRedeliveryContext>(() => new ScheduleMessageRedeliveryContext <TMessage>(context, schedulerContext)); return(next.Send(context)); }
Task Send <T>(ConsumeContext <T> context, Func <ConsumeContext <T>, ISagaRepositoryContextFactory <TSaga>, Task> send) where T : class { if (!context.TryGetPayload(out IServiceProvider serviceProvider)) { serviceProvider = _serviceProvider; } if (context.TryGetPayload <IServiceScope>(out var existingScope)) { existingScope.SetCurrentConsumeContext(context); context.GetOrAddPayload(() => existingScope.ServiceProvider.GetService <IStateMachineActivityFactory>() ?? DependencyInjectionStateMachineActivityFactory.Instance); var factory = existingScope.ServiceProvider.GetRequiredService <ISagaRepositoryContextFactory <TSaga> >(); return(send(context, factory)); } async Task CreateScope() { var serviceScope = serviceProvider.CreateScope(); try { var scopeServiceProvider = new DependencyInjectionScopeServiceProvider(serviceScope.ServiceProvider); var scopeContext = new ConsumeContextScope <T>(context, serviceScope, serviceScope.ServiceProvider, scopeServiceProvider); serviceScope.SetCurrentConsumeContext(scopeContext); var activityFactory = serviceScope.ServiceProvider.GetService <IStateMachineActivityFactory>() ?? DependencyInjectionStateMachineActivityFactory.Instance; var consumeContextScope = new ConsumeContextScope <T>(scopeContext, activityFactory); var factory = serviceScope.ServiceProvider.GetRequiredService <ISagaRepositoryContextFactory <TSaga> >(); await send(consumeContextScope, factory).ConfigureAwait(false); } finally { if (serviceScope is IAsyncDisposable asyncDisposable) { await asyncDisposable.DisposeAsync().ConfigureAwait(false); } else { serviceScope.Dispose(); } } } return(CreateScope()); }
Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next) { context.GetOrAddPayload <MessageRedeliveryContext>(() => { var provider = new ActiveMqScheduleMessageProvider(context); return(new ActiveMqMessageRedeliveryContext <TMessage>(context, new MessageScheduler(provider))); }); return(next.Send(context)); }
async Task ISagaRepository <TSaga> .Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) { using (var lifetimeScope = _scope.BeginLifetimeScope(_name, x => ConfigureScope(x, context))) { ConsumeContext <T> proxy = context.CreateScope(lifetimeScope); proxy.GetOrAddPayload <IStateMachineActivityFactory>(() => new AutofacStateMachineActivityFactory()); await _repository.Send(proxy, policy, next).ConfigureAwait(false); } }
Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next) { context.GetOrAddPayload <MessageRedeliveryContext>(() => { var modelContext = context.ReceiveContext.GetPayload <SessionContext>(); var provider = new DelayedExchangeScheduleMessageProvider(context, modelContext.ConnectionContext.Topology, modelContext.ConnectionContext.HostAddress); return(new DelayedExchangeMessageRedeliveryContext <TMessage>(context, new MessageScheduler(provider))); }); return(next.Send(context)); }
Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next) { context.GetOrAddPayload <MessageRedeliveryContext>(() => { var modelContext = context.ReceiveContext.GetPayload <ModelContext>(); var scheduler = new DelayedExchangeMessageScheduler(context, modelContext.ConnectionContext.HostSettings); return(new DelayedExchangeMessageRedeliveryContext <TMessage>(context, scheduler)); }); return(next.Send(context)); }
public async Task Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next) { if (context.Headers.TryGetHeader(MessageHeaders.ClientId, out var obj) && (obj is Guid clientId || obj is string s && Guid.TryParse(s, out clientId))) { var clientContext = await _clientCache.Link(clientId, context.ResponseAddress ?? context.SourceAddress).ConfigureAwait(false); clientContext.NotifyConsumed(context); context.GetOrAddPayload(() => clientContext); } await next.Send(context).ConfigureAwait(false); }
async Task ISagaRepository <TSaga> .Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) { using (var nestedContainer = _container.GetNestedContainer()) { ConsumeContext <T> proxy = context.CreateScope(nestedContainer); nestedContainer.Configure(x => { x.For <ConsumeContext>() .Use(proxy); x.For <ConsumeContext <T> >() .Use(proxy); }); proxy.GetOrAddPayload <IStateMachineActivityFactory>(() => new StructureMapStateMachineActivityFactory()); await _repository.Send(proxy, policy, next).ConfigureAwait(false); } }
Task Send <T>(ConsumeContext <T> context, Func <ConsumeContext <T>, ISagaRepositoryContextFactory <TSaga>, Task> send) where T : class { if (!context.TryGetPayload(out IServiceProvider serviceProvider)) { serviceProvider = _serviceProvider; } if (context.TryGetPayload <IServiceScope>(out var existingScope)) { existingScope.UpdateScope(context); context.GetOrAddPayload(() => existingScope.ServiceProvider.GetService <IStateMachineActivityFactory>() ?? DependencyInjectionStateMachineActivityFactory.Instance); var factory = existingScope.ServiceProvider.GetRequiredService <ISagaRepositoryContextFactory <TSaga> >(); return(send(context, factory)); } async Task CreateScope() { using var serviceScope = serviceProvider.CreateScope(); var scopeServiceProvider = serviceScope.ServiceProvider; var scopeContext = new ConsumeContextScope <T>(context, serviceScope, scopeServiceProvider); serviceScope.UpdateScope(scopeContext); var activityFactory = scopeServiceProvider.GetService <IStateMachineActivityFactory>() ?? DependencyInjectionStateMachineActivityFactory.Instance; var consumeContextScope = new ConsumeContextScope <T>(scopeContext, activityFactory); var factory = scopeServiceProvider.GetRequiredService <ISagaRepositoryContextFactory <TSaga> >(); await send(consumeContextScope, factory).ConfigureAwait(false); } return(CreateScope()); }
Task Send <T>(ConsumeContext <T> context, Func <ConsumeContext <T>, ISagaRepositoryContextFactory <TSaga>, Task> send) where T : class { if (context.TryGetPayload <Scope>(out var existingScope)) { existingScope.UpdateScope(context); context.GetOrAddPayload(() => existingScope.TryGetInstance <IStateMachineActivityFactory>() ?? SimpleInjectorStateMachineActivityFactory.Instance); var factory = existingScope.GetInstance <ISagaRepositoryContextFactory <TSaga> >(); return(send(context, factory)); } var scope = AsyncScopedLifestyle.BeginScope(_container); async Task CreateNestedContainer() { try { var scopeContext = new ConsumeContextScope <T>(context, scope); scope.UpdateScope(scopeContext); var activityFactory = scope.TryGetInstance <IStateMachineActivityFactory>() ?? SimpleInjectorStateMachineActivityFactory.Instance; var consumeContextScope = new ConsumeContextScope <T>(scopeContext, activityFactory); var factory = scope.GetInstance <ISagaRepositoryContextFactory <TSaga> >(); await send(consumeContextScope, factory).ConfigureAwait(false); } finally { scope.Dispose(); } } return(CreateNestedContainer()); }
Task Send <T>(ConsumeContext <T> context, Func <ConsumeContext <T>, ISagaRepositoryContextFactory <TSaga>, Task> send) where T : class { if (context.TryGetPayload <IKernel>(out var existingKernel)) { existingKernel.UpdateScope(context); context.GetOrAddPayload(() => existingKernel.TryResolve <IStateMachineActivityFactory>() ?? WindsorStateMachineActivityFactory.Instance); var factory = existingKernel.Resolve <ISagaRepositoryContextFactory <TSaga> >(); return(send(context, factory)); } var scope = _kernel.CreateNewOrUseExistingMessageScope(); async Task CreateMessageScope() { try { var scopeContext = new ConsumeContextScope <T>(context, _kernel); _kernel.UpdateScope(scopeContext); var activityFactory = _kernel.TryResolve <IStateMachineActivityFactory>() ?? WindsorStateMachineActivityFactory.Instance; var consumeContextScope = new ConsumeContextScope <T>(scopeContext, activityFactory); var factory = _kernel.Resolve <ISagaRepositoryContextFactory <TSaga> >(); await send(consumeContextScope, factory).ConfigureAwait(false); } finally { scope.Dispose(); } } return(CreateMessageScope()); }
Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next) { context.GetOrAddPayload <MessageRedeliveryContext>(() => new DelayedExchangeMessageRedeliveryContext <TMessage>(context)); return(next.Send(context)); }
public async Task Send(ConsumeContext <T> context, IPipe <ConsumeContext <T> > next) { RetryPolicyContext <ConsumeContext <T> > policyContext = _retryPolicy.CreatePolicyContext(context); await _observers.PostCreate(policyContext).ConfigureAwait(false); try { await next.Send(policyContext.Context).ConfigureAwait(false); } catch (Exception exception) { if (context.CancellationToken.IsCancellationRequested) { if (exception is OperationCanceledException canceledException && canceledException.CancellationToken == context.CancellationToken) { throw; } context.CancellationToken.ThrowIfCancellationRequested(); } if (policyContext.Context.TryGetPayload(out RetryContext <ConsumeContext <T> > payloadRetryContext)) { await policyContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(payloadRetryContext).ConfigureAwait(false); context.GetOrAddPayload(() => payloadRetryContext); throw; } if (policyContext.Context.TryGetPayload(out RetryContext genericRetryContext)) { await policyContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(genericRetryContext).ConfigureAwait(false); context.GetOrAddPayload(() => genericRetryContext); throw; } if (!policyContext.CanRetry(exception, out RetryContext <ConsumeContext <T> > retryContext)) { await retryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(retryContext).ConfigureAwait(false); if (_retryPolicy.IsHandled(exception)) { context.GetOrAddPayload(() => retryContext); } throw; } int previousDeliveryCount = context.Headers.Get(MessageHeaders.RedeliveryCount, default(int?)) ?? 0; for (int retryIndex = 0; retryIndex < previousDeliveryCount; retryIndex++) { if (!retryContext.CanRetry(exception, out retryContext)) { await retryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(retryContext).ConfigureAwait(false); if (_retryPolicy.IsHandled(exception)) { context.GetOrAddPayload(() => retryContext); } throw; } } await _observers.PostFault(retryContext).ConfigureAwait(false); try { if (!context.TryGetPayload(out MessageRedeliveryContext redeliveryContext)) { throw new ContextException("The message redelivery context was not available to delay the message", exception); } var delay = retryContext.Delay ?? TimeSpan.Zero; await redeliveryContext.ScheduleRedelivery(delay).ConfigureAwait(false); await context.NotifyConsumed(context, context.ReceiveContext.ElapsedTime, TypeMetadataCache <RedeliveryRetryFilter <T> > .ShortName).ConfigureAwait(false); } catch (Exception redeliveryException) { throw new ContextException("The message delivery could not be rescheduled", new AggregateException(redeliveryException, exception)); } } }
static void AddStateMachineActivityFactory(ConsumeContext context) { context.GetOrAddPayload(() => _activityFactory); }
TPayload PipeContext.GetOrAddPayload <TPayload>(PayloadFactory <TPayload> payloadFactory) { return(_context.GetOrAddPayload(payloadFactory)); }
public async Task Send(ConsumeContext <T> context, IPipe <ConsumeContext <T> > next) { RetryPolicyContext <ConsumeContext <T> > policyContext = _retryPolicy.CreatePolicyContext(context); await _observers.PostCreate(policyContext).ConfigureAwait(false); try { await next.Send(policyContext.Context).ConfigureAwait(false); } catch (Exception exception) { RetryContext <ConsumeContext <T> > payloadRetryContext; if (context.TryGetPayload(out payloadRetryContext)) { await policyContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(payloadRetryContext).ConfigureAwait(false); throw; } RetryContext genericRetryContext; if (context.TryGetPayload(out genericRetryContext)) { await policyContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(genericRetryContext).ConfigureAwait(false); throw; } RetryContext <ConsumeContext <T> > retryContext; if (!policyContext.CanRetry(exception, out retryContext)) { await retryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(retryContext).ConfigureAwait(false); context.GetOrAddPayload(() => retryContext); throw; } int previousDeliveryCount = context.Headers.Get(MessageHeaders.RedeliveryCount, default(int?)) ?? 0; for (int retryIndex = 0; retryIndex < previousDeliveryCount; retryIndex++) { if (!retryContext.CanRetry(exception, out retryContext)) { await retryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(retryContext).ConfigureAwait(false); context.GetOrAddPayload(() => retryContext); throw; } } await _observers.PostFault(retryContext).ConfigureAwait(false); try { MessageRedeliveryContext redeliveryContext; if (!context.TryGetPayload(out redeliveryContext)) { throw new ContextException("The message redelivery context was not available to delay the message", exception); } var delay = retryContext.Delay ?? TimeSpan.Zero; await redeliveryContext.ScheduleRedelivery(delay).ConfigureAwait(false); } catch (Exception redeliveryException) { throw new ContextException("The message delivery could not be rescheduled", new AggregateException(redeliveryException, exception)); } } }