Ejemplo n.º 1
0
 /// <summary>
 /// Subscribes the specified aggregator to a catchup.
 /// </summary>
 /// <typeparam name="TProjection">The type of the projection.</typeparam>
 /// <typeparam name="TData">The type of the stream's data.</typeparam>
 /// <typeparam name="TCursor">The type of the cursor.</typeparam>
 /// <param name="catchup">The catchup.</param>
 /// <param name="aggregator">The aggregator.</param>
 /// <returns>A disposable that, when disposed, unsubscribes the aggregator.</returns>
 public static IDisposable Subscribe <TProjection, TData, TCursor>(
     this IStreamCatchup <TData, TCursor> catchup,
     IStreamAggregator <TProjection, TData> aggregator,
     FetchAndSaveProjection <TProjection> manageProjection,
     HandleAggregatorError <TProjection> onError = null)
 {
     return(catchup.SubscribeAggregator(aggregator, manageProjection, onError));
 }
        public static FetchAndSaveProjection <TProjection> Catch <TProjection>(
            this FetchAndSaveProjection <TProjection> fetchAndSaveProjection,
            HandleAggregatorError <TProjection> onError)
        {
            return(async(id, aggregate) =>
            {
                Exception innerException = null;

                try
                {
                    await fetchAndSaveProjection(id, async projection =>
                    {
                        var resultingProjection = default(TProjection);

                        try
                        {
                            resultingProjection = await aggregate(projection);
                        }
                        catch (Exception exception)
                        {
                            var error = CheckErrorHandler(onError, exception, projection);

                            if (!error.ShouldContinue)
                            {
                                throw;
                            }

                            innerException = exception;

                            return error.Projection;
                        }

                        return resultingProjection;
                    });
                }
                catch (Exception exception)
                {
                    if (exception != innerException)
                    {
                        var error = CheckErrorHandler(onError, exception);

                        if (!error.ShouldContinue)
                        {
                            throw;
                        }
                    }
                }
            });
        }
        internal static StreamCatchupError <TProjection> CheckErrorHandler <TProjection>(
            this HandleAggregatorError <TProjection> onError,
            Exception exception,
            TProjection projection = default(TProjection))
        {
            var error = new StreamCatchupError <TProjection>
            {
                Exception  = exception,
                Projection = projection
            };

            onError(error);

            return(error);
        }
        public IDisposable SubscribeAggregator <TProjection>(
            IStreamAggregator <TProjection, TData> aggregator,
            FetchAndSaveProjection <TProjection> fetchAndSaveProjection,
            HandleAggregatorError <TProjection> onError)
        {
            var added = aggregatorSubscriptions.TryAdd(typeof(TProjection),
                                                       new AggregatorSubscription <TProjection, TData>(aggregator,
                                                                                                       fetchAndSaveProjection,
                                                                                                       onError));

            if (!added)
            {
                throw new InvalidOperationException(string.Format("Aggregator for projection of type {0} is already subscribed.", typeof(TProjection)));
            }

            return(Disposable.Create(() =>
            {
                IAggregatorSubscription _;
                aggregatorSubscriptions.TryRemove(typeof(TProjection), out _);
            }));
        }
Ejemplo n.º 5
0
        public AggregatorSubscription(
            IStreamAggregator <TProjection, TData> aggregator,
            FetchAndSaveProjection <TProjection> fetchAndSaveProjection = null,
            HandleAggregatorError <TProjection> onError = null)
        {
            if (aggregator == null)
            {
                throw new ArgumentNullException("aggregator");
            }

            OnError = onError ?? (error => { });

            if (onError != null)
            {
                fetchAndSaveProjection = fetchAndSaveProjection.Catch(onError);
            }

            FetchAndSaveProjection = fetchAndSaveProjection ??
                                     (async(streamId, aggregate) =>
            {
                await aggregate(Activator.CreateInstance <TProjection>());
            });
            Aggregator = aggregator;
        }