void Raise <TEvent>(Composer composer, TInstance instance, TEvent @event, Action <Composer, Activity <TInstance>, TInstance> callback) where TEvent : Event { List <Activity <TInstance> > activities; if (!_activityCache.TryGetValue(@event, out activities)) { return; } composer.Execute(() => { var notification = new EventNotification(instance, @event); var taskComposer = new TaskComposer <TInstance>(composer.CancellationToken); ((Composer)taskComposer).Execute(() => _raisingObserver.OnNext(notification)); foreach (var activity in activities) { callback(taskComposer, activity, instance); } ((Composer)taskComposer).Execute(() => _raisedObserver.OnNext(notification)); return(taskComposer.Finish()); }); }
void Transition(Composer composer, TInstance instance) { composer.Execute(() => { State <TInstance> currentState = _currentStateAccessor.Get(instance); if (_toState.Equals(currentState)) { return(composer.ComposeCompleted()); } var taskComposer = new TaskComposer <TInstance>(composer.CancellationToken); if (currentState != null) { currentState.Raise(taskComposer, instance, currentState.Leave); } _toState.Raise(taskComposer, instance, _toState.BeforeEnter, currentState); ((Composer)taskComposer).Execute(() => _currentStateAccessor.Set(instance, _toState)); if (currentState != null) { currentState.Raise(taskComposer, instance, currentState.AfterLeave, _toState); } _toState.Raise(taskComposer, instance, _toState.Enter); return(taskComposer.Finish()); }); }
public static Task ComposeActivity <T, TData>(this Composer composer, Activity <T> activity, T instance, TData data, bool runSynchronously = true) { var taskComposer = new TaskComposer <T>(composer.CancellationToken, runSynchronously); activity.Execute(composer, instance, data); return(taskComposer.Finish()); }
public static Task ComposeEvent <T>(this Composer composer, T instance, State <T> state, Event @event, bool runSynchronously = true) { var taskComposer = new TaskComposer <T>(composer.CancellationToken, runSynchronously); state.Raise(taskComposer, instance, @event); return(taskComposer.Finish()); }
public void Should_throw_an_exception_without_compensation() { var composer = new TaskComposer<int>(); composer.Execute(() => { throw new InvalidOperationException("This is expected"); }); var exception = Assert.Throws<AggregateException>(() => composer.Finish().Wait()); Assert.IsInstanceOf<InvalidOperationException>(exception.InnerException); }
public static Task Raise <TInstance, TData>(this EventLift <TInstance, TData> lift, TInstance instance, TData value, CancellationToken cancellationToken = default(CancellationToken)) where TInstance : class { var composer = new TaskComposer <TInstance>(cancellationToken); lift.Raise(composer, instance, value); return(composer.Finish()); }
public static Task Raise <T, TData>(this InstanceLift <T> lift, Event <TData> @event, TData data, CancellationToken cancellationToken = default(CancellationToken)) where T : StateMachine { var composer = new TaskComposer <T>(cancellationToken); lift.Raise(composer, @event, data); return(composer.Finish()); }
/// <summary> /// Raise a data event on the state machine /// </summary> /// <typeparam name="TData">The data type of the event</typeparam> /// <typeparam name="TInstance">The instance type</typeparam> /// <param name="stateMachine">The state machine</param> /// <param name="instance">The state machine instance</param> /// <param name="event"></param> /// <param name="data">The data for the event</param> /// <param name="cancellationToken"></param> public static void RaiseEvent <TData, TInstance>(this StateMachine <TInstance> stateMachine, TInstance instance, Event <TData> @event, TData data, CancellationToken cancellationToken = default(CancellationToken)) where TInstance : class { var composer = new TaskComposer <TInstance>(cancellationToken); stateMachine.RaiseEvent(composer, instance, @event, data); composer.Finish().Wait(); }
/// <summary> /// Transition a state machine instance to a specific state, producing any events related /// to the transaction such as leaving the previous state and entering the target state /// </summary> /// <typeparam name="TInstance">The state instance type</typeparam> /// <param name="stateMachine">The state machine</param> /// <param name="instance">The state instance</param> /// <param name="state">The target state</param> /// <param name="cancellationToken"></param> public static Task TransitionToState <TInstance>(this StateMachine <TInstance> stateMachine, TInstance instance, State state, CancellationToken cancellationToken = default(CancellationToken)) where TInstance : class { var composer = new TaskComposer <TInstance>(cancellationToken); stateMachine.TransitionToState(composer, instance, state); return(composer.Finish()); }
public void Should_throw_an_exception_without_compensation() { var composer = new TaskComposer <int>(); composer.Execute(() => { throw new InvalidOperationException("This is expected"); }); var exception = Assert.Throws <AggregateException>(() => composer.Finish().Wait()); Assert.IsInstanceOf <InvalidOperationException>(exception.InnerException); }
public void Should_delay_then_execute() { bool called = false; var composer = new TaskComposer <int>(); composer.Delay(100); composer.Execute(() => called = true); composer.Finish().Wait(); Assert.IsTrue(called); }
public void Should_execute_the_task() { bool called = false; var composer = new TaskComposer <int>(); composer.Execute(() => composer.Compose(x => x.Execute(() => called = true))); composer.Finish() .Wait(); Assert.IsTrue(called); }
public void Should_execute_the_method_immediately() { bool called = false; var composer = new TaskComposer <int>(); composer.Execute(() => called = true); composer.Finish() .Wait(); Assert.IsTrue(called); }
public void Should_execute_the_task() { bool called = false; var composer = new TaskComposer<int>(); composer.Execute(() => composer.Compose(x => x.Execute(() => called = true))); composer.Finish() .Wait(); Assert.IsTrue(called); }
public void Should_execute_the_method_immediately() { bool called = false; var composer = new TaskComposer<int>(); composer.Execute(() => called = true); composer.Finish() .Wait(); Assert.IsTrue(called); }
public void Should_delay_then_execute() { bool called = false; var composer = new TaskComposer<int>(); composer.Delay(100); composer.Execute(() => called = true); composer.Finish().Wait(); Assert.IsTrue(called); }
public void Should_always_be_called() { bool called = false; var composer = new TaskComposer<int>(); composer.Execute(() => { throw new InvalidOperationException("This is expected"); }); composer.Finally(status => { called = true; }); Assert.Throws<AggregateException>(() => composer.Finish().Wait()); Assert.IsTrue(called); }
State <TInstance> StateAccessor <TInstance> .Get(TInstance instance) { State <TInstance> state = _rawStateAccessor.Get(instance); if (state == null) { var composer = new TaskComposer <TInstance>(CancellationToken.None); _initialActivity.Execute(composer, instance); composer.Finish().Wait(); state = _rawStateAccessor.Get(instance); } return(state); }
void Activity <TInstance> .Execute <T>(Composer composer, TInstance instance, T value) { composer.Execute(() => { var taskComposer = new TaskComposer <TInstance>(composer.CancellationToken); foreach (var activity in _activities) { activity.Execute(taskComposer, instance, value); } return(taskComposer.Finish()); }); }
public void Should_always_be_called() { bool called = false; var composer = new TaskComposer <int>(); composer.Execute(() => { throw new InvalidOperationException("This is expected"); }); composer.Finally(status => { called = true; }); Assert.Throws <AggregateException>(() => composer.Finish().Wait()); Assert.IsTrue(called); }
public void Should_compensate_on_exception() { bool called = false; var composer = new TaskComposer <int>(); composer.Execute(() => { throw new InvalidOperationException("This is expected"); }); composer.Compensate(compensation => { called = true; return(compensation.Handled()); }); composer.Finish() .Wait(); Assert.IsTrue(called); }
public void Should_compensate_on_exception() { bool called = false; var composer = new TaskComposer<int>(); composer.Execute(() => { throw new InvalidOperationException("This is expected"); }); composer.Compensate(compensation => { called = true; return compensation.Handled(); }); composer.Finish() .Wait(); Assert.IsTrue(called); }
public void Should_throw_the_specified_exception_if_handled() { bool called = false; var composer = new TaskComposer <int>(); composer.Execute(() => { throw new InvalidOperationException("This is expected"); }); composer.Compensate(compensation => { called = true; return(compensation.Throw(new NotImplementedException("This is also expected"))); }); var exception = Assert.Throws <AggregateException>(() => composer.Finish().Wait()); Assert.IsInstanceOf <NotImplementedException>(exception.InnerException); Assert.IsTrue(called); }
void Execute(Composer composer, TInstance instance) { composer.Execute(() => { CompositeEventStatus value = _property.Get(instance); value.Set(_flag); _property.Set(instance, value); if (!value.Equals(_complete)) { return(composer.ComposeCompleted()); } var taskComposer = new TaskComposer <TInstance>(composer.CancellationToken); _completeCallback(taskComposer, instance); return(taskComposer.Finish()); }); }
void Activity <TInstance> .Execute <T>(Composer composer, TInstance instance, T value) { composer.Execute(() => { var taskComposer = new TaskComposer <TInstance>(composer.CancellationToken); _activities.ForEach(activity => activity.Execute(taskComposer, instance, value)); ((Composer)taskComposer).Compensate(compensation => { Type exceptionType = compensation.Exception.GetType(); #if !NETFX_CORE while (exceptionType != typeof(Exception).BaseType && exceptionType != null) #else while (exceptionType != typeof(Exception).GetTypeInfo().BaseType&& exceptionType != null) #endif { List <ExceptionActivity <TInstance> > handlers; if (_exceptionHandlers.TryGetValue(exceptionType, out handlers)) { var exceptionComposer = new TaskComposer <TInstance>(composer.CancellationToken); handlers.ForEach(handler => handler.Execute(exceptionComposer, instance, compensation.Exception)); return(compensation.Task(exceptionComposer.Finish())); } #if !NETFX_CORE exceptionType = exceptionType.BaseType; #else exceptionType = exceptionType.GetTypeInfo().BaseType; #endif } return(compensation.Throw()); }); }); }
Task StartStressGenerator(int instance, Task start) { var ready = new TaskCompletionSource<bool>(); var composer = new TaskComposer<bool>(_cancel.Token, false); string queueName = string.Format("{0}_client_{1}", _serviceBusAddress.Name, instance); Uri uri = RabbitMqEndpointAddress.Parse(_clientUri).ForQueue(queueName).Uri; var uriBuilder = new UriBuilder(uri); uriBuilder.Query = _clientUri.Query.Trim('?'); Uri address = uriBuilder.Uri; composer.Execute(() => { Interlocked.Increment(ref _instanceCount); }); composer.Execute(async () => { await Task.Yield(); }); IServiceBus bus = null; composer.Execute(() => { _log.InfoFormat("Creating {0}", address); bus = ServiceBusFactory.New(x => { x.UseRabbitMq(r => { r.ConfigureHost(address, h => { h.SetUsername(_username); h.SetPassword(_password); h.SetRequestedHeartbeat(_heartbeat); }); }); x.ReceiveFrom(address); }); }, false); Stopwatch clientTimer = null; composer.Execute(async () => { ready.TrySetResult(true); await start; }); composer.Execute(() => clientTimer = Stopwatch.StartNew()); composer.Execute(() => { Task task = composer.Compose(x => { for (int i = 0; i < _iterations; i++) { int iteration = i; x.Execute(() => { string messageContent = _mixed && iteration % 2 == 0 ? new string('*', 128) : _messageContent; var requestMessage = new StressfulRequestMessage(messageContent); Stopwatch sendTimer = Stopwatch.StartNew(); bus.Publish<StressfulRequest>(requestMessage); sendTimer.Stop(); Interlocked.Add(ref _sendTime, sendTimer.ElapsedTicks); _timings[instance][iteration] = (int)sendTimer.ElapsedTicks; Interlocked.Increment(ref _sendCount); }); } }); return task; }); composer.Execute(() => clientTimer.Stop()); composer.Execute(() => bus.Dispose(), false); composer.Compensate(compensation => { return compensation.Handled(); }); composer.Finally(status => { Interlocked.Add(ref _totalTime, clientTimer.ElapsedMilliseconds); int count = Interlocked.Decrement(ref _instanceCount); if (count == 0) Task.Factory.StartNew(() => _hostControl.Stop()); }, false); _clientTasks.Add(composer.Finish()); return ready.Task; }
public void Should_throw_the_same_exception_if_not_handled() { bool called = false; var composer = new TaskComposer<int>(); composer.Execute(() => { throw new InvalidOperationException("This is expected"); }); composer.Compensate(compensation => { called = true; return compensation.Throw(); }); var exception = Assert.Throws<AggregateException>(() => composer.Finish().Wait()); Assert.IsInstanceOf<InvalidOperationException>(exception.InnerException); Assert.IsTrue(called); }
Task StartStressGenerator(int instance, Task start) { var ready = new TaskCompletionSource <bool>(); var composer = new TaskComposer <bool>(_cancel.Token, false); var endpointAddress = _serviceBus.Endpoint.Address as IRabbitMqEndpointAddress; string queueName = string.Format("{0}_client_{1}", endpointAddress.Name, instance); Uri uri = RabbitMqEndpointAddress.Parse(_clientUri).ForQueue(queueName).Uri; var uriBuilder = new UriBuilder(uri); uriBuilder.Query = _clientUri.Query.Trim('?'); Uri address = uriBuilder.Uri; composer.Execute(() => { Interlocked.Increment(ref _instanceCount); }); IServiceBus bus = null; composer.Execute(() => { _log.InfoFormat("Creating {0}", address); bus = ServiceBusFactory.New(x => { x.UseRabbitMq(r => { r.ConfigureHost(address, h => { h.SetUsername(_username); h.SetPassword(_password); h.SetRequestedHeartbeat(_heartbeat); }); }); x.ReceiveFrom(address); }); }, false); Stopwatch clientTimer = null; composer.Execute(() => { ready.TrySetResult(true); return(start); }); composer.Execute(() => clientTimer = Stopwatch.StartNew()); for (int requestClient = 0; requestClient < _requestsPerInstance; requestClient++) { int clientIndex = requestClient; composer.Execute(() => { Task task = composer.Compose(x => { for (int i = 0; i < _iterations; i++) { int iteration = i; x.Execute(() => { string messageContent = _mixed && iteration % 2 == 0 ? new string('*', 128) : _messageContent; var requestMessage = new StressfulRequestMessage(messageContent); ITaskRequest <StressfulRequest> taskRequest = bus.PublishRequestAsync <StressfulRequest>(requestMessage, r => { r.Handle <StressfulResponse>(response => { Interlocked.Increment(ref _responseCount); TimeSpan timeSpan = response.Timestamp - requestMessage.Timestamp; Interlocked.Add(ref _responseTime, (long)timeSpan.TotalMilliseconds); _timings[instance][clientIndex * _iterations + iteration] = (int)timeSpan.TotalMilliseconds; if (response.RequestId != requestMessage.RequestId) { Interlocked.Increment(ref _mismatchedResponseCount); } }); }); Interlocked.Increment(ref _requestCount); return(taskRequest.Task); }); } }); return(task); }); } composer.Execute(() => clientTimer.Stop()); composer.Execute(() => bus.Dispose(), false); composer.Compensate(compensation => { return(compensation.Handled()); }); composer.Finally(status => { Interlocked.Add(ref _totalTime, clientTimer.ElapsedMilliseconds); int count = Interlocked.Decrement(ref _instanceCount); if (count == 0) { Task.Factory.StartNew(() => _hostControl.Stop()); } }, false); _clientTasks.Add(composer.Finish()); return(ready.Task); }
Task StartStressGenerator(int instance, Task start) { var ready = new TaskCompletionSource<bool>(); var composer = new TaskComposer<bool>(_cancel.Token, false); var endpointAddress = _serviceBus.Endpoint.Address as IRabbitMqEndpointAddress; string queueName = string.Format("{0}_client_{1}", endpointAddress.Name, instance); Uri uri = RabbitMqEndpointAddress.Parse(_clientUri).ForQueue(queueName).Uri; var uriBuilder = new UriBuilder(uri); uriBuilder.Query = _clientUri.Query.Trim('?'); Uri address = uriBuilder.Uri; composer.Execute(() => { Interlocked.Increment(ref _instanceCount); }); IServiceBus bus = null; composer.Execute(() => { _log.InfoFormat("Creating {0}", address); bus = ServiceBusFactory.New(x => { x.UseRabbitMq(r => { r.ConfigureHost(address, h => { h.SetUsername(_username); h.SetPassword(_password); h.SetRequestedHeartbeat(_heartbeat); }); }); x.ReceiveFrom(address); }); }, false); Stopwatch clientTimer = null; composer.Execute(() => { ready.TrySetResult(true); return start; }); composer.Execute(() => clientTimer = Stopwatch.StartNew()); for (int requestClient = 0; requestClient < _requestsPerInstance; requestClient++) { int clientIndex = requestClient; composer.Execute(() => { Task task = composer.Compose(x => { for (int i = 0; i < _iterations; i++) { int iteration = i; x.Execute(() => { string messageContent = _mixed && iteration % 2 == 0 ? new string('*', 128) : _messageContent; var requestMessage = new StressfulRequestMessage(messageContent); ITaskRequest<StressfulRequest> taskRequest = bus.PublishRequestAsync<StressfulRequest>(requestMessage, r => { r.Handle<StressfulResponse>(response => { Interlocked.Increment(ref _responseCount); TimeSpan timeSpan = response.Timestamp - requestMessage.Timestamp; Interlocked.Add(ref _responseTime, (long)timeSpan.TotalMilliseconds); _timings[instance][clientIndex * _iterations + iteration] = (int)timeSpan.TotalMilliseconds; if (response.RequestId != requestMessage.RequestId) { Interlocked.Increment(ref _mismatchedResponseCount); } }); }); Interlocked.Increment(ref _requestCount); return taskRequest.Task; }); } }); return task; }); } composer.Execute(() => clientTimer.Stop()); composer.Execute(() => bus.Dispose(), false); composer.Compensate(compensation => { return compensation.Handled(); }); composer.Finally(status => { Interlocked.Add(ref _totalTime, clientTimer.ElapsedMilliseconds); int count = Interlocked.Decrement(ref _instanceCount); if (count == 0) Task.Factory.StartNew(() => _hostControl.Stop()); }, false); _clientTasks.Add(composer.Finish()); return ready.Task; }
Task StartStressGenerator(int instance, Task start) { var ready = new TaskCompletionSource <bool>(); var composer = new TaskComposer <bool>(_cancel.Token, false); string queueName = string.Format("{0}_client_{1}", _serviceBusAddress.Name, instance); Uri uri = RabbitMqEndpointAddress.Parse(_clientUri).ForQueue(queueName).Uri; var uriBuilder = new UriBuilder(uri); uriBuilder.Query = _clientUri.Query.Trim('?'); Uri address = uriBuilder.Uri; composer.Execute(() => { Interlocked.Increment(ref _instanceCount); }); composer.Execute(async() => { await Task.Yield(); }); IServiceBus bus = null; composer.Execute(() => { _log.InfoFormat("Creating {0}", address); bus = ServiceBusFactory.New(x => { x.UseRabbitMq(r => { r.ConfigureHost(address, h => { h.SetUsername(_username); h.SetPassword(_password); h.SetRequestedHeartbeat(_heartbeat); }); }); x.ReceiveFrom(address); }); }, false); Stopwatch clientTimer = null; composer.Execute(async() => { ready.TrySetResult(true); await start; }); composer.Execute(() => clientTimer = Stopwatch.StartNew()); composer.Execute(() => { Task task = composer.Compose(x => { for (int i = 0; i < _iterations; i++) { int iteration = i; x.Execute(() => { string messageContent = _mixed && iteration % 2 == 0 ? new string('*', 128) : _messageContent; var requestMessage = new StressfulRequestMessage(messageContent); Stopwatch sendTimer = Stopwatch.StartNew(); bus.Publish <StressfulRequest>(requestMessage); sendTimer.Stop(); Interlocked.Add(ref _sendTime, sendTimer.ElapsedTicks); _timings[instance][iteration] = (int)sendTimer.ElapsedTicks; Interlocked.Increment(ref _sendCount); }); } }); return(task); }); composer.Execute(() => clientTimer.Stop()); composer.Execute(() => bus.Dispose(), false); composer.Compensate(compensation => { return(compensation.Handled()); }); composer.Finally(status => { Interlocked.Add(ref _totalTime, clientTimer.ElapsedMilliseconds); int count = Interlocked.Decrement(ref _instanceCount); if (count == 0) { Task.Factory.StartNew(() => _hostControl.Stop()); } }, false); _clientTasks.Add(composer.Finish()); return(ready.Task); }