我已多次阅读网站上的文档.我一遍又一遍地阅读相同的文章,我无法理解他们想要用传奇来实现的目标.此外,互联网上几乎没有与此主题相关的资源.
但我完全陷入了试图理解定义所谓的传奇的目的和好处.我理解处理程序(IHandleMessages) - 这些是拦截器.但我无法理解佐贺的用途.文档中的语言假设我应该知道一些特别的东西来掌握这个想法,但我不这样做.
有人可以用简单的语言向我解释,希望以现实生活中的例子说明我必须或应该定义Saga的情况,这样做有什么好处?我已经创建了一个具有多个端点和Saga定义的应用程序,如示例所示,它可以工作(我猜)但我不明白这些传奇是如何定义的......在许多示例中,他们在Saga类中使用RequestTimeout()方法.为什么,为什么有人想故意造成超时?我不想在这里放任何代码片段,因为它无关,我需要理解为什么我会想要使用"Sagas"无论那意味着什么?
谢谢.
我在使用NServiceBus saga时遇到"乐观并发冲突"异常.
我的传奇涵盖了一个相对简单的流程:当任何消息到达时,它几乎没有外部请求,并在一段时间后收集回复.
下面你可以找到我的传奇的一个例子.
NServiceBus为此类流产生"乐观并发冲突"异常是否正常?
我应该考虑以某种方式重新设计传奇吗?
class MySaga: SqlSaga<SagaData>, ...
{
CorrelationPropertyName => nameof(SagaData.UserId);
public Task Handle(StartSagaMessage message, IMessageHandlerContext context)
{
// save a new item id
Data.Items.Add(message.ItemId);
// make an external request for the item title
context.Send<GetItemTitle>(message.ItemId);
// make an external request for the item description
context.Send<GetItemDescription>(message.ItemId);
// gather results after one hour
RequestTimeout<RequestTimeout>(TimeSpan.FromHours(1));
}
// this method sometimes raises "optimistic concurrency violation" exception
public Task Handle(GetItemTitleResponse message, IMessageHandlerContext context)
{
Data.ItemTitles[message.ItemId] = message.ItemTitle;
}
// this method sometimes …Run Code Online (Sandbox Code Playgroud) 我有一个saga,如果从调用返回的状态成功,saga结束,则每隔30秒检查一次API调用的状态,如果不是saga等待30秒并再次尝试.如果API调用未在60分钟内返回成功响应,则传奇超时并结束.
我在解除60分钟超时时遇到问题.我的代码是
public class MonitorSubmissionFeedSagaData: IContainSagaData
{
public Guid Id { get; set; }
public string Originator { get; set; }
public string OriginalMessageId { get; set; }
public bool TimeoutSet { get; set; }
[Unique]
public string JobId { get; set; }
}
public class MonitorSubmissionFeedSaga : Saga<MonitorSubmissionFeedSagaData>,
IAmStartedByMessages<MonitorFeedSubmissonCommand>,
IHandleMessages<StartCheckSubmissionCommand>,
IHandleTimeouts<MonitorSubmissionFeedSagaTimeout>
{
public const int SagaTimeoutInMinutes = 60;
public IEmpathyBrokerClientApi PostFileService { get; set; }
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<MonitorSubmissionFeedSagaData> mapper)
{
mapper.ConfigureMapping<MonitorFeedSubmissonCommand>(x => x.JobId).ToSaga(saga => saga.JobId);
}
public void …Run Code Online (Sandbox Code Playgroud) 我正在使用 DDD 设计 CQRS 应用程序,并且想知道如何实现以下场景:
Participant聚合可以被多个引用ParticipantEntry聚合AddParticipantInfoCommand发送到 Command 端,其中包含Participantand one 的所有信息ParticipantEntry(类似于 an Orderand one OrderLineItem)应该在哪里实现检查 Participant 是否已经存在的逻辑,如果它不存在,则创建 Participant?
Participant,如果没有找到,则发出AddParticipantCommand一个AddParticipantEntry命令,然后发出包含Participant ID?我需要查询 Saga Data 类的属性来获取列表。它作为序列化对象存储在 SqlPersistance 表的 [Data] 列中。考虑一个场景,我的 SagaData 有一个名为 UserName 的属性,因此我想查询与该用户相关的每个 saga。以一种草率的方式,我可以查询列内容,获取列表,并可以通过如下查询从内容中创建 Saga 对象:
SELECT [Id]
,[Correlation_TaskId]
,[Metadata]
,[Data]
,[PersistenceVersion]
,[SagaTypeVersion]
,[Concurrency]
FROM [myWonderfulDb].[dbo].[MyWonderfulPeristanceTable]
where JSON_VALUE(Data,'$.Username') = 'arthur'
Run Code Online (Sandbox Code Playgroud)
但我正在寻找一种优雅的方法来做到这一点,可能使用 NserviceBus API。PspecialSoftware 文档中描述了 SagaFinder 实现(链接:https://docs.pspecial.net/persistence/sql/saga-finder),但这仅返回一个对象,该对象并不完全适合我的场景。
文档中的实现方式如下:
class SqlServerSagaFinder :
IFindSagas<MySagaData>.Using<MyMessage>
{
public Task<MySagaData> FindBy(MyMessage message, SynchronizedStorageSession session, ReadOnlyContextBag context)
{
return session.GetSagaData<MySagaData>(
context: context,
whereClause: "JSON_VALUE(Data,'$.PropertyPathInJson') = @propertyValue",
appendParameters: (builder, append) =>
{
var parameter = builder();
parameter.ParameterName = "propertyValue";
parameter.Value = message.PropertyValue;
append(parameter);
});
}
}
Run Code Online (Sandbox Code Playgroud)
任何想法表示赞赏。谢谢你!