private async Task <bool> DispatchProjection(ProjectionDescriptor projection, MessageEnvelope envelope, ProjectingContext context) { while (true) { try { await TryDispatch(projection, envelope, context).NotOnCapturedContext(); return(true); } catch (ProjectingException ex) { ProjectingError(ex); if (context.ExceptionSolution == ExceptionSolutions.Ignore) { return(true); } if (context.ExceptionSolution == ExceptionSolutions.Drop) { projection.Drop(); return(false); } if (!context.CanRetry()) { projection.Drop(); throw; } context.NextRetry(); } } }
public ProjectingException(ProjectionDescriptor descriptor, MessageEnvelope envelope, ProjectingContext context, Exception exception) : base($"Projecting '{descriptor.ContractName}' with message '{envelope.Meta.MessageContractName}' exception.", exception) { Descriptor = descriptor; Envelope = envelope; Context = context; }
private DispatchingResult(ProjectionDescriptor descriptor, Statuses status, int envelopesCount, long elapsedMilliseconds, bool anyDispatched, Exception exception = null) : this(descriptor, status) { EnvelopesCount = envelopesCount; ElapsedMilliseconds = elapsedMilliseconds; AnyDispatched = anyDispatched; Exception = exception; }
private async Task TryDispatch(ProjectionDescriptor descriptor, MessageEnvelope envelope, ProjectingContext context) { try { var instance = ProjectionFactory.CreateProjectionInstance(descriptor.ProjectionType); if (instance == null) { throw new NullReferenceException($"Projection instance {descriptor.ProjectionType.FullName} is null."); } await descriptor.Invoke(instance, envelope.Message, envelope.Meta, context); } catch (Exception e) { throw new ProjectingException(descriptor, envelope, context, e); } }
private async Task <DispatchingResult> Dispatch(ProjectionDescriptor descriptor, List <MessageEnvelope> envelopes, CancellationToken token) { if (descriptor.IsDropped()) { return(DispatchingResult.StillDropped(descriptor)); } var sw = new Stopwatch(); var context = new ProjectingContext(MaxProjectingRetries, descriptor.Checkpoint.Position); var anyDispatched = false; try { sw.Start(); using (var scope = this.NewTransactionScope()) { foreach (var envelope in envelopes) { if (!descriptor.CanDispatch(envelope.Message.GetType(), envelope.Meta.MessagePosition)) { continue; } context.Reset(); if (await DispatchProjection(descriptor, envelope, context).NotOnCapturedContext()) { descriptor.Checkpoint.Position = envelope.Meta.MessagePosition; anyDispatched = true; } } await UpdateCheckpoint(descriptor.Checkpoint, descriptor.UndropRequested, token).NotOnCapturedContext(); scope.Complete(); } sw.Stop(); return(DispatchingResult.Dispatched(descriptor, envelopes.Count, sw.ElapsedMilliseconds, anyDispatched)); } catch (Exception e) // error in batch { sw.Stop(); descriptor.Checkpoint.Position = context.StartingBatchAtPosition; // restoring position await UpdateCheckpoint(descriptor.Checkpoint, descriptor.UndropRequested, token).NotOnCapturedContext(); return(DispatchingResult.DroppedOnException(descriptor, envelopes.Count, sw.ElapsedMilliseconds, e)); } }
public DispatchingContext(ProjectionDescriptor descriptor, List <MessageEnvelope> envelopes) { Descriptor = descriptor; Envelopes = envelopes; }
private DispatchingResult(ProjectionDescriptor descriptor, Statuses status) { Descriptor = descriptor; Status = status; }
internal static DispatchingResult DroppedOnException(ProjectionDescriptor descriptor, int envelopesCount, long elapsedMilliseconds, Exception exception) { return(new DispatchingResult(descriptor, Statuses.DroppedOnException, envelopesCount, elapsedMilliseconds, false, exception)); }
internal static DispatchingResult Dispatched(ProjectionDescriptor descriptor, int envelopesCount, long elapsedMilliseconds, bool anyDispatched) { return(new DispatchingResult(descriptor, Statuses.Dispatched, envelopesCount, elapsedMilliseconds, anyDispatched)); }
internal static DispatchingResult StillDropped(ProjectionDescriptor descriptor) => new DispatchingResult(descriptor, Statuses.StillDropped);