複数のサイト (たとえば、ここまたはここでSagas は、ドメイン イベントをリッスンして反応し、新しいコマンドを実行し、最終的にドメインを変更するなどのメカニズムとして説明されています。
一部のサブスクライバーがイベントに反応する単純なイベント ディスパッチャーと、Saga との間に何か違いはありますか?
Saga は、ドメイン外のイベントによってトリガーされる長期実行プロセスです。そのイベントは、数秒、数分、または数日で発生する可能性があります。
単純なイベント バスとの違いは、Saga は、外部イベントによる「切断された」ワークフローで長時間実行されるプロセスを処理するために永続化できるステート マシンを保持することです。
それを理解する最も簡単な方法は、実際の例です。古典的な「素晴らしいフォーラムへの登録を完了するための確認メールを送信しました」は機能するはずです。
NServiceBus の例:
// data to be persisted to start and resume Saga when needed
public class UserRegistrationSagaData : ISagaEntity
{
public Guid Id { get; set; }
public string Originator { get; set; }
public string OriginalMessageId { get; set; }
public string Email { get; set; }
public int Ticket { get; set; }
}
// the saga itself
public class UserRegistrationSaga :
Saga<UserRegistrationSagaData>,
// tell NServiceBus the Saga is created when RequestRegistration message arrives
ISagaStartedBy<RequestRegistration>,
// tell NServiceBus the Saga is resumed when ConfirmRegistration message arrives
// (user click in the link inside the e-mail)
IMessageHandler<ConfirmRegistration>
{
public override void ConfigureHowToFindSaga() //primary keys of this saga in persistence
{
ConfigureMapping<RequestRegistration>(saga => saga.Email, message => message.Email);
ConfigureMapping<ConfirmRegistration>(saga => saga.Ticket, message => message.Ticket);
}
// when requestRegistrarion arrives this code is executed
public void Handle(RequestRegistration message)
{
// generate new ticket if it has not been generated
if (Data.Ticket == 0)
{
Data.Ticket = NewUserService.CreateTicket();
}
Data.Email = message.Email;
MailSender.Send(message.Email,
"Your registration request",
"Please go to /registration/confirm and enter the following ticket: " + Data.Ticket);
Console.WriteLine("New registration request for email {0} - ticket is {1}", Data.Email, Data.Ticket);
}
// when ConfirmRegistration arrives this code is executed
public void Handle(ConfirmRegistration message)
{
Console.WriteLine("Confirming email {0}", Data.Email);
NewUserService.CreateNewUserAccount(Data.Email);
MailSender.Send(Data.Email,
"Your registration request",
"Your email has been confirmed, and your user account has been created");
// tell NServiceBus that this saga can be cleaned up afterwards
MarkAsComplete();
}
}
}
シンプルな
Bus.Send(new RequestRegistration(...))
つまり、Web コントローラーによって作業を行う必要があります。
単純なイベント バスでこの動作をハード コーディングすると、ドメイン内のステート マシンを醜い方法でシミュレートする必要があります。つまり、ドメイン永続性でユーザー テーブルに「confirmed」ブール フィールドを追加し、システムのユーザー管理モジュールで「confirmed = true」ユーザーをクエリして操作する必要があります。または、永続ドメインに「確認ユーザーの保留中」のテーブルがあります。お分かりいただけると思います。
したがって、Saga は単純なイベント バスのようなものであり、「切断された」長時間実行プロセスが原因で、ドメインとドメインの永続性を状態マシンで汚染しないようにするのに役立ちます。これは、優れた OO 設計における責任の分離にすぎません。
これらの概念を区別するのは紛らわしいので、これは良い質問です。そして、サガはビジネスフローであると述べた回答に同意します。
また、サガは複数の境界付けられたコンテキスト、つまり複数のマイクロサービスまたはモジュールにまたがることができるため、次の 2 つの方法で実装できます。
イベント オーケストレーションは一種のプロセス マネージャーまたはフロー オーケストレーターであり、ビジネス フロー全体をオーケストレーションするために必要な中心的なコンポーネントです。そのため、サガを作成し、複数のマイクロサービスまたはモジュールにまたがるフロー全体を調整して、サガを終了します。
イベント コレオグラフィーははるかに単純で、サガの参加者がイベントを発行およびサブスクライブすることで実行できます。これは、イベント バス、ディスパッチャー、およびサブスクライバーによって実行できます。
したがって、サガ自体は、イベント ディスパッチャーとサブスクライバーを使用して実装できます。違いはサガにあります。発行された/サブスクライブされたイベントは、サガ自体のビジネスフローで意味があるはずです。
私は物事をより簡単にしたことを願っています:D