2017-03-29 8 views
2

TL; DR: で処理するにはどうすればよいですか?1.私は反パターンを作成していますか? 2. CQRSによるクレームチェックを処理する最善の方法は何ですか?クレームチェックはcqrs

私のシステムにはいくつかのエントリポイントがあります(webapiはjsonとxmlで渡されます)。また、固定長ファイルのファイルシステムもあります。

MSMQとSqlサーバーでRebusを使用してメッセージングを管理しています。データは4MBよりも大きくなる可能性があります(私が思うならMSMQの最大メッセージサイズ)。システムがファイルを受信したとき、私はストリームに変換し、以下のようにIAttachmentCommandを実装してコマンドを作成します。私は、(REBUSを使用して)コマンドバスを使用してそれを送信

public interface IAttachmentCommand : ICommand 
{ 
    Stream Attachment { get; } 

    IClaimCheckCommand ToClaimCheck(string attachmentId); 
} 

public interface IClaimCheckCommand : ICommand 
{ 
    string AttachmentId { get; } 
} 

。コマンドのタイプがIAttachmentCommandの場合、私はrebusデータバステーブルに添付ファイルを作成し、元のコマンドでToClaimCheckを使用して新しいIAttachmentCommandを返します。 AttachmentCommandは事実上元のコマンドのカーボンコピーですが、データの代わりにattachmentIdを持つ点が異なります。

私はその後、以下のように私の新しいにattachmentIDと私のREBUSバスに送る呼び出します。これは私が私のコードはズタズタに引っ張られていて幸せだが、動作しているようだ

public void Send<TCommand>(TCommand command) where TCommand : ICommand 
{ 
    if (command is IAttachmentCommand) 
    { 
    var cmd = command as IAttachmentCommand; 
    var task = CreateAttachment(cmd); // method excluded, but persists to Rebus DataBus and returns AttachmentId 
    var claimCheck = task.Result; 
    _activator.Bus.Send(claimCheck); 
    } 
    else 
    { 
    _activator.Bus.Send(command); 
    } 
} 

。私はコマンドを送信したり、集約されたルーツによって生成されたイベントを適用したり、イベントストアなどに保存したりすることができます。

私はwebapiコールまたはファイルシステムからファイルを取り出し、コマンドを作成して送信します私の命令バスで。

別のWindowsサービスでは、これらのメッセージのMSMQを監視するコマンドディスパッチャがあります。メッセージが入ってくると、多くのCommandValidationHandlerを反復してコマンドを検証します。 CommandValidationHandlersは以下を実装:

public interface ICommandValidationHandler<in TCommand> where TCommand : ICommand 
{ 
    ValidationResult Validate(TCommand command); 
} 

ValidationResultは、効果的にエラーのコレクションを返します。これらのエラーは、記録され、コマンド情報とエラーを含むInvalidCommandイベントとして公開されます。これにより、リスンしているすべてのサブスクライバがイベントを受け取ることができます。メールを送信するか、Webサービスなどを呼び出して、理由がある。コマンドが無効な場合、例外がスローされ、プロセスは停止します。

私の懸念は、私はattachmentIdを持っているので、ファイルを取得しなければならないことです。このファイルは、例えばxsdに対して検証されます。

そこから私はオブジェクト(一般的に、トランザクションなどのないメタデータを含むヘッダーを持つ金融取引のコレクション)に逆シリアル化し、オブジェクト内のデータに対して追加の検証を実行する必要があります。

この検証が完了したら、オブジェクト内のトランザクションのコレクションを反復し、コマンドバスを使用してそれらを関連する境界のあるコンテキストに送信し、さらに処理する必要があります。

このケースでは、クレームストアを複数回(各検証ハンドラごとに1回)打つことになりますが(これはバリデータの複合コレクションで解決できますが)、コマンドハンドラ一度検証が行われる。

さまざまなイベントハンドラでは、毎回クレームストアからデータを取得して何度もデシリアライズする必要があるすべてのデータにアクセスする必要があります。

これはコード匂いのようです。最初にすべてのイベントハンドラが完了したら、ファイルをキャッシュしてキャッシュからクリアすることを検討する必要がありますか?

もっと良い提案がありますか?

+0

キャッシングを使用している場合は、キャッシュを無効にする必要がありますか? –

+0

データは不変ですが、キャッシュから削除することができます。たとえば、キャッシュに期限を設定するか、またはメッセージを購読しているすべてのイベントハンドラがそれを受け取った場合、CPUがレコードの1000を超えるとヒットすることがあります。私はそれがキャッシュから削除されている場合、私はそれを読み込むことができます怠惰な方法で、添付ファイルを持っている場合でも、AttachmentIdへの参照を維持することが賢明だろうと思います。 –

+0

キャッシュパターンは良好ですが、キャッシングは、真実の原因が突き抜けるときに無効にする**ハード**の不和を持っています。これがあなたのケースでない場合は、それを使用してください。 –

答えて

1

あなたの問題について私が理解していることは、実際には:「検証ハンドラでclaim storeを読み取るためのキャッシングメカニズムを使用する必要がありますか?」

claim storeのデータは不変なので、必要に応じてキャッシュすることができます。それは不変のデータの美しさです:永遠にキャッシング可能です。

キャッシングメカニズムを実装するには、claim store上にデコレータパターンを使用し、composition rootのキャッシュ済みバージョンにdependency containerで切り替えることができます。このようにして、キャッシュされていないものにいつでも切り替えることができます。

さらにキャッシュすることができます。検証されたデータが変更されず、時間が経ってもそれが繰り返される場合でも、検証結果をキャッシュすることができます。

関連する問題