我一直在使用带有MassTransit的Automatonymous State Machine。我喜欢使用那个状态/ saga机器,特别是它是如何配置和设置的,以及我可以向状态机提供实现合同的事件以用作消息。
这就是它的样子:
//define the statemachine with a State class (ServiceState)
public class ServiceStateMachine :
AutomatonymousStateMachine<ServiceState>{
//define available states
public State Available { get; set; }
public State WaitForItem { get; set; }
//define available events
public Event<RequestItem> RequestItem { get; set; }
//configure the state machine and configure the store to use the ServiceState class
public void ConfigureStateMachineCorrelations(StateMachineSagaRepositoryConfigurator<ServiceState> r)
//bind events to contracts and conditions
r.Correlate(RequestItem,
(state, message) =>
state.CorrelationId == message.CorrelationId)
}
public ServiceStateMachine(IStateMachineActivityFactory activityFactory
{
State(() => Available);
State(() => WaitForItem);
Event(() => RequestItem);
//bind states, events, activities, custom actions...
During(Available,
When(RequestItem)
.Then((state, message) =>
{
state.ServiceId = message.ServiceId; // just an example baby!
})
.TransitionTo(WaitForItem)
.Then(() => _activityFactory.GetActivity<RequestItemActivity, ServiceState>())
}
哪些替代Saga实现有类似但没有连接到MQ架构?我想我真正想要的是状态机或Saga实现,至少有一个内存持久存储。
答案 0 :(得分:2)
您可以完全独立于MassTransit(或任何消息传递系统)使用Automatonymous。无论是否有数据,都有方法(和提升函数来分解状态机或事件)来引发事件。
_machine.RaiseEvent(instance, x => x.RequestItem, itemData);
普通状态机和实例实现没有状态(实例)存储的概念,这取决于应用程序。例如,您可以在内存中键入字典,或者您可以使用NHibernate程序集,这样可以很容易地将状态实例持久化到SQL数据库(该程序集主要包括用于映射CurrentState
属性的帮助程序,以及一些其他自定义类型。
这是一个在线请求的例子,我最近写的是Automatonymous最新分支(mt3)的单元测试:
class PhoneStateMachine :
AutomatonymousStateMachine<PrincessModelTelephone>
{
public PhoneStateMachine()
{
InstanceState(x => x.CurrentState);
State(() => OffHook);
State(() => Ringing);
State(() => Connected);
State(() => OnHold, Connected);
State(() => PhoneDestroyed);
Event(() => ServiceEstablished);
Event(() => CallDialed);
Event(() => HungUp);
Event(() => CallConnected);
Event(() => LeftMessage);
Event(() => PlacedOnHold);
Event(() => TakenOffHold);
Event(() => PhoneHurledAgainstWall);
Initially(
When(ServiceEstablished)
.Then(context => context.Instance.Number = context.Data.Digits)
.TransitionTo(OffHook));
During(OffHook,
When(CallDialed)
.TransitionTo(Ringing));
During(Ringing,
When(HungUp)
.TransitionTo(OffHook),
When(CallConnected)
.TransitionTo(Connected));
During(Connected,
When(LeftMessage).TransitionTo(OffHook),
When(HungUp).TransitionTo(OffHook),
When(PlacedOnHold).TransitionTo(OnHold));
During(OnHold,
When(TakenOffHold).TransitionTo(Connected),
When(PhoneHurledAgainstWall).TransitionTo(PhoneDestroyed));
DuringAny(
When(Connected.Enter)
.Then(context => StartCallTimer(context.Instance)),
When(Connected.Leave)
.Then(context => StopCallTimer(context.Instance)));
}
public State OffHook { get; set; }
public State Ringing { get; set; }
public State Connected { get; set; }
public State OnHold { get; set; }
public State PhoneDestroyed { get; set; }
public Event<PhoneServiceEstablished> ServiceEstablished { get; set; }
public Event CallDialed { get; set; }
public Event HungUp { get; set; }
public Event CallConnected { get; set; }
public Event LeftMessage { get; set; }
public Event PlacedOnHold { get; set; }
public Event TakenOffHold { get; set; }
public Event PhoneHurledAgainstWall { get; set; }
void StopCallTimer(PrincessModelTelephone instance)
{
instance.CallTimer.Stop();
}
void StartCallTimer(PrincessModelTelephone instance)
{
instance.CallTimer.Start();
}
}
创建并调用它(Princess模型是示例的状态实例),如下所示:
var phone = new PrincessModelTelephone();
await _machine.RaiseEvent(phone, _machine.ServiceEstablished, new PhoneServiceEstablished {Digits = "555-1212"});
await _machine.RaiseEvent(phone, x => x.CallDialed);
await _machine.RaiseEvent(phone, x => x.CallConnected);
await _machine.RaiseEvent(phone, x => x.PlacedOnHold);
await Task.Delay(10);
await _machine.RaiseEvent(phone, x => x.HungUp);
我确信还有更多示例,但状态机与任何依赖项都是分开的,可以在任何地方使用。