3

私はそれにまっすぐにカットします。銀行に送信されたファイルを介して、クレジット カードの支払いを自動化しようとしています。カードの支払いは、銀行でリアルタイムに検証されません。銀行は夜通し支払いを処理し、翌日、成功した支払いと失敗した支払いの両方を含む応答ファイルを送信します。

支払いを受け入れるかキャンセルすると、支払い/キャンセルの詳細を含むメッセージが (Bus.Send 経由で) コマンド メッセージ プロセッサに送信される Web アプリがあります。

次に、プロセッサは、すべてのサービスが参照できるようにこれを (Bus.Publish を介して) パブリッシュします。

1 つのサービスで次のことを行う必要があります。

  • 最初のメッセージの受信で物語を開始する
  • 営業終了のタイムアウト要求を発行する
  • 後続のすべてのメッセージを (サガで) 受信したときに追跡します
  • タイムアウトの受信時に、支払いとキャンセルのメッセージを銀行ファイルに変換します。

問題は、List<> が仮想メンバーとして許可されていないため、メッセージのコレクション (またはそれ以外のもの) をサガに格納する方法がわからないことです。

現在のサガ構造は次のとおりです。

public class PaymentRequestCancelledSagaBase : IContainSagaData
    {
        // the following properties are mandatory
        public virtual Guid Id { get; set; }
        public virtual string Originator { get; set; }
        public virtual string OriginalMessageId { get; set; }

        // List of all the received PaymentRequestedMessages
        public virtual List<PaymentRequested> PaymentRequestedMessages;

        // List of all the received PaymentCancelledMessages
        public virtual List<PaymentCancelled> PaymentCancelledMessages;
    }

何かご意見は?

4

1 に答える 1

9

私の考えがUdiらと一致しているかどうかはわかりませんが、サガデータはメッセージに関する非常に軽量なメタデータであると常に理解しており、実際のメッセージデータを多く含むべきではありません.

各支払い要求とそれに対応する承認/キャンセルについてのサガを持つことができますが、銀行が営業日ごとにそれらをすべてまとめてバッチ処理することを要求するか、ファイルごとに固定額を請求すると仮定しましょう。これは一般的です...

その場合、メッセージング システム (NServiceBus) の基礎となる、実際にトランザクション自体を追跡するある種のトランザクション システムを使用するか、使用する必要があります。それらが何らかのタイプのバッチ (つまり、営業日) にグループ化されている場合、バッチには ID が必要です。これは、プロセス全体の状態に関する基本的な情報に加えて、サガが参照する必要があるものです (つまり、銀行からの応答はまだありましたか?)。

サービス バスは、それ自体がシステムではなく、独立したシステムとコンポーネントが相互に通信する方法です。Sagas は実際には ( 経由で) 終了したら削除されることを意図しているMarkAsCompleteため、実際には「永続的な」情報を保存する場所ではありません。

私の世界では、佐賀データは代わりに次のようになります。

public class PaymentProcessingSagaData : IContainSagaData
{
    public virtual Guid Id { get; set; }
    public virtual string Originator { get; set; }
    public virtual string OriginalMessageId { get; set; }

    public virtual int RequestBatchId { get; set; }
    public virtual DateTime? WhenRequestBatchClosed { get; set; }
    public virtual string BankRequestFileName { get; set; }
    public virtual DateTime? WhenRequestFileSent { get; set; }
    public virtual string BankResponseFileName { get; set; }
    public virtual DateTime? WhenResponseFileReceived { get; set; }
    public virtual int PaymentBatchId { get; set; }
}

これは、次のような操作の順序に対応します。

  1. PaymentRequestedバッチを作成/追加してイベントを投稿するアプリにリクエストが送信されます。
  2. サブスクライバーはイベントをピックアップしPaymentRequested、必要に応じて新しいサガを作成してRequestBatchId、サガ相関 ID となる を設定します。次に、営業終了のタイムアウトを設定します。
  3. タイムアウト ハンドラーは、バッチを閉じ、イベントを設定WhenRequestBatchClosedし、公開しPaymentRequestBatchClosedます。
  4. サブスクライバーはPaymentRequestBatchClosedイベントを受け取り、支払いファイルを作成し (sets )、ファイルの準備ができたことをBankRequestFileName示すイベントを発行します。RequestFileAvailable
  5. サブスクライバーはイベントをピックアップしRequestFileAvailable、(たとえば) ファイルを銀行サーバーに FTP 送信し、イベントを更新WhenRequestFileSentして発行するアップロード プロセスを開始しますRequestFileSent
  6. モニタリング プロセス (または別のタイムアウト ハンドラ) は、応答ファイルを検出し、イベントを更新BankResponseFileNameおよびWhenResponseFileReceived発行しResponseFileAvailableます。
  7. サブスクライバーは、イベントResponseFileAvailableを受け取り、ファイルを処理し、支払いバッチを作成し、.PaymentBatchIdPaymentsProcessed

もちろん、必ずしもこれらのWhenDateTime フィールドが必要というわけではありません。どのステップが完了したかを示すブール値フラグを簡単に設定できます。しかし重要なことは、saga がトランザクションデータではなく、トランザクションの状態を追跡していることです。

すべてを物語に詰め込もうとする間違いをしないでください。これは、トランザクション システムの代わりになることを意図したものではなく、すべてをまとめるためのちょっとした接着剤です。

于 2011-10-26T04:52:56.197 に答える