/// <summary> /// <see cref="UnarySequentialDispatcherRemoteNode{TInput}"/> /// </summary> /// <param name="persistentCache">Persistent cache to avoid dropped data on system crash</param> /// <param name="progress">Progress of the current bulk</param> /// <param name="host"><see cref="Host"/></param> /// <param name="cts"><see cref="CancellationTokenSource"/></param> /// <param name="circuitBreakerOptions"><see cref="CircuitBreakerOptions"/></param> /// <param name="clusterOptions"><see cref="ClusterOptions"/></param> /// <param name="logger"><see cref="ILogger"/></param> public UnarySequentialDispatcherRemoteNode( IAppCache persistentCache, IProgress <double> progress, Host host, CancellationTokenSource cts, CircuitBreakerOptions circuitBreakerOptions, ClusterOptions clusterOptions, ILogger logger) : base( Policy.Handle <Exception>() .AdvancedCircuitBreakerAsync(circuitBreakerOptions.CircuitBreakerFailureThreshold, circuitBreakerOptions.CircuitBreakerSamplingDuration, circuitBreakerOptions.CircuitBreakerMinimumThroughput, circuitBreakerOptions.CircuitBreakerDurationOfBreak, onBreak: (ex, timespan, context) => { logger.LogError( $"Batch processor breaker: Breaking the circuit for {timespan.TotalMilliseconds}ms due to {ex.Message}."); }, onReset: context => { logger.LogInformation( "Batch processor breaker: Succeeded, closed the circuit."); }, onHalfOpen: () => { logger.LogWarning( "Batch processor breaker: Half-open, next call is a trial."); }), clusterOptions, progress, cts, logger) { _logger = logger; _clusterOptions = clusterOptions; ISubject <PersistentItem <TInput> > dispatcherSubject = new Subject <PersistentItem <TInput> >(); _synchronizedDispatcherSubject = Subject.Synchronize(dispatcherSubject); _synchronizedDispatcherSubjectSubscription = _synchronizedDispatcherSubject .ObserveOn(new EventLoopScheduler(ts => new Thread(ts))) .Select(item => { return(Observable.FromAsync(() => persistentCache.AddItemAsync(item.Entity, item.CancellationTokenSource.Token))); }) .Merge() .Subscribe(); var channel = new Channel(host.MachineName, host.Port, ChannelCredentials.Insecure); _remoteContract = MagicOnionClient.Create <IRemoteContract <TInput> >(channel); IRemoteNodeSubject nodeReceiver = new NodeReceiver(_logger); _remoteNodeHealthSubscription = nodeReceiver.RemoteNodeHealthSubject.Subscribe(remoteNodeHealth => { NodeMetrics.RemoteNodeHealth = remoteNodeHealth; }); _nodeHub = StreamingHubClient.Connect <INodeHub, INodeReceiver>(channel, (INodeReceiver)nodeReceiver); NodeMetrics = new NodeMetrics(Guid.NewGuid()); }
/// <summary> /// <see cref="UnarySequentialDispatcherLocalNode{TInput}"/> /// </summary> /// <param name="persistentCache">Persistent cache to avoid dropped data on system crash</param> /// <param name="process">The <see cref="Task"/> to be applied to an item</param> /// <param name="progress">Progress of the current bulk</param> /// <param name="cts"><see cref="CancellationTokenSource"/></param> /// <param name="circuitBreakerOptions"><see cref="CircuitBreakerOptions"/></param> /// <param name="clusterOptions"><see cref="ClusterOptions"/></param> /// <param name="logger"><see cref="ILogger"/></param> public UnarySequentialDispatcherLocalNode( IAppCache persistentCache, Func <TInput, NodeMetrics, CancellationToken, Task> process, IProgress <double> progress, CancellationTokenSource cts, CircuitBreakerOptions circuitBreakerOptions, ClusterOptions clusterOptions, ILogger logger) : base( Policy.Handle <Exception>() .AdvancedCircuitBreakerAsync(circuitBreakerOptions.CircuitBreakerFailureThreshold, circuitBreakerOptions.CircuitBreakerSamplingDuration, circuitBreakerOptions.CircuitBreakerMinimumThroughput, circuitBreakerOptions.CircuitBreakerDurationOfBreak, onBreak: (ex, timespan, context) => { logger.LogError( $"Batch processor breaker: Breaking the circuit for {timespan.TotalMilliseconds}ms due to {ex.Message}."); }, onReset: context => { logger.LogInformation( "Batch processor breaker: Succeeded, closed the circuit."); }, onHalfOpen: () => { logger.LogWarning( "Batch processor breaker: Half-open, next call is a trial."); }), clusterOptions, progress, cts, logger) { _logger = logger; _process = process; _clusterOptions = clusterOptions; ISubject <PersistentItem <TInput> > dispatcherSubject = new Subject <PersistentItem <TInput> >(); _synchronizedDispatcherSubject = Subject.Synchronize(dispatcherSubject); _synchronizedDispatcherSubjectSubscription = _synchronizedDispatcherSubject .ObserveOn(new EventLoopScheduler(ts => new Thread(ts))) .Select(item => { return(Observable.FromAsync(() => persistentCache.AddItemAsync(item.Entity, item.CancellationTokenSource.Token))); }) .Merge() .Subscribe(); NodeMetrics = new NodeMetrics(Guid.NewGuid()); }