My Saga消息处理程序(配置为ISagaStartedBy)为收到的每条消息请求超时消息。
一次调试几条消息,我发现第一次触发处理程序的时间,发送到超时管理器的传奇ID与a)持久存储在数据库中的传统ID不同,b)传奇后续邮件中发送的ID。后续消息都从数据库中发送Saga ID。
这是处理程序:
public void Handle(PaymentRequested message)
{
int timeoutMinutes = 3;
try
{
timeoutMinutes = int.Parse(ConfigurationManager.AppSettings["TimeoutMinutes"]);
}
catch (Exception ex)
{
// log errors
}
Data.PseudoSagaID = message.PseudoSagaID;
var child = new TransactionDetail()
{ // fields added}
Data.AddTransactionItem(message.TransactionItem);
RequestUtcTimeout(DateTime.UtcNow.AddMinutes(timeoutMinutes), "Saga ending");
}
我也尝试在代码中设置Saga ID,但是当它退出处理程序时,它会在数据库中被覆盖。我有自己的持有人,如下:
public class MySBASagaPersister : ISagaPersister, IDisposable
{
public MySBASagaPersister(ISessionFactory sessionFactory)
{
SessionFactory = sessionFactory;
Session = sessionFactory.OpenSession();
}
public ISessionFactory SessionFactory { get; set; }
public ISession Session { get; set; }
#region ISagaPersister Members
public void Save(ISagaEntity saga)
{
Session.Save(saga);
}
public void Update(ISagaEntity saga)
{
Session.Merge(saga);
}
public void UpdateWithDelete(ISagaEntity saga)
{
Session.Merge(saga);
}
public T Get<T>(Guid sagaId) where T : ISagaEntity
{
return Session.CreateCriteria(typeof(T), "b")
.Add(Restrictions.Eq("b.Id", sagaId))
.SetFetchMode("b.PaymentRequestedTransactionItems", FetchMode.Eager)
.SetCacheable(true)
.SetCacheMode(CacheMode.Normal)
.UniqueResult<T>();
}
public T Get<T>(string property, object value) where T : ISagaEntity
{
return Session.CreateCriteria(typeof(T), "b")
.Add(Restrictions.Eq("b." + property, value))
.SetFetchMode("b.PaymentRequestedTransactionItems", FetchMode.Eager)
.UniqueResult<T>();
}
public void Complete(ISagaEntity saga)
{
Session.Delete(saga);
}
#endregion
#region IDisposable Members
void IDisposable.Dispose()
{
if (Session == null) return;
if (!Session.IsOpen) return;
Session.Close();
Session.Dispose();
}
#endregion
}
如何检查saga是否已保存在数据库中?或者这是检查真正的Saga ID的错误方法吗?或者我的超时请求是否错误?
更新:
public override void ConfigureHowToFindSaga()
{
// Map PaymentRequested message type.
ConfigureMapping<PaymentRequested>(
saga => saga.PseudoSagaID,
message => message.PseudoSagaID);
// Map PaymentCancelled message type.
ConfigureMapping<PaymentCancelled>(
saga => saga.PseudoSagaID,
message => message.PseudoSagaID);
}
我之所以不使用基于guid的Id将数据从数据库中拉出来的原因是因为一次只有一个saga活动因此使用PseudoSagaID但它仍然应该以相同的方式工作。如果没有传奇,那么应该创建一个并且应该在那时生成一个新的guid等并且预先设置。但事实并非如此......